Merge "Reenable SocksProxyTest"
diff --git a/check-ojluni-files b/check-ojluni-files
new file mode 100755
index 0000000..c0066fc
--- /dev/null
+++ b/check-ojluni-files
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+
+# Copyright (C) 2016 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.
+
+
+##### Script to check whether the files openjdk_java_files.mk match
+##### those in the corresponding directory.
+COMMAND='diff <(for i in $(openjdk_java_files); do echo "\$$i"; done | sort) '
+COMMAND=${COMMAND}'<( find ojluni/src/main/java -type f | grep '\''\.java$$'\'' | sort )'
+
+# Need to do it this nasty way (creating a Makefile on the fly and
+# executing the bash command inside it) as to read the openjdk_java_files
+# variable from an .mk file.
+make -s -f <(cat <<EOF
+include openjdk_java_files.mk
+check_openjdk_java_files: ; /bin/bash -c "$COMMAND"
+EOF)
+
+if [ $? -eq 0 ]; then
+    echo 'No differences found'
+else
+    echo 'Differences found'
+    exit 1
+fi
+
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Character_UnicodeBlockTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Character_UnicodeBlockTest.java
index 792ee3d..9a4a406 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Character_UnicodeBlockTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/Character_UnicodeBlockTest.java
@@ -4,9 +4,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -232,6 +232,14 @@
         assertEquals(Character.UnicodeBlock.SPECIALS, Character.UnicodeBlock.of((char) 0xfff0));
         assertEquals(Character.UnicodeBlock.SPECIALS, Character.UnicodeBlock.of((char) 0xffff));
 
+        // Blocks added in 1.8
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.of((char) 0x08a0));
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.of((char) 0x08ff));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.of((char) 0x1cc0));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.of((char) 0x1ccf));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.of((char) 0xaae0));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.of((char) 0xaaff));
+
         // Negative test: The range [0x0860, 0x08A0) is currently unassigned.
         assertEquals(null, Character.UnicodeBlock.of((char) 0x0860));
         assertEquals(null, Character.UnicodeBlock.of((char) 0x089F));
@@ -489,6 +497,30 @@
         assertEquals(Character.UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B, Character.UnicodeBlock.of(0x100000));
         assertEquals(Character.UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B, Character.UnicodeBlock.of(0x10ffff));
 
+        // Blocks added in 1.8
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.of(0x08a0));
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.of(0x08ff));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.of(0x1cc0));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.of(0x1ccf));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.of(0xaae0));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.of(0xaaff));
+        assertEquals(Character.UnicodeBlock.MEROITIC_HIEROGLYPHS, Character.UnicodeBlock.of(0x10980));
+        assertEquals(Character.UnicodeBlock.MEROITIC_HIEROGLYPHS, Character.UnicodeBlock.of(0x1099f));
+        assertEquals(Character.UnicodeBlock.MEROITIC_CURSIVE, Character.UnicodeBlock.of(0x109a0));
+        assertEquals(Character.UnicodeBlock.MEROITIC_CURSIVE, Character.UnicodeBlock.of(0x109ff));
+        assertEquals(Character.UnicodeBlock.SORA_SOMPENG, Character.UnicodeBlock.of(0x110d0));
+        assertEquals(Character.UnicodeBlock.SORA_SOMPENG, Character.UnicodeBlock.of(0x110ff));
+        assertEquals(Character.UnicodeBlock.CHAKMA, Character.UnicodeBlock.of(0x11100));
+        assertEquals(Character.UnicodeBlock.CHAKMA, Character.UnicodeBlock.of(0x1114f));
+        assertEquals(Character.UnicodeBlock.SHARADA, Character.UnicodeBlock.of(0x11180));
+        assertEquals(Character.UnicodeBlock.SHARADA, Character.UnicodeBlock.of(0x111df));
+        assertEquals(Character.UnicodeBlock.TAKRI, Character.UnicodeBlock.of(0x11680));
+        assertEquals(Character.UnicodeBlock.TAKRI, Character.UnicodeBlock.of(0x116cf));
+        assertEquals(Character.UnicodeBlock.MIAO, Character.UnicodeBlock.of(0x16f00));
+        assertEquals(Character.UnicodeBlock.MIAO, Character.UnicodeBlock.of(0x16f9f));
+        assertEquals(Character.UnicodeBlock.ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS, Character.UnicodeBlock.of(0x1ee00));
+        assertEquals(Character.UnicodeBlock.ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS, Character.UnicodeBlock.of(0x1eeff));
+
         // Negative test: The range [0x0860, 0x08A0) is currently unassigned.
         assertEquals(null, Character.UnicodeBlock.of((char) 0x0860));
         assertEquals(null, Character.UnicodeBlock.of((char) 0x089F));
@@ -793,6 +825,37 @@
         assertEquals(Character.UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B, Character.UnicodeBlock.forName("SUPPLEMENTARY_PRIVATE_USE_AREA_B"));
         assertEquals(Character.UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B, Character.UnicodeBlock.forName("Supplementary Private Use Area-B"));
         assertEquals(Character.UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B, Character.UnicodeBlock.forName("SupplementaryPrivateUseArea-B"));
+
+        // Blocks added in 1.8
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.forName("ARABIC_EXTENDED_A"));
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.forName("arabic extended-A"));
+        assertEquals(Character.UnicodeBlock.ARABIC_EXTENDED_A, Character.UnicodeBlock.forName("ArabicExtended-A"));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.forName("SUNDANESE_SUPPLEMENT"));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.forName("Sundanese Supplement"));
+        assertEquals(Character.UnicodeBlock.SUNDANESE_SUPPLEMENT, Character.UnicodeBlock.forName("SundaneseSupplement"));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.forName("MEETEI_MAYEK_EXTENSIONS"));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.forName("MEETEI MAYEK EXTENSIONS"));
+        assertEquals(Character.UnicodeBlock.MEETEI_MAYEK_EXTENSIONS, Character.UnicodeBlock.forName("MeeteiMayekExtensions"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_HIEROGLYPHS, Character.UnicodeBlock.forName("MEROITIC_HIEROGLYPHS"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_HIEROGLYPHS, Character.UnicodeBlock.forName("MEROITIC HIEROGLYPHS"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_HIEROGLYPHS, Character.UnicodeBlock.forName("MeroiticHieroglyphs"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_CURSIVE, Character.UnicodeBlock.forName("MEROITIC_CURSIVE"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_CURSIVE, Character.UnicodeBlock.forName("MEROITIC CURSIVE"));
+        assertEquals(Character.UnicodeBlock.MEROITIC_CURSIVE, Character.UnicodeBlock.forName("MeroiticCursive"));
+        assertEquals(Character.UnicodeBlock.SORA_SOMPENG, Character.UnicodeBlock.forName("SORA_SOMPENG"));
+        assertEquals(Character.UnicodeBlock.SORA_SOMPENG, Character.UnicodeBlock.forName("SORA SOMPENG"));
+        assertEquals(Character.UnicodeBlock.SORA_SOMPENG, Character.UnicodeBlock.forName("SoraSompeng"));
+        assertEquals(Character.UnicodeBlock.CHAKMA, Character.UnicodeBlock.forName("CHAKMA"));
+        assertEquals(Character.UnicodeBlock.SHARADA, Character.UnicodeBlock.forName("SHARADA"));
+        assertEquals(Character.UnicodeBlock.TAKRI, Character.UnicodeBlock.forName("TAKRI"));
+        assertEquals(Character.UnicodeBlock.MIAO, Character.UnicodeBlock.forName("MIAO"));
+        assertEquals(Character.UnicodeBlock.ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS,
+                     Character.UnicodeBlock.forName("ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS"));
+        assertEquals(Character.UnicodeBlock.ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS,
+                     Character.UnicodeBlock.forName("ARABIC MATHEMATICAL ALPHABETIC SYMBOLS"));
+        assertEquals(Character.UnicodeBlock.ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS,
+                     Character.UnicodeBlock.forName("ArabicMathematicalAlphabeticSymbols"));
+
     }
 
     public void test_forNameLjava_lang_StringExceptions() {
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 5809da3..7e34d44 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -25,6 +25,7 @@
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Locale;
 import junit.framework.TestCase;
 
@@ -547,4 +548,48 @@
         assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
         assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
     }
+
+    public void testJoin_CharSequenceArray() {
+        assertEquals("", String.join("-"));
+        assertEquals("", String.join("-", ""));
+        assertEquals("foo", String.join("-", "foo"));
+        assertEquals("foo---bar---boo", String.join("---", "foo", "bar", "boo"));
+        assertEquals("foobarboo", String.join("", "foo", "bar", "boo"));
+        assertEquals("null-null", String.join("-", null, null));
+        assertEquals("¯\\_(ツ)_/¯", String.join("(ツ)", "¯\\_", "_/¯"));
+    }
+
+    public void testJoin_CharSequenceArray_NPE() {
+        try {
+            String.join(null, "foo", "bar");
+            fail();
+        } catch (NullPointerException expected) {}
+    }
+
+    public void testJoin_Iterable() {
+        ArrayList<String> iterable = new ArrayList<>();
+        assertEquals("", String.join("-", iterable));
+
+        iterable.add("foo");
+        assertEquals("foo", String.join("-", iterable));
+
+        iterable.add("bar");
+        assertEquals("foo...bar", String.join("...", iterable));
+
+        iterable.add("foo");
+        assertEquals("foo-bar-foo", String.join("-", iterable));
+        assertEquals("foobarfoo", String.join("", iterable));
+    }
+
+    public void testJoin_Iterable_NPE() {
+        try {
+            String.join(null, new ArrayList<String>());
+            fail();
+        } catch (NullPointerException expected) {}
+
+        try {
+            String.join("-", (Iterable<String>)null);
+            fail();
+        } catch (NullPointerException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java b/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
index d78456d..a251963 100644
--- a/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
+++ b/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
@@ -1,11 +1,17 @@
-package java.net;
+package libcore.java.net;
 
 import junit.framework.TestCase;
 
 import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketImpl;
+import java.net.SocketException;
+import java.net.SocketAddress;
+import java.net.ServerSocket;
 import java.util.Locale;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Tests for race conditions between {@link ServerSocket#close()} and
@@ -34,16 +40,33 @@
         }
         final ExposedServerSocket serverSocket = new ExposedServerSocket();
         serverSocket.close();
-        try {
-            // Hack: Need to subclass to access the protected constructor without reflection
-            Socket socket = new Socket((SocketImpl) null) { };
-            serverSocket.implAcceptExposedForTest(socket);
-            fail("accepting on a closed socket should throw");
-        } catch (SocketException expected) {
-            // expected
-        } catch (IOException e) {
-            throw new AssertionError(e);
+        // implAccept() on background thread to prevent this test hanging
+        final AtomicReference<Exception> failure = new AtomicReference<>();
+        final CountDownLatch threadFinishedLatch = new CountDownLatch(1);
+        Thread thread = new Thread("implAccept() closed ServerSocket") {
+            public void run() {
+                try {
+                    // Hack: Need to subclass to access the protected constructor without reflection
+                    Socket socket = new Socket((SocketImpl) null) { };
+                    serverSocket.implAcceptExposedForTest(socket);
+                } catch (SocketException expected) {
+                    // pass
+                } catch (IOException|RuntimeException e) {
+                    failure.set(e);
+                } finally {
+                    threadFinishedLatch.countDown();
+                }
+            }
+        };
+        thread.start();
+
+        boolean completed = threadFinishedLatch.await(5, TimeUnit.SECONDS);
+        assertTrue("implAccept didn't throw or return within time limit", completed);
+        Exception e = failure.get();
+        if (e != null) {
+            throw new AssertionError("Unexpected exception", e);
         }
+        thread.join();
     }
 
     /**
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 37fa771..7c5cc42 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -16,15 +16,19 @@
 
 package libcore.java.net;
 
-import com.android.okhttp.AndroidShimResponseCache;
-
 import com.google.mockwebserver.Dispatcher;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
+
+import com.android.okhttp.AndroidShimResponseCache;
+
+import junit.framework.TestCase;
+
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
@@ -35,7 +39,6 @@
 import java.net.CacheResponse;
 import java.net.HttpRetryException;
 import java.net.HttpURLConnection;
-import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.PasswordAuthentication;
 import java.net.ProtocolException;
@@ -82,8 +85,8 @@
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 import libcore.java.security.TestKeyStore;
-import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
 import libcore.javax.net.ssl.TestSSLContext;
+
 import tests.net.DelegatingSocketFactory;
 
 import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
@@ -96,16 +99,18 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.spy;
 
-public final class URLConnectionTest extends AbstractResourceLeakageDetectorTestCase {
+public final class URLConnectionTest extends TestCase {
 
     private MockWebServer server;
     private AndroidShimResponseCache cache;
     private String hostName;
+    private List<TestSSLContext> testSSLContextsToClose;
 
     @Override protected void setUp() throws Exception {
         super.setUp();
         server = new MockWebServer();
         hostName = server.getHostName();
+        testSSLContextsToClose = new ArrayList<>();
     }
 
     @Override protected void tearDown() throws Exception {
@@ -123,6 +128,9 @@
             cache.delete();
             cache = null;
         }
+        for (TestSSLContext testSSLContext : testSSLContextsToClose) {
+            testSSLContext.close();
+        }
         super.tearDown();
     }
 
@@ -521,7 +529,7 @@
     }
 
     public void testConnectViaHttps() throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
@@ -538,7 +546,7 @@
     }
 
     public void testConnectViaHttpsReusingConnections() throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         SSLSocketFactory clientSocketFactory = testSSLContext.clientContext.getSocketFactory();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
@@ -560,7 +568,7 @@
 
     public void testConnectViaHttpsReusingConnectionsDifferentFactories()
             throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
@@ -588,6 +596,7 @@
     public void testConnectViaHttpsToUntrustedServer() throws IOException, InterruptedException {
         TestSSLContext testSSLContext = TestSSLContext.create(TestKeyStore.getClientCA2(),
                                                               TestKeyStore.getServer());
+        testSSLContextsToClose.add(testSSLContext);
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse()); // unused
@@ -666,7 +675,7 @@
     }
 
     private void testConnectViaDirectProxyToHttps(ProxyConfig proxyConfig) throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
@@ -704,7 +713,7 @@
      * through a proxy. http://b/3097277
      */
     private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
@@ -737,7 +746,7 @@
      * Tolerate bad https proxy response when using HttpResponseCache. http://b/6754912
      */
     public void testConnectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         initResponseCache();
 
@@ -912,7 +921,7 @@
     public void testProxyConnectIncludesProxyHeadersOnly()
             throws IOException, InterruptedException {
         RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
         server.enqueue(new MockResponse()
@@ -945,7 +954,7 @@
 
     public void testProxyAuthenticateOnConnect() throws Exception {
         Authenticator.setDefault(new SimpleAuthenticator());
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
         server.enqueue(new MockResponse()
                 .setResponseCode(407)
@@ -980,7 +989,7 @@
     // Don't disconnect after building a tunnel with CONNECT
     // http://code.google.com/p/android/issues/detail?id=37221
     public void testProxyWithConnectionClose() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
         server.enqueue(new MockResponse()
                 .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)
@@ -1449,7 +1458,7 @@
      * http://code.google.com/p/android/issues/detail?id=12860
      */
     private void testSecureStreamingPost(StreamingMode streamingMode) throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse().setBody("Success!"));
         server.play();
@@ -1660,7 +1669,7 @@
     }
 
     public void testRedirectedOnHttps() throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse()
                 .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
@@ -1682,7 +1691,7 @@
     }
 
     public void testNotRedirectedFromHttpsToHttp() throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse()
                 .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
@@ -1919,7 +1928,7 @@
         SSLSocketFactory defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
         HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
         try {
-            TestSSLContext testSSLContext = TestSSLContext.create();
+            TestSSLContext testSSLContext = createDefaultTestSSLContext();
             server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
             server.enqueue(new MockResponse().setBody("ABC"));
             server.enqueue(new MockResponse().setBody("DEF"));
@@ -2681,7 +2690,7 @@
     }
 
     public void testSslFallback_allSupportedProtocols() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         String[] allSupportedProtocols = { "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3" };
         SSLSocketFactory serverSocketFactory =
@@ -2734,7 +2743,7 @@
     }
 
     public void testSslFallback_defaultProtocols() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
 
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
@@ -2784,7 +2793,7 @@
     }
 
     public void testInspectSslBeforeConnect() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse());
         server.play();
@@ -2819,7 +2828,7 @@
      * http://code.google.com/p/android/issues/detail?id=24431
      */
     public void testInspectSslAfterConnect() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
+        TestSSLContext testSSLContext = createDefaultTestSSLContext();
         server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
         server.enqueue(new MockResponse());
         server.play();
@@ -2838,45 +2847,6 @@
         }
     }
 
-    // http://b/26769689
-    public void testSSLSocketFactoryWithIpv6LiteralHostname() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse());
-        server.play();
-
-        final AtomicReference<String> hostNameUsed = new AtomicReference<>(null);
-
-        SSLSocketFactory factory = new DelegatingSSLSocketFactory(
-                testSSLContext.clientContext.getSocketFactory()) {
-            @Override
-            public SSLSocket createSocket(Socket s, String host, int port, boolean autoClose)
-                    throws IOException {
-                hostNameUsed.set(host);
-                return (SSLSocket) delegate.createSocket(s, host, port, autoClose);
-            }
-        };
-
-        HttpsURLConnection urlConnection = (HttpsURLConnection)
-                new URL("https://[" + Inet6Address.getLoopbackAddress().getHostAddress() + "]:"
-                        + server.getPort() + "/").openConnection();
-        urlConnection.setSSLSocketFactory(factory);
-        try {
-            urlConnection.connect();
-            fail();
-        } catch (IOException expected) {
-            // We expect the connection to fail with a cert validation exception because we're
-            // using a literal address.
-        } finally {
-            urlConnection.disconnect();
-        }
-
-        // Note that the square brackets around the literal address were crucial. Whatsapp
-        // wouldn't function properly without them.
-        assertEquals("[" + Inet6Address.getLoopbackAddress().getHostAddress() + "]",
-                hostNameUsed.get());
-    }
-
     /**
      * Returns a gzipped copy of {@code bytes}.
      */
@@ -2919,6 +2889,12 @@
         return new HashSet<String>(Arrays.asList(elements));
     }
 
+    private TestSSLContext createDefaultTestSSLContext() {
+        TestSSLContext result = TestSSLContext.create();
+        testSSLContextsToClose.add(result);
+        return result;
+    }
+
     enum TransferKind {
         CHUNKED() {
             @Override void setBody(MockResponse response, byte[] content, int chunkSize)
diff --git a/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java b/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java
deleted file mode 100755
index b1a08ce..0000000
--- a/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2007, 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 com.sun.net.ssl.internal.ssl;
-
-import sun.security.ssl.SunJSSE;
-
-/**
- * Main class for the SunJSSE provider. The actual code was moved to the
- * class sun.security.ssl.SunJSSE, but for backward compatibility we
- * continue to use this class as the main Provider class.
- */
-public final class Provider extends SunJSSE {
-
-    private static final long serialVersionUID = 3231825739635378733L;
-
-    // standard constructor
-    public Provider() {
-        super();
-    }
-
-    // prefered constructor to enable FIPS mode at runtime
-    public Provider(java.security.Provider cryptoProvider) {
-        super(cryptoProvider);
-    }
-
-    // constructor to enable FIPS mode from java.security file
-    public Provider(String cryptoProvider) {
-        super(cryptoProvider);
-    }
-
-    // public for now, but we may want to change it or not document it.
-    public static synchronized boolean isFIPS() {
-        return SunJSSE.isFIPS();
-    }
-
-    /**
-     * Installs the JSSE provider.
-     */
-    public static synchronized void install() {
-        /* nop. Remove this method in the future. */
-    }
-
-}
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
old mode 100755
new mode 100644
index aa71ca4..383a358
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2010, 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
@@ -26,6 +26,7 @@
 
 package java.lang;
 
+import sun.misc.FloatingDecimal;
 import java.util.Arrays;
 
 /**
@@ -35,12 +36,16 @@
  * particular sequence of characters, but the length and content of the
  * sequence can be changed through certain method calls.
  *
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
  * @author      Michael McCloskey
  * @author      Martin Buchholz
  * @author      Ulf Zibis
  * @since       1.5
  */
-abstract class AbstractStringBuilder implements CharSequence {
+abstract class AbstractStringBuilder implements Appendable, CharSequence {
     /**
      * The value is used for character storage.
      */
@@ -70,6 +75,7 @@
      * @return  the length of the sequence of characters currently
      *          represented by this object
      */
+    @Override
     public int length() {
         return count;
     }
@@ -91,11 +97,13 @@
      * array is allocated with greater capacity. The new capacity is the
      * larger of:
      * <ul>
-     * <li>The <code>minimumCapacity</code> argument.
-     * <li>Twice the old capacity, plus <code>2</code>.
+     * <li>The {@code minimumCapacity} argument.
+     * <li>Twice the old capacity, plus {@code 2}.
      * </ul>
-     * If the <code>minimumCapacity</code> argument is nonpositive, this
+     * If the {@code minimumCapacity} argument is nonpositive, this
      * method takes no action and simply returns.
+     * Note that subsequent operations on this object can reduce the
+     * actual capacity below that requested here.
      *
      * @param   minimumCapacity   the minimum desired capacity.
      */
@@ -108,7 +116,7 @@
      * This method has the same contract as ensureCapacity, but is
      * never synchronized.
      */
-    void ensureCapacityInternal(int minimumCapacity) {
+    private void ensureCapacityInternal(int minimumCapacity) {
         // overflow-conscious code
         if (minimumCapacity - value.length > 0)
             expandCapacity(minimumCapacity);
@@ -147,26 +155,26 @@
      * Sets the length of the character sequence.
      * The sequence is changed to a new character sequence
      * whose length is specified by the argument. For every nonnegative
-     * index <i>k</i> less than <code>newLength</code>, the character at
+     * index <i>k</i> less than {@code newLength}, the character at
      * index <i>k</i> in the new character sequence is the same as the
      * character at index <i>k</i> in the old sequence if <i>k</i> is less
      * than the length of the old character sequence; otherwise, it is the
-     * null character <code>'&#92;u0000'</code>.
+     * null character {@code '\u005Cu0000'}.
      *
-     * In other words, if the <code>newLength</code> argument is less than
+     * In other words, if the {@code newLength} argument is less than
      * the current length, the length is changed to the specified length.
      * <p>
-     * If the <code>newLength</code> argument is greater than or equal
+     * If the {@code newLength} argument is greater than or equal
      * to the current length, sufficient null characters
-     * (<code>'&#92;u0000'</code>) are appended so that
-     * length becomes the <code>newLength</code> argument.
+     * ({@code '\u005Cu0000'}) are appended so that
+     * length becomes the {@code newLength} argument.
      * <p>
-     * The <code>newLength</code> argument must be greater than or equal
-     * to <code>0</code>.
+     * The {@code newLength} argument must be greater than or equal
+     * to {@code 0}.
      *
      * @param      newLength   the new length
      * @throws     IndexOutOfBoundsException  if the
-     *               <code>newLength</code> argument is negative.
+     *               {@code newLength} argument is negative.
      */
     public void setLength(int newLength) {
         if (newLength < 0)
@@ -174,30 +182,30 @@
         ensureCapacityInternal(newLength);
 
         if (count < newLength) {
-            for (; count < newLength; count++)
-                value[count] = '\0';
-        } else {
-            count = newLength;
+            Arrays.fill(value, count, newLength, '\0');
         }
+
+        count = newLength;
     }
 
     /**
-     * Returns the <code>char</code> value in this sequence at the specified index.
-     * The first <code>char</code> value is at index <code>0</code>, the next at index
-     * <code>1</code>, and so on, as in array indexing.
+     * Returns the {@code char} value in this sequence at the specified index.
+     * The first {@code char} value is at index {@code 0}, the next at index
+     * {@code 1}, and so on, as in array indexing.
      * <p>
      * The index argument must be greater than or equal to
-     * <code>0</code>, and less than the length of this sequence.
+     * {@code 0}, and less than the length of this sequence.
      *
-     * <p>If the <code>char</code> value specified by the index is a
+     * <p>If the {@code char} value specified by the index is a
      * <a href="Character.html#unicode">surrogate</a>, the surrogate
      * value is returned.
      *
-     * @param      index   the index of the desired <code>char</code> value.
-     * @return     the <code>char</code> value at the specified index.
-     * @throws     IndexOutOfBoundsException  if <code>index</code> is
-     *             negative or greater than or equal to <code>length()</code>.
+     * @param      index   the index of the desired {@code char} value.
+     * @return     the {@code char} value at the specified index.
+     * @throws     IndexOutOfBoundsException  if {@code index} is
+     *             negative or greater than or equal to {@code length()}.
      */
+    @Override
     public char charAt(int index) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
@@ -206,22 +214,22 @@
 
     /**
      * Returns the character (Unicode code point) at the specified
-     * index. The index refers to <code>char</code> values
-     * (Unicode code units) and ranges from <code>0</code> to
-     * {@link #length()}<code> - 1</code>.
+     * index. The index refers to {@code char} values
+     * (Unicode code units) and ranges from {@code 0} to
+     * {@link #length()}{@code  - 1}.
      *
-     * <p> If the <code>char</code> value specified at the given index
+     * <p> If the {@code char} value specified at the given index
      * is in the high-surrogate range, the following index is less
      * than the length of this sequence, and the
-     * <code>char</code> value at the following index is in the
+     * {@code char} value at the following index is in the
      * low-surrogate range, then the supplementary code point
      * corresponding to this surrogate pair is returned. Otherwise,
-     * the <code>char</code> value at the given index is returned.
+     * the {@code char} value at the given index is returned.
      *
-     * @param      index the index to the <code>char</code> values
+     * @param      index the index to the {@code char} values
      * @return     the code point value of the character at the
-     *             <code>index</code>
-     * @exception  IndexOutOfBoundsException  if the <code>index</code>
+     *             {@code index}
+     * @exception  IndexOutOfBoundsException  if the {@code index}
      *             argument is negative or not less than the length of this
      *             sequence.
      */
@@ -229,27 +237,27 @@
         if ((index < 0) || (index >= count)) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointAt(value, index);
+        return Character.codePointAtImpl(value, index, count);
     }
 
     /**
      * Returns the character (Unicode code point) before the specified
-     * index. The index refers to <code>char</code> values
-     * (Unicode code units) and ranges from <code>1</code> to {@link
+     * index. The index refers to {@code char} values
+     * (Unicode code units) and ranges from {@code 1} to {@link
      * #length()}.
      *
-     * <p> If the <code>char</code> value at <code>(index - 1)</code>
-     * is in the low-surrogate range, <code>(index - 2)</code> is not
-     * negative, and the <code>char</code> value at <code>(index -
-     * 2)</code> is in the high-surrogate range, then the
+     * <p> If the {@code char} value at {@code (index - 1)}
+     * is in the low-surrogate range, {@code (index - 2)} is not
+     * negative, and the {@code char} value at {@code (index -
+     * 2)} is in the high-surrogate range, then the
      * supplementary code point value of the surrogate pair is
-     * returned. If the <code>char</code> value at <code>index -
-     * 1</code> is an unpaired low-surrogate or a high-surrogate, the
+     * returned. If the {@code char} value at {@code index -
+     * 1} is an unpaired low-surrogate or a high-surrogate, the
      * surrogate value is returned.
      *
      * @param     index the index following the code point that should be returned
      * @return    the Unicode code point value before the given index.
-     * @exception IndexOutOfBoundsException if the <code>index</code>
+     * @exception IndexOutOfBoundsException if the {@code index}
      *            argument is less than 1 or greater than the length
      *            of this sequence.
      */
@@ -258,28 +266,28 @@
         if ((i < 0) || (i >= count)) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBefore(value, index);
+        return Character.codePointBeforeImpl(value, index, 0);
     }
 
     /**
      * Returns the number of Unicode code points in the specified text
      * range of this sequence. The text range begins at the specified
-     * <code>beginIndex</code> and extends to the <code>char</code> at
-     * index <code>endIndex - 1</code>. Thus the length (in
-     * <code>char</code>s) of the text range is
-     * <code>endIndex-beginIndex</code>. Unpaired surrogates within
+     * {@code beginIndex} and extends to the {@code char} at
+     * index {@code endIndex - 1}. Thus the length (in
+     * {@code char}s) of the text range is
+     * {@code endIndex-beginIndex}. Unpaired surrogates within
      * this sequence count as one code point each.
      *
-     * @param beginIndex the index to the first <code>char</code> of
+     * @param beginIndex the index to the first {@code char} of
      * the text range.
-     * @param endIndex the index after the last <code>char</code> of
+     * @param endIndex the index after the last {@code char} of
      * the text range.
      * @return the number of Unicode code points in the specified text
      * range
      * @exception IndexOutOfBoundsException if the
-     * <code>beginIndex</code> is negative, or <code>endIndex</code>
+     * {@code beginIndex} is negative, or {@code endIndex}
      * is larger than the length of this sequence, or
-     * <code>beginIndex</code> is larger than <code>endIndex</code>.
+     * {@code beginIndex} is larger than {@code endIndex}.
      */
     public int codePointCount(int beginIndex, int endIndex) {
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -290,22 +298,22 @@
 
     /**
      * Returns the index within this sequence that is offset from the
-     * given <code>index</code> by <code>codePointOffset</code> code
+     * given {@code index} by {@code codePointOffset} code
      * points. Unpaired surrogates within the text range given by
-     * <code>index</code> and <code>codePointOffset</code> count as
+     * {@code index} and {@code codePointOffset} count as
      * one code point each.
      *
      * @param index the index to be offset
      * @param codePointOffset the offset in code points
      * @return the index within this sequence
-     * @exception IndexOutOfBoundsException if <code>index</code>
+     * @exception IndexOutOfBoundsException if {@code index}
      *   is negative or larger then the length of this sequence,
-     *   or if <code>codePointOffset</code> is positive and the subsequence
-     *   starting with <code>index</code> has fewer than
-     *   <code>codePointOffset</code> code points,
-     *   or if <code>codePointOffset</code> is negative and the subsequence
-     *   before <code>index</code> has fewer than the absolute value of
-     *   <code>codePointOffset</code> code points.
+     *   or if {@code codePointOffset} is positive and the subsequence
+     *   starting with {@code index} has fewer than
+     *   {@code codePointOffset} code points,
+     *   or if {@code codePointOffset} is negative and the subsequence
+     *   before {@code index} has fewer than the absolute value of
+     *   {@code codePointOffset} code points.
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
         if (index < 0 || index > count) {
@@ -317,32 +325,30 @@
 
     /**
      * Characters are copied from this sequence into the
-     * destination character array <code>dst</code>. The first character to
-     * be copied is at index <code>srcBegin</code>; the last character to
-     * be copied is at index <code>srcEnd-1</code>. The total number of
-     * characters to be copied is <code>srcEnd-srcBegin</code>. The
-     * characters are copied into the subarray of <code>dst</code> starting
-     * at index <code>dstBegin</code> and ending at index:
-     * <p><blockquote><pre>
+     * destination character array {@code dst}. The first character to
+     * be copied is at index {@code srcBegin}; the last character to
+     * be copied is at index {@code srcEnd-1}. The total number of
+     * characters to be copied is {@code srcEnd-srcBegin}. The
+     * characters are copied into the subarray of {@code dst} starting
+     * at index {@code dstBegin} and ending at index:
+     * <pre>{@code
      * dstbegin + (srcEnd-srcBegin) - 1
-     * </pre></blockquote>
+     * }</pre>
      *
      * @param      srcBegin   start copying at this offset.
      * @param      srcEnd     stop copying at this offset.
      * @param      dst        the array to copy the data into.
-     * @param      dstBegin   offset into <code>dst</code>.
-     * @throws     NullPointerException if <code>dst</code> is
-     *             <code>null</code>.
+     * @param      dstBegin   offset into {@code dst}.
      * @throws     IndexOutOfBoundsException  if any of the following is true:
      *             <ul>
-     *             <li><code>srcBegin</code> is negative
-     *             <li><code>dstBegin</code> is negative
-     *             <li>the <code>srcBegin</code> argument is greater than
-     *             the <code>srcEnd</code> argument.
-     *             <li><code>srcEnd</code> is greater than
-     *             <code>this.length()</code>.
-     *             <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
-     *             <code>dst.length</code>
+     *             <li>{@code srcBegin} is negative
+     *             <li>{@code dstBegin} is negative
+     *             <li>the {@code srcBegin} argument is greater than
+     *             the {@code srcEnd} argument.
+     *             <li>{@code srcEnd} is greater than
+     *             {@code this.length()}.
+     *             <li>{@code dstBegin+srcEnd-srcBegin} is greater than
+     *             {@code dst.length}
      *             </ul>
      */
     public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
@@ -357,18 +363,18 @@
     }
 
     /**
-     * The character at the specified index is set to <code>ch</code>. This
+     * The character at the specified index is set to {@code ch}. This
      * sequence is altered to represent a new character sequence that is
      * identical to the old character sequence, except that it contains the
-     * character <code>ch</code> at position <code>index</code>.
+     * character {@code ch} at position {@code index}.
      * <p>
      * The index argument must be greater than or equal to
-     * <code>0</code>, and less than the length of this sequence.
+     * {@code 0}, and less than the length of this sequence.
      *
      * @param      index   the index of the character to modify.
      * @param      ch      the new character.
-     * @throws     IndexOutOfBoundsException  if <code>index</code> is
-     *             negative or greater than or equal to <code>length()</code>.
+     * @throws     IndexOutOfBoundsException  if {@code index} is
+     *             negative or greater than or equal to {@code length()}.
      */
     public void setCharAt(int index, char ch) {
         if ((index < 0) || (index >= count))
@@ -412,10 +418,11 @@
      * @hide
      */
     public AbstractStringBuilder append(String str) {
-        if (str == null) str = "null";
+        if (str == null)
+            return appendNull();
         int len = str.length();
         ensureCapacityInternal(count + len);
-        str.getCharsNoCheck(0, len, value, count);
+        str.getChars(0, len, value, count);
         count += len;
         return this;
     }
@@ -424,7 +431,7 @@
     /** @hide */
     public AbstractStringBuilder append(StringBuffer sb) {
         if (sb == null)
-            return append("null");
+            return appendNull();
         int len = sb.length();
         ensureCapacityInternal(count + len);
         sb.getChars(0, len, value, count);
@@ -432,18 +439,46 @@
         return this;
     }
 
+    /**
+     * @since 1.8
+     * @hide
+     */
+    AbstractStringBuilder append(AbstractStringBuilder asb) {
+        if (asb == null)
+            return appendNull();
+        int len = asb.length();
+        ensureCapacityInternal(count + len);
+        asb.getChars(0, len, value, count);
+        count += len;
+        return this;
+    }
+
     // Documentation in subclasses because of synchro difference
     /** @hide */
+    @Override
     public AbstractStringBuilder append(CharSequence s) {
         if (s == null)
-            s = "null";
+            return appendNull();
         if (s instanceof String)
             return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
+        if (s instanceof AbstractStringBuilder)
+            return this.append((AbstractStringBuilder)s);
+
         return this.append(s, 0, s.length());
     }
 
+    private AbstractStringBuilder appendNull() {
+        int c = count;
+        ensureCapacityInternal(c + 4);
+        final char[] value = this.value;
+        value[c++] = 'n';
+        value[c++] = 'u';
+        value[c++] = 'l';
+        value[c++] = 'l';
+        count = c;
+        return this;
+    }
+
     /**
      * Appends a subsequence of the specified {@code CharSequence} to this
      * sequence.
@@ -474,6 +509,7 @@
      *             {@code end} is greater than {@code s.length()}
      * @hide
      */
+    @Override
     public AbstractStringBuilder append(CharSequence s, int start, int end) {
         if (s == null)
             s = "null";
@@ -483,16 +519,8 @@
                 + s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        if (s instanceof String) {
-            ((String) s).getCharsNoCheck(start, end, value, count);
-        } else if (s instanceof AbstractStringBuilder) {
-            AbstractStringBuilder other = (AbstractStringBuilder) s;
-            System.arraycopy(other.value, start, value, count, len);
-        } else {
-            for (int i = start, j = count; i < end; i++, j++) {
-                value[j] = s.charAt(i);
-            }
-        }
+        for (int i = start, j = count; i < end; i++, j++)
+            value[j] = s.charAt(i);
         count += len;
         return this;
     }
@@ -569,19 +597,17 @@
     public AbstractStringBuilder append(boolean b) {
         if (b) {
             ensureCapacityInternal(count + 4);
-            value[count] = 't';
-            value[count+1] = 'r';
-            value[count+2] = 'u';
-            value[count+3] = 'e';
-            count += 4;
+            value[count++] = 't';
+            value[count++] = 'r';
+            value[count++] = 'u';
+            value[count++] = 'e';
         } else {
             ensureCapacityInternal(count + 5);
-            value[count] = 'f';
-            value[count+1] = 'a';
-            value[count+2] = 'l';
-            value[count+3] = 's';
-            value[count+4] = 'e';
-            count += 5;
+            value[count++] = 'f';
+            value[count++] = 'a';
+            value[count++] = 'l';
+            value[count++] = 's';
+            value[count++] = 'e';
         }
         return this;
     }
@@ -602,6 +628,7 @@
      * @return  a reference to this object.
      * @hide
      */
+    @Override
     public AbstractStringBuilder append(char c) {
         ensureCapacityInternal(count + 1);
         value[count++] = c;
@@ -676,9 +703,7 @@
      * @hide
      */
     public AbstractStringBuilder append(float f) {
-        FloatingDecimal.getThreadLocalInstance()
-            .loadFloat(f)
-            .appendTo(this);
+        FloatingDecimal.appendTo(f,this);
         return this;
     }
 
@@ -696,9 +721,7 @@
      * @hide
      */
     public AbstractStringBuilder append(double d) {
-        FloatingDecimal.getThreadLocalInstance()
-            .loadDouble(d)
-            .appendTo(this);
+        FloatingDecimal.appendTo(d,this);
         return this;
     }
 
@@ -770,21 +793,21 @@
     }
 
     /**
-     * Removes the <code>char</code> at the specified position in this
-     * sequence. This sequence is shortened by one <code>char</code>.
+     * Removes the {@code char} at the specified position in this
+     * sequence. This sequence is shortened by one {@code char}.
      *
      * <p>Note: If the character at the given index is a supplementary
      * character, this method does not remove the entire character. If
      * correct handling of supplementary characters is required,
-     * determine the number of <code>char</code>s to remove by calling
-     * <code>Character.charCount(thisSequence.codePointAt(index))</code>,
-     * where <code>thisSequence</code> is this sequence.
+     * determine the number of {@code char}s to remove by calling
+     * {@code Character.charCount(thisSequence.codePointAt(index))},
+     * where {@code thisSequence} is this sequence.
      *
-     * @param       index  Index of <code>char</code> to remove
+     * @param       index  Index of {@code char} to remove
      * @return      This object.
-     * @throws      StringIndexOutOfBoundsException  if the <code>index</code>
+     * @throws      StringIndexOutOfBoundsException  if the {@code index}
      *              is negative or greater than or equal to
-     *              <code>length()</code>.
+     *              {@code length()}.
      * @hide
      */
     public AbstractStringBuilder deleteCharAt(int index) {
@@ -797,12 +820,12 @@
 
     /**
      * Replaces the characters in a substring of this sequence
-     * with characters in the specified <code>String</code>. The substring
-     * begins at the specified <code>start</code> and extends to the character
-     * at index <code>end - 1</code> or to the end of the
+     * with characters in the specified {@code String}. The substring
+     * begins at the specified {@code start} and extends to the character
+     * at index {@code end - 1} or to the end of the
      * sequence if no such character exists. First the
      * characters in the substring are removed and then the specified
-     * <code>String</code> is inserted at <code>start</code>. (This
+     * {@code String} is inserted at {@code start}. (This
      * sequence will be lengthened to accommodate the
      * specified String if necessary.)
      *
@@ -810,9 +833,9 @@
      * @param      end      The ending index, exclusive.
      * @param      str   String that will replace previous contents.
      * @return     This object.
-     * @throws     StringIndexOutOfBoundsException  if <code>start</code>
-     *             is negative, greater than <code>length()</code>, or
-     *             greater than <code>end</code>.
+     * @throws     StringIndexOutOfBoundsException  if {@code start}
+     *             is negative, greater than {@code length()}, or
+     *             greater than {@code end}.
      * @hide
      */
     public AbstractStringBuilder replace(int start, int end, String str) {
@@ -830,20 +853,20 @@
         ensureCapacityInternal(newCount);
 
         System.arraycopy(value, end, value, start + len, count - end);
-        str.getCharsNoCheck(0, len, value, start);
+        str.getChars(value, start);
         count = newCount;
         return this;
     }
 
     /**
-     * Returns a new <code>String</code> that contains a subsequence of
+     * Returns a new {@code String} that contains a subsequence of
      * characters currently contained in this character sequence. The
      * substring begins at the specified index and extends to the end of
      * this sequence.
      *
      * @param      start    The beginning index, inclusive.
      * @return     The new string.
-     * @throws     StringIndexOutOfBoundsException  if <code>start</code> is
+     * @throws     StringIndexOutOfBoundsException  if {@code start} is
      *             less than zero, or greater than the length of this object.
      */
     public String substring(int start) {
@@ -855,44 +878,45 @@
      *
      * <p> An invocation of this method of the form
      *
-     * <blockquote><pre>
-     * sb.subSequence(begin,&nbsp;end)</pre></blockquote>
+     * <pre>{@code
+     * sb.subSequence(begin,&nbsp;end)}</pre>
      *
      * behaves in exactly the same way as the invocation
      *
-     * <blockquote><pre>
-     * sb.substring(begin,&nbsp;end)</pre></blockquote>
+     * <pre>{@code
+     * sb.substring(begin,&nbsp;end)}</pre>
      *
      * This method is provided so that this class can
-     * implement the {@link CharSequence} interface. </p>
+     * implement the {@link CharSequence} interface.
      *
      * @param      start   the start index, inclusive.
      * @param      end     the end index, exclusive.
      * @return     the specified subsequence.
      *
      * @throws  IndexOutOfBoundsException
-     *          if <tt>start</tt> or <tt>end</tt> are negative,
-     *          if <tt>end</tt> is greater than <tt>length()</tt>,
-     *          or if <tt>start</tt> is greater than <tt>end</tt>
+     *          if {@code start} or {@code end} are negative,
+     *          if {@code end} is greater than {@code length()},
+     *          or if {@code start} is greater than {@code end}
      * @spec JSR-51
      */
+    @Override
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
     }
 
     /**
-     * Returns a new <code>String</code> that contains a subsequence of
+     * Returns a new {@code String} that contains a subsequence of
      * characters currently contained in this sequence. The
-     * substring begins at the specified <code>start</code> and
-     * extends to the character at index <code>end - 1</code>.
+     * substring begins at the specified {@code start} and
+     * extends to the character at index {@code end - 1}.
      *
      * @param      start    The beginning index, inclusive.
      * @param      end      The ending index, exclusive.
      * @return     The new string.
-     * @throws     StringIndexOutOfBoundsException  if <code>start</code>
-     *             or <code>end</code> are negative or greater than
-     *             <code>length()</code>, or <code>start</code> is
-     *             greater than <code>end</code>.
+     * @throws     StringIndexOutOfBoundsException  if {@code start}
+     *             or {@code end} are negative or greater than
+     *             {@code length()}, or {@code start} is
+     *             greater than {@code end}.
      */
     public String substring(int start, int end) {
         if (start < 0)
@@ -1006,7 +1030,7 @@
         int len = str.length();
         ensureCapacityInternal(count + len);
         System.arraycopy(value, offset, value, offset + len, count - offset);
-        str.getCharsNoCheck(0, len, value, offset);
+        str.getChars(value, offset);
         count += len;
         return this;
     }
@@ -1294,18 +1318,16 @@
      * Returns the index within this string of the first occurrence of the
      * specified substring. The integer returned is the smallest value
      * <i>k</i> such that:
-     * <blockquote><pre>
+     * <pre>{@code
      * this.toString().startsWith(str, <i>k</i>)
-     * </pre></blockquote>
-     * is <code>true</code>.
+     * }</pre>
+     * is {@code true}.
      *
      * @param   str   any string.
      * @return  if the string argument occurs as a substring within this
      *          object, then the index of the first character of the first
      *          such substring is returned; if it does not occur as a
-     *          substring, <code>-1</code> is returned.
-     * @throws  java.lang.NullPointerException if <code>str</code> is
-     *          <code>null</code>.
+     *          substring, {@code -1} is returned.
      */
     public int indexOf(String str) {
         return indexOf(str, 0);
@@ -1314,19 +1336,17 @@
     /**
      * Returns the index within this string of the first occurrence of the
      * specified substring, starting at the specified index.  The integer
-     * returned is the smallest value <tt>k</tt> for which:
-     * <blockquote><pre>
-     *     k >= Math.min(fromIndex, str.length()) &&
+     * returned is the smallest value {@code k} for which:
+     * <pre>{@code
+     *     k >= Math.min(fromIndex, this.length()) &&
      *                   this.toString().startsWith(str, k)
-     * </pre></blockquote>
+     * }</pre>
      * If no such value of <i>k</i> exists, then -1 is returned.
      *
      * @param   str         the substring for which to search.
      * @param   fromIndex   the index from which to start the search.
      * @return  the index within this string of the first occurrence of the
      *          specified substring, starting at the specified index.
-     * @throws  java.lang.NullPointerException if <code>str</code> is
-     *            <code>null</code>.
      */
     public int indexOf(String str, int fromIndex) {
         return String.indexOf(value, 0, count,
@@ -1336,20 +1356,18 @@
     /**
      * Returns the index within this string of the rightmost occurrence
      * of the specified substring.  The rightmost empty string "" is
-     * considered to occur at the index value <code>this.length()</code>.
+     * considered to occur at the index value {@code this.length()}.
      * The returned index is the largest value <i>k</i> such that
-     * <blockquote><pre>
+     * <pre>{@code
      * this.toString().startsWith(str, k)
-     * </pre></blockquote>
+     * }</pre>
      * is true.
      *
      * @param   str   the substring to search for.
      * @return  if the string argument occurs one or more times as a substring
      *          within this object, then the index of the first character of
      *          the last such substring is returned. If it does not occur as
-     *          a substring, <code>-1</code> is returned.
-     * @throws  java.lang.NullPointerException  if <code>str</code> is
-     *          <code>null</code>.
+     *          a substring, {@code -1} is returned.
      */
     public int lastIndexOf(String str) {
         return lastIndexOf(str, count);
@@ -1359,22 +1377,20 @@
      * Returns the index within this string of the last occurrence of the
      * specified substring. The integer returned is the largest value <i>k</i>
      * such that:
-     * <blockquote><pre>
-     *     k <= Math.min(fromIndex, str.length()) &&
+     * <pre>{@code
+     *     k <= Math.min(fromIndex, this.length()) &&
      *                   this.toString().startsWith(str, k)
-     * </pre></blockquote>
+     * }</pre>
      * If no such value of <i>k</i> exists, then -1 is returned.
      *
      * @param   str         the substring to search for.
      * @param   fromIndex   the index to start the search from.
      * @return  the index within this sequence of the last occurrence of the
      *          specified substring.
-     * @throws  java.lang.NullPointerException if <code>str</code> is
-     *          <code>null</code>.
      */
     public int lastIndexOf(String str, int fromIndex) {
         return String.lastIndexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+                                  str.toCharArray(), 0, str.length(), fromIndex);
     }
 
     /**
@@ -1385,8 +1401,8 @@
      * is never reversed.
      *
      * Let <i>n</i> be the character length of this character sequence
-     * (not the length in <code>char</code> values) just prior to
-     * execution of the <code>reverse</code> method. Then the
+     * (not the length in {@code char} values) just prior to
+     * execution of the {@code reverse} method. Then the
      * character at index <i>k</i> in the new character sequence is
      * equal to the character at index <i>n-k-1</i> in the old
      * character sequence.
@@ -1394,56 +1410,61 @@
      * <p>Note that the reverse operation may result in producing
      * surrogate pairs that were unpaired low-surrogates and
      * high-surrogates before the operation. For example, reversing
-     * "&#92;uDC00&#92;uD800" produces "&#92;uD800&#92;uDC00" which is
+     * "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
      * a valid surrogate pair.
      *
      * @return  a reference to this object.
      * @hide
      */
     public AbstractStringBuilder reverse() {
-        boolean hasSurrogate = false;
+        boolean hasSurrogates = false;
         int n = count - 1;
-        for (int j = (n-1) >> 1; j >= 0; --j) {
-            char temp = value[j];
-            char temp2 = value[n - j];
-            if (!hasSurrogate) {
-                hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
-                    || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
+        for (int j = (n-1) >> 1; j >= 0; j--) {
+            int k = n - j;
+            char cj = value[j];
+            char ck = value[k];
+            value[j] = ck;
+            value[k] = cj;
+            if (Character.isSurrogate(cj) ||
+                Character.isSurrogate(ck)) {
+                hasSurrogates = true;
             }
-            value[j] = temp2;
-            value[n - j] = temp;
         }
-        if (hasSurrogate) {
-            // Reverse back all valid surrogate pairs
-            for (int i = 0; i < count - 1; i++) {
-                char c2 = value[i];
-                if (Character.isLowSurrogate(c2)) {
-                    char c1 = value[i + 1];
-                    if (Character.isHighSurrogate(c1)) {
-                        value[i++] = c1;
-                        value[i] = c2;
-                    }
-                }
-            }
+        if (hasSurrogates) {
+            reverseAllValidSurrogatePairs();
         }
         return this;
     }
 
+    /** Outlined helper method for reverse() */
+    private void reverseAllValidSurrogatePairs() {
+        for (int i = 0; i < count - 1; i++) {
+            char c2 = value[i];
+            if (Character.isLowSurrogate(c2)) {
+                char c1 = value[i + 1];
+                if (Character.isHighSurrogate(c1)) {
+                    value[i++] = c1;
+                    value[i] = c2;
+                }
+            }
+        }
+    }
+
     /**
      * Returns a string representing the data in this sequence.
-     * A new <code>String</code> object is allocated and initialized to
+     * A new {@code String} object is allocated and initialized to
      * contain the character sequence currently represented by this
-     * object. This <code>String</code> is then returned. Subsequent
+     * object. This {@code String} is then returned. Subsequent
      * changes to this sequence do not affect the contents of the
-     * <code>String</code>.
+     * {@code String}.
      *
      * @return  a string representation of this sequence of characters.
-     * @hide
      */
+    @Override
     public abstract String toString();
 
     /**
-     * Needed by <tt>String</tt> for the contentEquals method.
+     * Needed by {@code String} for the contentEquals method.
      */
     final char[] getValue() {
         return value;
diff --git a/ojluni/src/main/java/java/lang/Character.java b/ojluni/src/main/java/java/lang/Character.java
index 11d2fe3..ac04a7d 100644
--- a/ojluni/src/main/java/java/lang/Character.java
+++ b/ojluni/src/main/java/java/lang/Character.java
@@ -670,8 +670,14 @@
          * This name must be the same as the block identifier.
          */
         private UnicodeBlock(String idName) {
+            this(idName, true);
+        }
+
+        private UnicodeBlock(String idName, boolean isMap) {
             super(idName);
-            map.put(idName, this);
+            if (isMap) {
+                map.put(idName, this);
+            }
         }
 
         /**
@@ -1252,7 +1258,7 @@
          */
         @Deprecated
         public static final UnicodeBlock SURROGATES_AREA =
-            new UnicodeBlock("SURROGATES_AREA");
+            new UnicodeBlock("SURROGATES_AREA", false);
 
         /**
          * Constant for the "Syriac" Unicode character block.
diff --git a/ojluni/src/main/java/java/lang/ClassCastException.java b/ojluni/src/main/java/java/lang/ClassCastException.java
old mode 100755
new mode 100644
index fc9b261..e4ca76c
--- a/ojluni/src/main/java/java/lang/ClassCastException.java
+++ b/ojluni/src/main/java/java/lang/ClassCastException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2008, 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
@@ -29,7 +29,7 @@
  * Thrown to indicate that the code has attempted to cast an object
  * to a subclass of which it is not an instance. For example, the
  * following code generates a <code>ClassCastException</code>:
- * <p><blockquote><pre>
+ * <blockquote><pre>
  *     Object x = new Integer(0);
  *     System.out.println((String)x);
  * </pre></blockquote>
diff --git a/ojluni/src/main/java/java/lang/Comparable.java b/ojluni/src/main/java/java/lang/Comparable.java
old mode 100755
new mode 100644
index c049323..c14e493
--- a/ojluni/src/main/java/java/lang/Comparable.java
+++ b/ojluni/src/main/java/java/lang/Comparable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, 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
@@ -56,7 +56,7 @@
  * method.<p>
  *
  * For example, if one adds two keys <tt>a</tt> and <tt>b</tt> such that
- * <tt>(!a.equals(b) && a.compareTo(b) == 0)</tt> to a sorted
+ * {@code (!a.equals(b) && a.compareTo(b) == 0)} to a sorted
  * set that does not use an explicit comparator, the second <tt>add</tt>
  * operation returns false (and the size of the sorted set does not increase)
  * because <tt>a</tt> and <tt>b</tt> are equivalent from the sorted set's
@@ -93,7 +93,6 @@
  * @see java.util.Comparator
  * @since 1.2
  */
-
 public interface Comparable<T> {
     /**
      * Compares this object with the specified object for order.  Returns a
diff --git a/ojluni/src/main/java/java/lang/Deprecated.java b/ojluni/src/main/java/java/lang/Deprecated.java
old mode 100755
new mode 100644
index 2b1546b..58a0691
--- a/ojluni/src/main/java/java/lang/Deprecated.java
+++ b/ojluni/src/main/java/java/lang/Deprecated.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -36,6 +36,7 @@
  *
  * @author  Neal Gafter
  * @since 1.5
+ * @jls 9.6.3.6 @Deprecated
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/ojluni/src/main/java/java/lang/Double.java b/ojluni/src/main/java/java/lang/Double.java
old mode 100755
new mode 100644
index 59f8088..2bc2bf3
--- a/ojluni/src/main/java/java/lang/Double.java
+++ b/ojluni/src/main/java/java/lang/Double.java
@@ -26,6 +26,7 @@
 
 package java.lang;
 
+import sun.misc.FloatingDecimal;
 import sun.misc.FpUtils;
 import sun.misc.DoubleConsts;
 
@@ -135,6 +136,7 @@
      *
      * @since JDK1.1
      */
+    @SuppressWarnings("unchecked")
     public static final Class<Double>   TYPE = (Class<Double>) double[].class.getComponentType();
 
     /**
@@ -146,7 +148,7 @@
      * <li>Otherwise, the result is a string that represents the sign and
      * magnitude (absolute value) of the argument. If the sign is negative,
      * the first character of the result is '{@code -}'
-     * (<code>'&#92;u002D'</code>); if the sign is positive, no sign character
+     * ({@code '\u005Cu002D'}); if the sign is positive, no sign character
      * appears in the result. As for the magnitude <i>m</i>:
      * <ul>
      * <li>If <i>m</i> is infinity, it is represented by the characters
@@ -162,7 +164,7 @@
      * <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less
      * than 10<sup>7</sup>, then it is represented as the integer part of
      * <i>m</i>, in decimal form with no leading zeroes, followed by
-     * '{@code .}' (<code>'&#92;u002E'</code>), followed by one or
+     * '{@code .}' ({@code '\u005Cu002E'}), followed by one or
      * more decimal digits representing the fractional part of <i>m</i>.
      *
      * <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or
@@ -174,9 +176,9 @@
      * 10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10. The
      * magnitude is then represented as the integer part of <i>a</i>,
      * as a single decimal digit, followed by '{@code .}'
-     * (<code>'&#92;u002E'</code>), followed by decimal digits
+     * ({@code '\u005Cu002E'}), followed by decimal digits
      * representing the fractional part of <i>a</i>, followed by the
-     * letter '{@code E}' (<code>'&#92;u0045'</code>), followed
+     * letter '{@code E}' ({@code '\u005Cu0045'}), followed
      * by a representation of <i>n</i> as a decimal integer, as
      * produced by the method {@link Integer#toString(int)}.
      * </ul>
@@ -200,7 +202,7 @@
      * @return a string representation of the argument.
      */
     public static String toString(double d) {
-        return FloatingDecimal.getThreadLocalInstance().loadDouble(d).toJavaFormatString();
+        return FloatingDecimal.toJavaFormatString(d);
     }
 
     /**
@@ -214,7 +216,7 @@
      * <li>Otherwise, the result is a string that represents the sign
      * and magnitude of the argument. If the sign is negative, the
      * first character of the result is '{@code -}'
-     * (<code>'&#92;u002D'</code>); if the sign is positive, no sign
+     * ({@code '\u005Cu002D'}); if the sign is positive, no sign
      * character appears in the result. As for the magnitude <i>m</i>:
      *
      * <ul>
@@ -255,7 +257,7 @@
      * </ul>
      *
      * <table border>
-     * <caption><h3>Examples</h3></caption>
+     * <caption>Examples</caption>
      * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
      * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
      * <tr><td>{@code -1.0}</td>        <td>{@code -0x1.0p0}</td>
@@ -283,14 +285,14 @@
          * 7.19.6.1; however, the output of this method is more
          * tightly specified.
          */
-        if (!FpUtils.isFinite(d) )
+        if (!isFinite(d) )
             // For infinity and NaN, use the decimal output.
             return Double.toString(d);
         else {
             // Initialized to maximum size of output.
-            StringBuffer answer = new StringBuffer(24);
+            StringBuilder answer = new StringBuilder(24);
 
-            if (FpUtils.rawCopySign(1.0, d) == -1.0) // value is negative,
+            if (Math.copySign(1.0, d) == -1.0)    // value is negative,
                 answer.append("-");                  // so append sign info
 
             answer.append("0x");
@@ -299,8 +301,7 @@
 
             if(d == 0.0) {
                 answer.append("0.0p0");
-            }
-            else {
+            } else {
                 boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
 
                 // Isolate significand bits and OR in a high-order bit
@@ -323,13 +324,14 @@
                               "0":
                               signif.replaceFirst("0{1,12}$", ""));
 
+                answer.append('p');
                 // If the value is subnormal, use the E_min exponent
                 // value for double; otherwise, extract and report d's
                 // exponent (the representation of a subnormal uses
                 // E_min -1).
-                answer.append("p" + (subnormal ?
-                               DoubleConsts.MIN_EXPONENT:
-                               FpUtils.getExponent(d) ));
+                answer.append(subnormal ?
+                              DoubleConsts.MIN_EXPONENT:
+                              Math.getExponent(d));
             }
             return answer.toString();
         }
@@ -360,15 +362,11 @@
      * <dd><i>SignedInteger</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>HexFloatingPointLiteral</i>:
      * <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>HexSignificand:</i>
      * <dd><i>HexNumeral</i>
@@ -379,15 +377,11 @@
      *     </i>{@code .} <i>HexDigits</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>BinaryExponent:</i>
      * <dd><i>BinaryExponentIndicator SignedInteger</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>BinaryExponentIndicator:</i>
      * <dd>{@code p}
@@ -452,8 +446,7 @@
      * a {@code NumberFormatException} be thrown, the regular
      * expression below can be used to screen the input string:
      *
-     * <code>
-     * <pre>
+     * <pre>{@code
      *  final String Digits     = "(\\p{Digit}+)";
      *  final String HexDigits  = "(\\p{XDigit}+)";
      *  // an exponent is 'e' or 'E' followed by an optionally
@@ -473,7 +466,7 @@
      *       // in addition to strings of floating-point literals, the
      *       // two sub-patterns below are simplifications of the grammar
      *       // productions from section 3.10.2 of
-     *       // <cite>The Java&trade; Language Specification</cite>.
+     *       // The Java Language Specification.
      *
      *       // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
      *       "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
@@ -498,8 +491,7 @@
      *  else {
      *      // Perform suitable alternative action
      *  }
-     * </pre>
-     * </code>
+     * }</pre>
      *
      * @param      s   the string to be parsed.
      * @return     a {@code Double} object holding the value
@@ -508,7 +500,7 @@
      *             parsable number.
      */
     public static Double valueOf(String s) throws NumberFormatException {
-        return new Double(FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).doubleValue());
+        return new Double(parseDouble(s));
     }
 
     /**
@@ -544,7 +536,7 @@
      * @since 1.2
      */
     public static double parseDouble(String s) throws NumberFormatException {
-        return FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).doubleValue();
+        return FloatingDecimal.parseDouble(s);
     }
 
     /**
@@ -555,7 +547,7 @@
      * @return  {@code true} if the value of the argument is NaN;
      *          {@code false} otherwise.
      */
-    static public boolean isNaN(double v) {
+    public static boolean isNaN(double v) {
         return (v != v);
     }
 
@@ -567,7 +559,7 @@
      * @return  {@code true} if the value of the argument is positive
      *          infinity or negative infinity; {@code false} otherwise.
      */
-    static public boolean isInfinite(double v) {
+    public static boolean isInfinite(double v) {
         return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
     }
 
@@ -614,8 +606,7 @@
      * @see       java.lang.Double#valueOf(java.lang.String)
      */
     public Double(String s) throws NumberFormatException {
-        // REMIND: this is inefficient
-        this(valueOf(s).doubleValue());
+        value = parseDouble(s);
     }
 
     /**
@@ -655,11 +646,12 @@
     }
 
     /**
-     * Returns the value of this {@code Double} as a {@code byte} (by
-     * casting to a {@code byte}).
+     * Returns the value of this {@code Double} as a {@code byte}
+     * after a narrowing primitive conversion.
      *
      * @return  the {@code double} value represented by this object
      *          converted to type {@code byte}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      * @since JDK1.1
      */
     public byte byteValue() {
@@ -667,11 +659,12 @@
     }
 
     /**
-     * Returns the value of this {@code Double} as a
-     * {@code short} (by casting to a {@code short}).
+     * Returns the value of this {@code Double} as a {@code short}
+     * after a narrowing primitive conversion.
      *
      * @return  the {@code double} value represented by this object
      *          converted to type {@code short}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      * @since JDK1.1
      */
     public short shortValue() {
@@ -679,8 +672,9 @@
     }
 
     /**
-     * Returns the value of this {@code Double} as an
-     * {@code int} (by casting to type {@code int}).
+     * Returns the value of this {@code Double} as an {@code int}
+     * after a narrowing primitive conversion.
+     * @jls 5.1.3 Narrowing Primitive Conversions
      *
      * @return  the {@code double} value represented by this object
      *          converted to type {@code int}
@@ -690,22 +684,24 @@
     }
 
     /**
-     * Returns the value of this {@code Double} as a
-     * {@code long} (by casting to type {@code long}).
+     * Returns the value of this {@code Double} as a {@code long}
+     * after a narrowing primitive conversion.
      *
      * @return  the {@code double} value represented by this object
      *          converted to type {@code long}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public long longValue() {
         return (long)value;
     }
 
     /**
-     * Returns the {@code float} value of this
-     * {@code Double} object.
+     * Returns the value of this {@code Double} as a {@code float}
+     * after a narrowing primitive conversion.
      *
      * @return  the {@code double} value represented by this object
      *          converted to type {@code float}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      * @since JDK1.0
      */
     public float floatValue() {
@@ -713,13 +709,12 @@
     }
 
     /**
-     * Returns the {@code double} value of this
-     * {@code Double} object.
+     * Returns the {@code double} value of this {@code Double} object.
      *
      * @return the {@code double} value represented by this object
      */
     public double doubleValue() {
-        return (double)value;
+        return value;
     }
 
     /**
@@ -743,6 +738,7 @@
      *
      * @return  a {@code hash code} value for this object.
      */
+    @Override
     public int hashCode() {
         return Double.hashCode(value);
     }
@@ -912,13 +908,13 @@
      * <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three
      * values that can be computed from the argument:
      *
-     * <blockquote><pre>
-     * int s = ((bits &gt;&gt; 63) == 0) ? 1 : -1;
-     * int e = (int)((bits &gt;&gt; 52) & 0x7ffL);
+     * <blockquote><pre>{@code
+     * int s = ((bits >> 63) == 0) ? 1 : -1;
+     * int e = (int)((bits >> 52) & 0x7ffL);
      * long m = (e == 0) ?
-     *                 (bits & 0xfffffffffffffL) &lt;&lt; 1 :
+     *                 (bits & 0xfffffffffffffL) << 1 :
      *                 (bits & 0xfffffffffffffL) | 0x10000000000000L;
-     * </pre></blockquote>
+     * }</pre></blockquote>
      *
      * Then the floating-point result equals the value of the mathematical
      * expression <i>s</i>&middot;<i>m</i>&middot;2<sup><i>e</i>-1075</sup>.
diff --git a/ojluni/src/main/java/java/lang/Float.java b/ojluni/src/main/java/java/lang/Float.java
old mode 100755
new mode 100644
index d75953e..32bd625
--- a/ojluni/src/main/java/java/lang/Float.java
+++ b/ojluni/src/main/java/java/lang/Float.java
@@ -26,7 +26,7 @@
 
 package java.lang;
 
-import sun.misc.FpUtils;
+import sun.misc.FloatingDecimal;
 import sun.misc.FloatConsts;
 import sun.misc.DoubleConsts;
 
@@ -134,6 +134,7 @@
      *
      * @since JDK1.1
      */
+    @SuppressWarnings("unchecked")
     public static final Class<Float> TYPE = (Class<Float>) float[].class.getComponentType();
 
     /**
@@ -145,7 +146,7 @@
      * <li>Otherwise, the result is a string that represents the sign and
      *     magnitude (absolute value) of the argument. If the sign is
      *     negative, the first character of the result is
-     *     '{@code -}' (<code>'&#92;u002D'</code>); if the sign is
+     *     '{@code -}' ({@code '\u005Cu002D'}); if the sign is
      *     positive, no sign character appears in the result. As for
      *     the magnitude <i>m</i>:
      * <ul>
@@ -161,7 +162,7 @@
      *      less than 10<sup>7</sup>, then it is represented as the
      *      integer part of <i>m</i>, in decimal form with no leading
      *      zeroes, followed by '{@code .}'
-     *      (<code>'&#92;u002E'</code>), followed by one or more
+     *      ({@code '\u005Cu002E'}), followed by one or more
      *      decimal digits representing the fractional part of
      *      <i>m</i>.
      * <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
@@ -173,10 +174,10 @@
      *      10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10.
      *      The magnitude is then represented as the integer part of
      *      <i>a</i>, as a single decimal digit, followed by
-     *      '{@code .}' (<code>'&#92;u002E'</code>), followed by
+     *      '{@code .}' ({@code '\u005Cu002E'}), followed by
      *      decimal digits representing the fractional part of
      *      <i>a</i>, followed by the letter '{@code E}'
-     *      (<code>'&#92;u0045'</code>), followed by a representation
+     *      ({@code '\u005Cu0045'}), followed by a representation
      *      of <i>n</i> as a decimal integer, as produced by the
      *      method {@link java.lang.Integer#toString(int)}.
      *
@@ -203,7 +204,7 @@
      * @return a string representation of the argument.
      */
     public static String toString(float f) {
-        return FloatingDecimal.getThreadLocalInstance().loadFloat(f).toJavaFormatString();
+        return FloatingDecimal.toJavaFormatString(f);
     }
 
     /**
@@ -217,7 +218,7 @@
      * <li>Otherwise, the result is a string that represents the sign and
      * magnitude (absolute value) of the argument. If the sign is negative,
      * the first character of the result is '{@code -}'
-     * (<code>'&#92;u002D'</code>); if the sign is positive, no sign character
+     * ({@code '\u005Cu002D'}); if the sign is positive, no sign character
      * appears in the result. As for the magnitude <i>m</i>:
      *
      * <ul>
@@ -258,7 +259,7 @@
      * </ul>
      *
      * <table border>
-     * <caption><h3>Examples</h3></caption>
+     * <caption>Examples</caption>
      * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
      * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
      * <tr><td>{@code -1.0}</td>        <td>{@code -0x1.0p0}</td>
@@ -286,10 +287,10 @@
             // Adjust exponent to create subnormal double, then
             // replace subnormal double exponent with subnormal float
             // exponent
-            String s = Double.toHexString(FpUtils.scalb((double)f,
-                                                        /* -1022+126 */
-                                                        DoubleConsts.MIN_EXPONENT-
-                                                        FloatConsts.MIN_EXPONENT));
+            String s = Double.toHexString(Math.scalb((double)f,
+                                                     /* -1022+126 */
+                                                     DoubleConsts.MIN_EXPONENT-
+                                                     FloatConsts.MIN_EXPONENT));
             return s.replaceFirst("p-1022$", "p-126");
         }
         else // double string will be the same as float string
@@ -321,15 +322,11 @@
      * <dd><i>SignedInteger</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>HexFloatingPointLiteral</i>:
      * <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>HexSignificand:</i>
      * <dd><i>HexNumeral</i>
@@ -340,15 +337,11 @@
      *     </i>{@code .} <i>HexDigits</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>BinaryExponent:</i>
      * <dd><i>BinaryExponentIndicator SignedInteger</i>
      * </dl>
      *
-     * <p>
-     *
      * <dl>
      * <dt><i>BinaryExponentIndicator:</i>
      * <dd>{@code p}
@@ -421,7 +414,7 @@
      *          parsable number.
      */
     public static Float valueOf(String s) throws NumberFormatException {
-        return new Float(FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).floatValue());
+        return new Float(parseFloat(s));
     }
 
     /**
@@ -456,7 +449,7 @@
      * @since 1.2
      */
     public static float parseFloat(String s) throws NumberFormatException {
-        return FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).floatValue();
+        return FloatingDecimal.parseFloat(s);
     }
 
     /**
@@ -467,7 +460,7 @@
      * @return  {@code true} if the argument is NaN;
      *          {@code false} otherwise.
      */
-    static public boolean isNaN(float v) {
+    public static boolean isNaN(float v) {
         return (v != v);
     }
 
@@ -479,10 +472,11 @@
      * @return  {@code true} if the argument is positive infinity or
      *          negative infinity; {@code false} otherwise.
      */
-    static public boolean isInfinite(float v) {
+    public static boolean isInfinite(float v) {
         return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
     }
 
+
     /**
      * Returns {@code true} if the argument is a finite floating-point
      * value; returns {@code false} otherwise (for NaN and infinity
@@ -536,8 +530,7 @@
      * @see        java.lang.Float#valueOf(java.lang.String)
      */
     public Float(String s) throws NumberFormatException {
-        // REMIND: this is inefficient
-        this(valueOf(s).floatValue());
+        value = parseFloat(s);
     }
 
     /**
@@ -577,22 +570,24 @@
     }
 
     /**
-     * Returns the value of this {@code Float} as a {@code byte} (by
-     * casting to a {@code byte}).
+     * Returns the value of this {@code Float} as a {@code byte} after
+     * a narrowing primitive conversion.
      *
      * @return  the {@code float} value represented by this object
      *          converted to type {@code byte}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public byte byteValue() {
         return (byte)value;
     }
 
     /**
-     * Returns the value of this {@code Float} as a {@code short} (by
-     * casting to a {@code short}).
+     * Returns the value of this {@code Float} as a {@code short}
+     * after a narrowing primitive conversion.
      *
      * @return  the {@code float} value represented by this object
      *          converted to type {@code short}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      * @since JDK1.1
      */
     public short shortValue() {
@@ -600,22 +595,24 @@
     }
 
     /**
-     * Returns the value of this {@code Float} as an {@code int} (by
-     * casting to type {@code int}).
+     * Returns the value of this {@code Float} as an {@code int} after
+     * a narrowing primitive conversion.
      *
      * @return  the {@code float} value represented by this object
      *          converted to type {@code int}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public int intValue() {
         return (int)value;
     }
 
     /**
-     * Returns value of this {@code Float} as a {@code long} (by
-     * casting to type {@code long}).
+     * Returns value of this {@code Float} as a {@code long} after a
+     * narrowing primitive conversion.
      *
      * @return  the {@code float} value represented by this object
      *          converted to type {@code long}
+     * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public long longValue() {
         return (long)value;
@@ -631,11 +628,12 @@
     }
 
     /**
-     * Returns the {@code double} value of this {@code Float} object.
+     * Returns the value of this {@code Float} as a {@code double}
+     * after a widening primitive conversion.
      *
      * @return the {@code float} value represented by this
-     *         object is converted to type {@code double} and the
-     *         result of the conversion is returned.
+     *         object converted to type {@code double}
+     * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)value;
@@ -650,8 +648,9 @@
      *
      * @return a hash code value for this object.
      */
+    @Override
     public int hashCode() {
-        return floatToIntBits(value);
+        return Float.hashCode(value);
     }
 
     /**
@@ -815,13 +814,13 @@
      * <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three
      * values that can be computed from the argument:
      *
-     * <blockquote><pre>
-     * int s = ((bits &gt;&gt; 31) == 0) ? 1 : -1;
-     * int e = ((bits &gt;&gt; 23) & 0xff);
+     * <blockquote><pre>{@code
+     * int s = ((bits >> 31) == 0) ? 1 : -1;
+     * int e = ((bits >> 23) & 0xff);
      * int m = (e == 0) ?
-     *                 (bits & 0x7fffff) &lt;&lt; 1 :
+     *                 (bits & 0x7fffff) << 1 :
      *                 (bits & 0x7fffff) | 0x800000;
-     * </pre></blockquote>
+     * }</pre></blockquote>
      *
      * Then the floating-point result equals the value of the mathematical
      * expression <i>s</i>&middot;<i>m</i>&middot;2<sup><i>e</i>-150</sup>.
diff --git a/ojluni/src/main/java/java/lang/FloatingDecimal.java b/ojluni/src/main/java/java/lang/FloatingDecimal.java
deleted file mode 100755
index d27c5ae..0000000
--- a/ojluni/src/main/java/java/lang/FloatingDecimal.java
+++ /dev/null
@@ -1,2476 +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 java.lang;
-
-import sun.misc.FpUtils;
-import sun.misc.FDBigInt;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import java.util.regex.*;
-
-public class FloatingDecimal {
-    boolean     isExceptional;
-    boolean     isNegative;
-    int         decExponent;
-    char        digits[];
-    int         nDigits;
-    int         bigIntExp;
-    int         bigIntNBits;
-    boolean     mustSetRoundDir = false;
-    boolean     fromHex = false;
-    int         roundDir = 0; // set by doubleValue
-
-    /*
-     * Constants of the implementation
-     * Most are IEEE-754 related.
-     * (There are more really boring constants at the end.)
-     */
-    static final long   signMask = 0x8000000000000000L;
-    static final long   expMask  = 0x7ff0000000000000L;
-    static final long   fractMask= ~(signMask|expMask);
-    static final int    expShift = 52;
-    static final int    expBias  = 1023;
-    static final long   fractHOB = ( 1L<<expShift ); // assumed High-Order bit
-    static final long   expOne   = ((long)expBias)<<expShift; // exponent of 1.0
-    static final int    maxSmallBinExp = 62;
-    static final int    minSmallBinExp = -( 63 / 3 );
-    static final int    maxDecimalDigits = 15;
-    static final int    maxDecimalExponent = 308;
-    static final int    minDecimalExponent = -324;
-    static final int    bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
-
-    static final long   highbyte = 0xff00000000000000L;
-    static final long   highbit  = 0x8000000000000000L;
-    static final long   lowbytes = ~highbyte;
-
-    static final int    singleSignMask =    0x80000000;
-    static final int    singleExpMask  =    0x7f800000;
-    static final int    singleFractMask =   ~(singleSignMask|singleExpMask);
-    static final int    singleExpShift  =   23;
-    static final int    singleFractHOB  =   1<<singleExpShift;
-    static final int    singleExpBias   =   127;
-    static final int    singleMaxDecimalDigits = 7;
-    static final int    singleMaxDecimalExponent = 38;
-    static final int    singleMinDecimalExponent = -45;
-
-    static final int    intDecimalDigits = 9;
-
-    /*
-     * count number of bits from high-order 1 bit to low-order 1 bit,
-     * inclusive.
-     */
-    private static int
-    countBits( long v ){
-        //
-        // the strategy is to shift until we get a non-zero sign bit
-        // then shift until we have no bits left, counting the difference.
-        // we do byte shifting as a hack. Hope it helps.
-        //
-        if ( v == 0L ) return 0;
-
-        while ( ( v & highbyte ) == 0L ){
-            v <<= 8;
-        }
-        while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
-            v <<= 1;
-        }
-
-        int n = 0;
-        while (( v & lowbytes ) != 0L ){
-            v <<= 8;
-            n += 8;
-        }
-        while ( v != 0L ){
-            v <<= 1;
-            n += 1;
-        }
-        return n;
-    }
-
-    /*
-     * Keep big powers of 5 handy for future reference.
-     */
-    private static FDBigInt b5p[];
-
-    private static synchronized FDBigInt
-    big5pow( int p ){
-        assert p >= 0 : p; // negative power of 5
-        if ( b5p == null ){
-            b5p = new FDBigInt[ p+1 ];
-        }else if (b5p.length <= p ){
-            FDBigInt t[] = new FDBigInt[ p+1 ];
-            System.arraycopy( b5p, 0, t, 0, b5p.length );
-            b5p = t;
-        }
-        if ( b5p[p] != null )
-            return b5p[p];
-        else if ( p < small5pow.length )
-            return b5p[p] = new FDBigInt( small5pow[p] );
-        else if ( p < long5pow.length )
-            return b5p[p] = new FDBigInt( long5pow[p] );
-        else {
-            // construct the value.
-            // recursively.
-            int q, r;
-            // in order to compute 5^p,
-            // compute its square root, 5^(p/2) and square.
-            // or, let q = p / 2, r = p -q, then
-            // 5^p = 5^(q+r) = 5^q * 5^r
-            q = p >> 1;
-            r = p - q;
-            FDBigInt bigq =  b5p[q];
-            if ( bigq == null )
-                bigq = big5pow ( q );
-            if ( r < small5pow.length ){
-                return (b5p[p] = bigq.mult( small5pow[r] ) );
-            }else{
-                FDBigInt bigr = b5p[ r ];
-                if ( bigr == null )
-                    bigr = big5pow( r );
-                return (b5p[p] = bigq.mult( bigr ) );
-            }
-        }
-    }
-
-    //
-    // a common operation
-    //
-    private static FDBigInt
-    multPow52( FDBigInt v, int p5, int p2 ){
-        if ( p5 != 0 ){
-            if ( p5 < small5pow.length ){
-                v = v.mult( small5pow[p5] );
-            } else {
-                v = v.mult( big5pow( p5 ) );
-            }
-        }
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
-        }
-        return v;
-    }
-
-    //
-    // another common operation
-    //
-    private static FDBigInt
-    constructPow52( int p5, int p2 ){
-        FDBigInt v = new FDBigInt( big5pow( p5 ) );
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
-        }
-        return v;
-    }
-
-    /*
-     * Make a floating double into a FDBigInt.
-     * This could also be structured as a FDBigInt
-     * constructor, but we'd have to build a lot of knowledge
-     * about floating-point representation into it, and we don't want to.
-     *
-     * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-     * bigIntExp and bigIntNBits
-     *
-     */
-    private FDBigInt
-    doubleToBigInt( double dval ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        lbits &= fractMask;
-        if ( binexp > 0 ){
-            lbits |= fractHOB;
-        } else {
-            assert lbits != 0L : lbits; // doubleToBigInt(0.0)
-            binexp +=1;
-            while ( (lbits & fractHOB ) == 0L){
-                lbits <<= 1;
-                binexp -= 1;
-            }
-        }
-        binexp -= expBias;
-        int nbits = countBits( lbits );
-        /*
-         * We now know where the high-order 1 bit is,
-         * and we know how many there are.
-         */
-        int lowOrderZeros = expShift+1-nbits;
-        lbits >>>= lowOrderZeros;
-
-        bigIntExp = binexp+1-nbits;
-        bigIntNBits = nbits;
-        return new FDBigInt( lbits );
-    }
-
-    /*
-     * Compute a number that is the ULP of the given value,
-     * for purposes of addition/subtraction. Generally easy.
-     * More difficult if subtracting and the argument
-     * is a normalized a power of 2, as the ULP changes at these points.
-     */
-    private static double ulp( double dval, boolean subtracting ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        double ulpval;
-        if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
-            // for subtraction from normalized, powers of 2,
-            // use next-smaller exponent
-            binexp -= 1;
-        }
-        if ( binexp > expShift ){
-            ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
-        } else if ( binexp == 0 ){
-            ulpval = Double.MIN_VALUE;
-        } else {
-            ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
-        }
-        if ( subtracting ) ulpval = - ulpval;
-
-        return ulpval;
-    }
-
-    /*
-     * Round a double to a float.
-     * In addition to the fraction bits of the double,
-     * look at the class instance variable roundDir,
-     * which should help us avoid double-rounding error.
-     * roundDir was set in hardValueOf if the estimate was
-     * close enough, but not exact. It tells us which direction
-     * of rounding is preferred.
-     */
-    float
-    stickyRound( double dval ){
-        long lbits = Double.doubleToLongBits( dval );
-        long binexp = lbits & expMask;
-        if ( binexp == 0L || binexp == expMask ){
-            // what we have here is special.
-            // don't worry, the right thing will happen.
-            return (float) dval;
-        }
-        lbits += (long)roundDir; // hack-o-matic.
-        return (float)Double.longBitsToDouble( lbits );
-    }
-
-
-    /*
-     * This is the easy subcase --
-     * all the significant bits, after scaling, are held in lvalue.
-     * negSign and decExponent tell us what processing and scaling
-     * has already been done. Exceptional cases have already been
-     * stripped out.
-     * In particular:
-     * lvalue is a finite number (not Inf, nor NaN)
-     * lvalue > 0L (not zero, nor negative).
-     *
-     * The only reason that we develop the digits here, rather than
-     * calling on Long.toString() is that we can do it a little faster,
-     * and besides want to treat trailing 0s specially. If Long.toString
-     * changes, we should re-evaluate this strategy!
-     */
-    private void
-    developLongDigits( int decExponent, long lvalue, long insignificant ){
-        char digits[];
-        int  ndigits;
-        int  digitno;
-        int  c;
-        //
-        // Discard non-significant low-order bits, while rounding,
-        // up to insignificant value.
-        int i;
-        for ( i = 0; insignificant >= 10L; i++ )
-            insignificant /= 10L;
-        if ( i != 0 ){
-            long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
-            long residue = lvalue % pow10;
-            lvalue /= pow10;
-            decExponent += i;
-            if ( residue >= (pow10>>1) ){
-                // round up based on the low-order bits we're discarding
-                lvalue++;
-            }
-        }
-        if ( lvalue <= Integer.MAX_VALUE ){
-            assert lvalue > 0L : lvalue; // lvalue <= 0
-            // even easier subcase!
-            // can do int arithmetic rather than long!
-            int  ivalue = (int)lvalue;
-            ndigits = 10;
-            digits = (char[])(perThreadBuffer.get());
-            digitno = ndigits-1;
-            c = ivalue%10;
-            ivalue /= 10;
-            while ( c == 0 ){
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            while ( ivalue != 0){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        } else {
-            // same algorithm as above (same bugs, too )
-            // but using long arithmetic.
-            ndigits = 20;
-            digits = (char[])(perThreadBuffer.get());
-            digitno = ndigits-1;
-            c = (int)(lvalue%10L);
-            lvalue /= 10L;
-            while ( c == 0 ){
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10L;
-            }
-            while ( lvalue != 0L ){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        }
-        char result [];
-        ndigits -= digitno;
-        result = new char[ ndigits ];
-        System.arraycopy( digits, digitno, result, 0, ndigits );
-        this.digits = result;
-        this.decExponent = decExponent+1;
-        this.nDigits = ndigits;
-    }
-
-    //
-    // add one to the least significant digit.
-    // in the unlikely event there is a carry out,
-    // deal with it.
-    // assert that this will only happen where there
-    // is only one digit, e.g. (float)1e-44 seems to do it.
-    //
-    private void
-    roundup(){
-        int i;
-        int q = digits[ i = (nDigits-1)];
-        if ( q == '9' ){
-            while ( q == '9' && i > 0 ){
-                digits[i] = '0';
-                q = digits[--i];
-            }
-            if ( q == '9' ){
-                // carryout! High-order 1, rest 0s, larger exp.
-                decExponent += 1;
-                digits[0] = '1';
-                return;
-            }
-            // else fall through.
-        }
-        digits[i] = (char)(q+1);
-    }
-
-    private FloatingDecimal() {}
-
-    private static final ThreadLocal<FloatingDecimal> TL_INSTANCE = new ThreadLocal<FloatingDecimal>() {
-        @Override protected FloatingDecimal initialValue() {
-            return new FloatingDecimal();
-        }
-    };
-    public static FloatingDecimal getThreadLocalInstance() {
-        return TL_INSTANCE.get();
-    }
-
-    /*
-     * FIRST IMPORTANT LOAD: DOUBLE
-     */
-    public FloatingDecimal loadDouble(double d) {
-        long    dBits = Double.doubleToLongBits( d );
-        long    fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        mustSetRoundDir = false;
-        fromHex = false;
-        roundDir = 0;
-
-        // discover and delete sign
-        if ( (dBits&signMask) != 0 ){
-            isNegative = true;
-            dBits ^= signMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (int)( (dBits&expMask) >> expShift );
-        fractBits = dBits&fractMask;
-        if ( binExp == (int)(expMask>>expShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
-            return this;
-        }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0L ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return this;
-            }
-            while ( (fractBits&fractHOB) == 0L ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = expShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
-        } else {
-            fractBits |= fractHOB;
-            nSignificantBits = expShift+1;
-        }
-        binExp -= expBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, fractBits, nSignificantBits );
-        return this;
-    }
-
-    /*
-     * SECOND IMPORTANT LOAD: SINGLE
-     */
-    public FloatingDecimal loadFloat(float f) {
-        int     fBits = Float.floatToIntBits( f );
-        int     fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        mustSetRoundDir = false;
-        fromHex = false;
-        roundDir = 0;
-
-        // discover and delete sign
-        if ( (fBits&singleSignMask) != 0 ){
-            isNegative = true;
-            fBits ^= singleSignMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (int)( (fBits&singleExpMask) >> singleExpShift );
-        fractBits = fBits&singleFractMask;
-        if ( binExp == (int)(singleExpMask>>singleExpShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
-            return this;
-        }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0 ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return this;
-            }
-            while ( (fractBits&singleFractHOB) == 0 ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = singleExpShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
-        } else {
-            fractBits |= singleFractHOB;
-            nSignificantBits = singleExpShift+1;
-        }
-        binExp -= singleExpBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
-        return this;
-    }
-
-    private void
-    dtoa( int binExp, long fractBits, int nSignificantBits )
-    {
-        int     nFractBits; // number of significant bits of fractBits;
-        int     nTinyBits;  // number of these to the right of the point.
-        int     decExp;
-
-        // Examine number. Determine if it is an easy case,
-        // which we can do pretty trivially using float/long conversion,
-        // or whether we must do real work.
-        nFractBits = countBits( fractBits );
-        nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
-        if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
-            // Look more closely at the number to decide if,
-            // with scaling by 10^nTinyBits, the result will fit in
-            // a long.
-            if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
-                /*
-                 * We can do this:
-                 * take the fraction bits, which are normalized.
-                 * (a) nTinyBits == 0: Shift left or right appropriately
-                 *     to align the binary point at the extreme right, i.e.
-                 *     where a long int point is expected to be. The integer
-                 *     result is easily converted to a string.
-                 * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
-                 *     which effectively converts to long and scales by
-                 *     2^nTinyBits. Then multiply by 5^nTinyBits to
-                 *     complete the scaling. We know this won't overflow
-                 *     because we just counted the number of bits necessary
-                 *     in the result. The integer you get from this can
-                 *     then be converted to a string pretty easily.
-                 */
-                long halfULP;
-                if ( nTinyBits == 0 ) {
-                    if ( binExp > nSignificantBits ){
-                        halfULP = 1L << ( binExp-nSignificantBits-1);
-                    } else {
-                        halfULP = 0L;
-                    }
-                    if ( binExp >= expShift ){
-                        fractBits <<= (binExp-expShift);
-                    } else {
-                        fractBits >>>= (expShift-binExp) ;
-                    }
-                    developLongDigits( 0, fractBits, halfULP );
-                    return;
-                }
-                /*
-                 * The following causes excess digits to be printed
-                 * out in the single-float case. Our manipulation of
-                 * halfULP here is apparently not correct. If we
-                 * better understand how this works, perhaps we can
-                 * use this special case again. But for the time being,
-                 * we do not.
-                 * else {
-                 *     fractBits >>>= expShift+1-nFractBits;
-                 *     fractBits *= long5pow[ nTinyBits ];
-                 *     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
-                 *     developLongDigits( -nTinyBits, fractBits, halfULP );
-                 *     return;
-                 * }
-                 */
-            }
-        }
-        /*
-         * This is the hard case. We are going to compute large positive
-         * integers B and S and integer decExp, s.t.
-         *      d = ( B / S ) * 10^decExp
-         *      1 <= B / S < 10
-         * Obvious choices are:
-         *      decExp = floor( log10(d) )
-         *      B      = d * 2^nTinyBits * 10^max( 0, -decExp )
-         *      S      = 10^max( 0, decExp) * 2^nTinyBits
-         * (noting that nTinyBits has already been forced to non-negative)
-         * I am also going to compute a large positive integer
-         *      M      = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
-         * i.e. M is (1/2) of the ULP of d, scaled like B.
-         * When we iterate through dividing B/S and picking off the
-         * quotient bits, we will know when to stop when the remainder
-         * is <= M.
-         *
-         * We keep track of powers of 2 and powers of 5.
-         */
-
-        /*
-         * Estimate decimal exponent. (If it is small-ish,
-         * we could double-check.)
-         *
-         * First, scale the mantissa bits such that 1 <= d2 < 2.
-         * We are then going to estimate
-         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
-         * and so we can estimate
-         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
-         * take the floor and call it decExp.
-         * FIXME -- use more precise constants here. It costs no more.
-         */
-        double d2 = Double.longBitsToDouble(
-            expOne | ( fractBits &~ fractHOB ) );
-        decExp = (int)Math.floor(
-            (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
-        int B2, B5; // powers of 2 and powers of 5, respectively, in B
-        int S2, S5; // powers of 2 and powers of 5, respectively, in S
-        int M2, M5; // powers of 2 and powers of 5, respectively, in M
-        int Bbits; // binary digits needed to represent B, approx.
-        int tenSbits; // binary digits needed to represent 10*S, approx.
-        FDBigInt Sval, Bval, Mval;
-
-        B5 = Math.max( 0, -decExp );
-        B2 = B5 + nTinyBits + binExp;
-
-        S5 = Math.max( 0, decExp );
-        S2 = S5 + nTinyBits;
-
-        M5 = B5;
-        M2 = B2 - nSignificantBits;
-
-        /*
-         * the long integer fractBits contains the (nFractBits) interesting
-         * bits from the mantissa of d ( hidden 1 added if necessary) followed
-         * by (expShift+1-nFractBits) zeros. In the interest of compactness,
-         * I will shift out those zeros before turning fractBits into a
-         * FDBigInt. The resulting whole number will be
-         *      d * 2^(nFractBits-1-binExp).
-         */
-        fractBits >>>= (expShift+1-nFractBits);
-        B2 -= nFractBits-1;
-        int common2factor = Math.min( B2, S2 );
-        B2 -= common2factor;
-        S2 -= common2factor;
-        M2 -= common2factor;
-
-        /*
-         * HACK!! For exact powers of two, the next smallest number
-         * is only half as far away as we think (because the meaning of
-         * ULP changes at power-of-two bounds) for this reason, we
-         * hack M2. Hope this works.
-         */
-        if ( nFractBits == 1 )
-            M2 -= 1;
-
-        if ( M2 < 0 ){
-            // oops.
-            // since we cannot scale M down far enough,
-            // we must scale the other values up.
-            B2 -= M2;
-            S2 -= M2;
-            M2 =  0;
-        }
-        /*
-         * Construct, Scale, iterate.
-         * Some day, we'll write a stopping test that takes
-         * account of the asymmetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        char digits[] = this.digits = new char[18];
-        int  ndigit = 0;
-        boolean low, high;
-        long lowDigitDifference;
-        int  q;
-
-        /*
-         * Detect the special cases where all the numbers we are about
-         * to compute will fit in int or long integers.
-         * In these cases, we will avoid doing FDBigInt arithmetic.
-         * We use the same algorithms, except that we "normalize"
-         * our FDBigInts before iterating. This is to make division easier,
-         * as it makes our fist guess (quotient of high-order words)
-         * more accurate!
-         *
-         * Some day, we'll write a stopping test that takes
-         * account of the asymmetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
-        tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
-        if ( Bbits < 64 && tenSbits < 64){
-            if ( Bbits < 32 && tenSbits < 32){
-                // wa-hoo! They're all ints!
-                int b = ((int)fractBits * small5pow[B5] ) << B2;
-                int s = small5pow[S5] << S2;
-                int m = small5pow[M5] << M2;
-                int tens = s * 10;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = b / s;
-                b = 10 * ( b % s );
-                m *= 10;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if ( decExp < -3 || decExp >= 8 ){
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = b / s;
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q; // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                lowDigitDifference = (b<<1) - tens;
-            } else {
-                // still good! they're all longs!
-                long b = (fractBits * long5pow[B5] ) << B2;
-                long s = long5pow[S5] << S2;
-                long m = long5pow[M5] << M2;
-                long tens = s * 10L;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = (int) ( b / s );
-                b = 10L * ( b % s );
-                m *= 10L;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if ( decExp < -3 || decExp >= 8 ){
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = (int) ( b / s );
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q;  // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                lowDigitDifference = (b<<1) - tens;
-            }
-        } else {
-            FDBigInt tenSval;
-            int  shiftBias;
-
-            /*
-             * We really must do FDBigInt arithmetic.
-             * Fist, construct our FDBigInt initial values.
-             */
-            Bval = multPow52( new FDBigInt( fractBits  ), B5, B2 );
-            Sval = constructPow52( S5, S2 );
-            Mval = constructPow52( M5, M2 );
-
-
-            // normalize so that division works better
-            Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
-            Mval.lshiftMe( shiftBias );
-            tenSval = Sval.mult( 10 );
-            /*
-             * Unroll the first iteration. If our decExp estimate
-             * was too high, our first quotient will be zero. In this
-             * case, we discard it and decrement decExp.
-             */
-            ndigit = 0;
-            q = Bval.quoRemIteration( Sval );
-            Mval = Mval.mult( 10 );
-            low  = (Bval.cmp( Mval ) < 0);
-            high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-            assert q < 10 : q; // excessively large digit
-            if ( (q == 0) && ! high ){
-                // oops. Usually ignore leading zero.
-                decExp--;
-            } else {
-                digits[ndigit++] = (char)('0' + q);
-            }
-            /*
-             * HACK! Java spec sez that we always have at least
-             * one digit after the . in either F- or E-form output.
-             * Thus we will need more than one digit if we're using
-             * E-form
-             */
-            if ( decExp < -3 || decExp >= 8 ){
-                high = low = false;
-            }
-            while( ! low && ! high ){
-                q = Bval.quoRemIteration( Sval );
-                Mval = Mval.mult( 10 );
-                assert q < 10 : q;  // excessively large digit
-                low  = (Bval.cmp( Mval ) < 0);
-                high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-                digits[ndigit++] = (char)('0' + q);
-            }
-            if ( high && low ){
-                Bval.lshiftMe(1);
-                lowDigitDifference = Bval.cmp(tenSval);
-            } else
-                lowDigitDifference = 0L; // this here only for flow analysis!
-        }
-        this.decExponent = decExp+1;
-        this.digits = digits;
-        this.nDigits = ndigit;
-        /*
-         * Last digit gets rounded based on stopping condition.
-         */
-        if ( high ){
-            if ( low ){
-                if ( lowDigitDifference == 0L ){
-                    // it's a tie!
-                    // choose based on which digits we like.
-                    if ( (digits[nDigits-1]&1) != 0 ) roundup();
-                } else if ( lowDigitDifference > 0 ){
-                    roundup();
-                }
-            } else {
-                roundup();
-            }
-        }
-    }
-
-    public String
-    toString(){
-        // most brain-dead version
-        StringBuffer result = new StringBuffer( nDigits+8 );
-        if ( isNegative ){ result.append( '-' ); }
-        if ( isExceptional ){
-            result.append( digits, 0, nDigits );
-        } else {
-            result.append( "0.");
-            result.append( digits, 0, nDigits );
-            result.append('e');
-            result.append( decExponent );
-        }
-        return new String(result);
-    }
-
-    public String toJavaFormatString() {
-        char result[] = (char[])(perThreadBuffer.get());
-        int i = getChars(result);
-        return new String(result, 0, i);
-    }
-
-    private int getChars(char[] result) {
-        assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
-        int i = 0;
-        if (isNegative) { result[0] = '-'; i = 1; }
-        if (isExceptional) {
-            System.arraycopy(digits, 0, result, i, nDigits);
-            i += nDigits;
-        } else {
-            if (decExponent > 0 && decExponent < 8) {
-                // case with digits.digits
-                int charLength = Math.min(nDigits, decExponent);
-                System.arraycopy(digits, 0, result, i, charLength);
-                i += charLength;
-                if (charLength < decExponent) {
-                    charLength = decExponent-charLength;
-                    System.arraycopy(zero, 0, result, i, charLength);
-                    i += charLength;
-                    result[i++] = '.';
-                    result[i++] = '0';
-                } else {
-                    result[i++] = '.';
-                    if (charLength < nDigits) {
-                        int t = nDigits - charLength;
-                        System.arraycopy(digits, charLength, result, i, t);
-                        i += t;
-                    } else {
-                        result[i++] = '0';
-                    }
-                }
-            } else if (decExponent <=0 && decExponent > -3) {
-                // case with 0.digits
-                result[i++] = '0';
-                result[i++] = '.';
-                if (decExponent != 0) {
-                    System.arraycopy(zero, 0, result, i, -decExponent);
-                    i -= decExponent;
-                }
-                System.arraycopy(digits, 0, result, i, nDigits);
-                i += nDigits;
-            } else {
-                // case with digit.digitsEexponent
-                result[i++] = digits[0];
-                result[i++] = '.';
-                if (nDigits > 1) {
-                    System.arraycopy(digits, 1, result, i, nDigits-1);
-                    i += nDigits-1;
-                } else {
-                    result[i++] = '0';
-                }
-                result[i++] = 'E';
-                int e;
-                if (decExponent <= 0) {
-                    result[i++] = '-';
-                    e = -decExponent+1;
-                } else {
-                    e = decExponent-1;
-                }
-                // decExponent has 1, 2, or 3, digits
-                if (e <= 9) {
-                    result[i++] = (char)(e+'0');
-                } else if (e <= 99) {
-                    result[i++] = (char)(e/10 +'0');
-                    result[i++] = (char)(e%10 + '0');
-                } else {
-                    result[i++] = (char)(e/100+'0');
-                    e %= 100;
-                    result[i++] = (char)(e/10+'0');
-                    result[i++] = (char)(e%10 + '0');
-                }
-            }
-        }
-        return i;
-    }
-
-    // Per-thread buffer for string/stringbuffer conversion
-    private static ThreadLocal perThreadBuffer = new ThreadLocal() {
-            protected synchronized Object initialValue() {
-                return new char[26];
-            }
-        };
-
-    public void appendTo(AbstractStringBuilder buf) {
-        if (isNegative) { buf.append('-'); }
-        if (isExceptional) {
-            buf.append(digits, 0 , nDigits);
-            return;
-        }
-        if (decExponent > 0 && decExponent < 8) {
-            // print digits.digits.
-            int charLength = Math.min(nDigits, decExponent);
-            buf.append(digits, 0 , charLength);
-            if (charLength < decExponent) {
-                charLength = decExponent-charLength;
-                buf.append(zero, 0 , charLength);
-                buf.append(".0");
-            } else {
-                buf.append('.');
-                if (charLength < nDigits) {
-                    buf.append(digits, charLength, nDigits - charLength);
-                } else {
-                    buf.append('0');
-                }
-            }
-        } else if (decExponent <=0 && decExponent > -3) {
-            buf.append("0.");
-            if (decExponent != 0) {
-                buf.append(zero, 0, -decExponent);
-            }
-            buf.append(digits, 0, nDigits);
-        } else {
-            buf.append(digits[0]);
-            buf.append('.');
-            if (nDigits > 1) {
-                buf.append(digits, 1, nDigits-1);
-            } else {
-                buf.append('0');
-            }
-            buf.append('E');
-            int e;
-            if (decExponent <= 0) {
-                buf.append('-');
-                e = -decExponent + 1;
-            } else {
-                e = decExponent - 1;
-            }
-            // decExponent has 1, 2, or 3, digits
-            if (e <= 9) {
-                buf.append((char)(e + '0'));
-            } else if (e <= 99) {
-                buf.append((char)(e/10 + '0'));
-                buf.append((char)(e%10 + '0'));
-            } else {
-                buf.append((char)(e/100 + '0'));
-                e %= 100;
-                buf.append((char)(e/10 + '0'));
-                buf.append((char)(e%10 + '0'));
-            }
-        }
-    }
-
-    public FloatingDecimal
-    readJavaFormatString( String in ) throws NumberFormatException {
-        boolean isNegative = false;
-        boolean signSeen   = false;
-        int     decExp;
-        char    c;
-
-    parseNumber:
-        try{
-            in = in.trim(); // don't fool around with white space.
-                            // throws NullPointerException if null
-            int l = in.length();
-            if ( l == 0 ) throw new NumberFormatException("empty String");
-            int i = 0;
-            switch ( c = in.charAt( i ) ){
-            case '-':
-                isNegative = true;
-                //FALLTHROUGH
-            case '+':
-                i++;
-                signSeen = true;
-            }
-
-            // Check for NaN and Infinity strings
-            c = in.charAt(i);
-            if(c == 'N' || c == 'I') { // possible NaN or infinity
-                boolean potentialNaN = false;
-                char targetChars[] = null;  // char array of "NaN" or "Infinity"
-
-                if(c == 'N') {
-                    targetChars = notANumber;
-                    potentialNaN = true;
-                } else {
-                    targetChars = infinity;
-                }
-
-                // compare Input string to "NaN" or "Infinity"
-                int j = 0;
-                while(i < l && j < targetChars.length) {
-                    if(in.charAt(i) == targetChars[j]) {
-                        i++; j++;
-                    }
-                    else // something is amiss, throw exception
-                        break parseNumber;
-                }
-
-                // For the candidate string to be a NaN or infinity,
-                // all characters in input string and target char[]
-                // must be matched ==> j must equal targetChars.length
-                // and i must equal l
-                if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
-                    return (potentialNaN ? loadDouble(Double.NaN) // NaN has no sign
-                            : loadDouble(isNegative?
-                                                  Double.NEGATIVE_INFINITY:
-                                                  Double.POSITIVE_INFINITY)) ;
-                }
-                else { // something went wrong, throw exception
-                    break parseNumber;
-                }
-
-            } else if (c == '0')  { // check for hexadecimal floating-point number
-                if (l > i+1 ) {
-                    char ch = in.charAt(i+1);
-                    if (ch == 'x' || ch == 'X' ) // possible hex string
-                        return parseHexString(in);
-                }
-            }  // look for and process decimal floating-point string
-
-            char[] digits = new char[ l ];
-            int    nDigits= 0;
-            boolean decSeen = false;
-            int decPt = 0;
-            int nLeadZero = 0;
-            int nTrailZero= 0;
-        digitLoop:
-            while ( i < l ){
-                switch ( c = in.charAt( i ) ){
-                case '0':
-                    if ( nDigits > 0 ){
-                        nTrailZero += 1;
-                    } else {
-                        nLeadZero += 1;
-                    }
-                    break; // out of switch.
-                case '1':
-                case '2':
-                case '3':
-                case '4':
-                case '5':
-                case '6':
-                case '7':
-                case '8':
-                case '9':
-                    while ( nTrailZero > 0 ){
-                        digits[nDigits++] = '0';
-                        nTrailZero -= 1;
-                    }
-                    digits[nDigits++] = c;
-                    break; // out of switch.
-                case '.':
-                    if ( decSeen ){
-                        // already saw one ., this is the 2nd.
-                        throw new NumberFormatException("multiple points");
-                    }
-                    decPt = i;
-                    if ( signSeen ){
-                        decPt -= 1;
-                    }
-                    decSeen = true;
-                    break; // out of switch.
-                default:
-                    break digitLoop;
-                }
-                i++;
-            }
-            /*
-             * At this point, we've scanned all the digits and decimal
-             * point we're going to see. Trim off leading and trailing
-             * zeros, which will just confuse us later, and adjust
-             * our initial decimal exponent accordingly.
-             * To review:
-             * we have seen i total characters.
-             * nLeadZero of them were zeros before any other digits.
-             * nTrailZero of them were zeros after any other digits.
-             * if ( decSeen ), then a . was seen after decPt characters
-             * ( including leading zeros which have been discarded )
-             * nDigits characters were neither lead nor trailing
-             * zeros, nor point
-             */
-            /*
-             * special hack: if we saw no non-zero digits, then the
-             * answer is zero!
-             * Unfortunately, we feel honor-bound to keep parsing!
-             */
-            if ( nDigits == 0 ){
-                digits = zero;
-                nDigits = 1;
-                if ( nLeadZero == 0 ){
-                    // we saw NO DIGITS AT ALL,
-                    // not even a crummy 0!
-                    // this is not allowed.
-                    break parseNumber; // go throw exception
-                }
-
-            }
-
-            /* Our initial exponent is decPt, adjusted by the number of
-             * discarded zeros. Or, if there was no decPt,
-             * then its just nDigits adjusted by discarded trailing zeros.
-             */
-            if ( decSeen ){
-                decExp = decPt - nLeadZero;
-            } else {
-                decExp = nDigits+nTrailZero;
-            }
-
-            /*
-             * Look for 'e' or 'E' and an optionally signed integer.
-             */
-            if ( (i < l) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
-                int expSign = 1;
-                int expVal  = 0;
-                int reallyBig = Integer.MAX_VALUE / 10;
-                boolean expOverflow = false;
-                switch( in.charAt(++i) ){
-                case '-':
-                    expSign = -1;
-                    //FALLTHROUGH
-                case '+':
-                    i++;
-                }
-                int expAt = i;
-            expLoop:
-                while ( i < l  ){
-                    if ( expVal >= reallyBig ){
-                        // the next character will cause integer
-                        // overflow.
-                        expOverflow = true;
-                    }
-                    switch ( c = in.charAt(i++) ){
-                    case '0':
-                    case '1':
-                    case '2':
-                    case '3':
-                    case '4':
-                    case '5':
-                    case '6':
-                    case '7':
-                    case '8':
-                    case '9':
-                        expVal = expVal*10 + ( (int)c - (int)'0' );
-                        continue;
-                    default:
-                        i--;           // back up.
-                        break expLoop; // stop parsing exponent.
-                    }
-                }
-                int expLimit = bigDecimalExponent+nDigits+nTrailZero;
-                if ( expOverflow || ( expVal > expLimit ) ){
-                    //
-                    // The intent here is to end up with
-                    // infinity or zero, as appropriate.
-                    // The reason for yielding such a small decExponent,
-                    // rather than something intuitive such as
-                    // expSign*Integer.MAX_VALUE, is that this value
-                    // is subject to further manipulation in
-                    // doubleValue() and floatValue(), and I don't want
-                    // it to be able to cause overflow there!
-                    // (The only way we can get into trouble here is for
-                    // really outrageous nDigits+nTrailZero, such as 2 billion. )
-                    //
-                    decExp = expSign*expLimit;
-                } else {
-                    // this should not overflow, since we tested
-                    // for expVal > (MAX+N), where N >= abs(decExp)
-                    decExp = decExp + expSign*expVal;
-                }
-
-                // if we saw something not a digit ( or end of string )
-                // after the [Ee][+-], without seeing any digits at all
-                // this is certainly an error. If we saw some digits,
-                // but then some trailing garbage, that might be ok.
-                // so we just fall through in that case.
-                // HUMBUG
-                if ( i == expAt )
-                    break parseNumber; // certainly bad
-            }
-            /*
-             * We parsed everything we could.
-             * If there are leftovers, then this is not good input!
-             */
-            if ( i < l &&
-                ((i != l - 1) ||
-                (in.charAt(i) != 'f' &&
-                 in.charAt(i) != 'F' &&
-                 in.charAt(i) != 'd' &&
-                 in.charAt(i) != 'D'))) {
-                break parseNumber; // go throw exception
-            }
-
-            this.isNegative = isNegative;
-            this.decExponent = decExp;
-            this.digits = digits;
-            this.nDigits = nDigits;
-            this.isExceptional = false;
-            return this;
-        } catch ( StringIndexOutOfBoundsException e ){ }
-        throw new NumberFormatException("For input string: \"" + in + "\"");
-    }
-
-    /*
-     * Take a FloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a double.
-     *
-     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
-     * ROUNDING DIRECTION in case the result is really destined
-     * for a single-precision float.
-     */
-
-    public strictfp double doubleValue(){
-        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );
-        long    lValue;
-        double  dValue;
-        double  rValue, tValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Double.NaN;
-            else
-                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
-        }
-        else {
-            if (mustSetRoundDir) {
-                roundDir = 0;
-            }
-            /*
-             * convert the lead kDigits to a long integer.
-             */
-            // (special performance hack: start to do it using int)
-            int iValue = (int)digits[0]-(int)'0';
-            int iDigits = Math.min( kDigits, intDecimalDigits );
-            for ( int i=1; i < iDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            lValue = (long)iValue;
-            for ( int i=iDigits; i < kDigits; i++ ){
-                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-            }
-            dValue = (double)lValue;
-            int exp = decExponent-kDigits;
-            /*
-             * lValue now contains a long integer with the value of
-             * the first kDigits digits of the number.
-             * dValue contains the (double) of the same.
-             */
-
-            if ( nDigits <= maxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here
-                 */
-                if (exp == 0 || dValue == 0.0)
-                    return (isNegative)? -dValue : dValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= maxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        rValue = dValue * small10pow[exp];
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    int slop = maxDecimalDigits - kDigits;
-                    if ( exp <= maxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        dValue *= small10pow[slop];
-                        rValue = dValue * small10pow[exp-slop];
-
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp-slop];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -maxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        rValue = dValue / small10pow[-exp];
-                        tValue = rValue * small10pow[-exp];
-                        if ( mustSetRoundDir ){
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            }
-
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by approximating the right answer by,
-             * naively, scaling by powers of 10.
-             */
-            if ( exp > 0 ){
-                if ( decExponent > maxDecimalExponent+1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * Infinity. Cut to the chase.
-                     */
-                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue *= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= big10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could overflow.
-                     */
-                    double t = dValue * big10pow[j];
-                    if ( Double.isInfinite( t ) ){
-                        /*
-                         * It did overflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too large,
-                         * then use the maximum finite as our estimate
-                         * value. Else call the result infinity
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two larger than
-                         * Double.MAX_VALUE ).
-                         */
-                        t = dValue / 2.0;
-                        t *= big10pow[j];
-                        if ( Double.isInfinite( t ) ){
-                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                        }
-                        t = Double.MAX_VALUE;
-                    }
-                    dValue = t;
-                }
-            } else if ( exp < 0 ){
-                exp = -exp;
-                if ( decExponent < minDecimalExponent-1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * zero. Cut to the chase.
-                     */
-                    return (isNegative)? -0.0 : 0.0;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue /= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= tiny10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could underflow.
-                     */
-                    double t = dValue * tiny10pow[j];
-                    if ( t == 0.0 ){
-                        /*
-                         * It did underflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too small,
-                         * then use the minimum finite as our estimate
-                         * value. Else call the result 0.0
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two less than
-                         * Double.MIN_VALUE ).
-                         */
-                        t = dValue * 2.0;
-                        t *= tiny10pow[j];
-                        if ( t == 0.0 ){
-                            return (isNegative)? -0.0 : 0.0;
-                        }
-                        t = Double.MIN_VALUE;
-                    }
-                    dValue = t;
-                }
-            }
-
-            /*
-             * dValue is now approximately the result.
-             * The hard part is adjusting it, by comparison
-             * with FDBigInt arithmetic.
-             * Formulate the EXACT big-number result as
-             * bigD0 * 10^exp
-             */
-            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
-            exp   = decExponent - nDigits;
-
-            correctionLoop:
-            while(true){
-                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-                 * bigIntExp and bigIntNBits
-                 */
-                FDBigInt bigB = doubleToBigInt( dValue );
-
-                /*
-                 * Scale bigD, bigB appropriately for
-                 * big-integer operations.
-                 * Naively, we multiply by powers of ten
-                 * and powers of two. What we actually do
-                 * is keep track of the powers of 5 and
-                 * powers of 2 we would use, then factor out
-                 * common divisors before doing the work.
-                 */
-                int B2, B5; // powers of 2, 5 in bigB
-                int     D2, D5; // powers of 2, 5 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if ( exp >= 0 ){
-                    B2 = B5 = 0;
-                    D2 = D5 = exp;
-                } else {
-                    B2 = B5 = -exp;
-                    D2 = D5 = 0;
-                }
-                if ( bigIntExp >= 0 ){
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if ( bigIntExp+bigIntNBits <= -expBias+1 ){
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(expBias+expShift+1)
-                    hulpbias = bigIntExp+ expBias + expShift;
-                } else {
-                    hulpbias = expShift + 2 - bigIntNBits;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                bigB = multPow52( bigB, B5, B2 );
-                FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
-                //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
-                //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
-                //
-                FDBigInt diff;
-                int cmpResult;
-                boolean overvalue;
-                if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
-                        // candidate is a normalized exact power of 2 and
-                        // is too big. We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if ( Ulp2 < 0 ){
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff.lshiftMe( 1 );
-                        }
-                    }
-                } else if ( cmpResult < 0 ){
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.sub( bigB );
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising frequency
-                    break correctionLoop;
-                }
-                FDBigInt halfUlp = constructPow52( B5, Ulp2 );
-                if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
-                    // difference is small.
-                    // this is close enough
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else if ( cmpResult == 0 ){
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    dValue += 0.5*ulp( dValue, overvalue );
-                    // should check for bigIntNBits == 1 here??
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    dValue += ulp( dValue, overvalue );
-                    if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
-                        break correctionLoop; // oops. Fell off end of range.
-                    continue; // try again.
-                }
-
-            }
-            return (isNegative)? -dValue : dValue;
-        }
-    }
-
-    /*
-     * Take a FloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a float.
-     * This is distinct from doubleValue() to avoid the extremely
-     * unlikely case of a double rounding error, wherein the conversion
-     * to double has one rounding error, and the conversion of that double
-     * to a float has another rounding error, IN THE WRONG DIRECTION,
-     * ( because of the preference to a zero low-order bit ).
-     */
-
-    public strictfp float floatValue(){
-        int     kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
-        int     iValue;
-        float   fValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Float.NaN;
-            else
-                return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
-        }
-        else {
-            /*
-             * convert the lead kDigits to an integer.
-             */
-            iValue = (int)digits[0]-(int)'0';
-            for ( int i=1; i < kDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            fValue = (float)iValue;
-            int exp = decExponent-kDigits;
-            /*
-             * iValue now contains an integer with the value of
-             * the first kDigits digits of the number.
-             * fValue contains the (float) of the same.
-             */
-
-            if ( nDigits <= singleMaxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here.
-                 */
-                if (exp == 0 || fValue == 0.0f)
-                    return (isNegative)? -fValue : fValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= singleMaxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        fValue *= singleSmall10pow[exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    int slop = singleMaxDecimalDigits - kDigits;
-                    if ( exp <= singleMaxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        fValue *= singleSmall10pow[slop];
-                        fValue *= singleSmall10pow[exp-slop];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -singleMaxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        fValue /= singleSmall10pow[-exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
-                /*
-                 * In double-precision, this is an exact floating integer.
-                 * So we can compute to double, then shorten to float
-                 * with one round, and get the right answer.
-                 *
-                 * First, finish accumulating digits.
-                 * Then convert that integer to a double, multiply
-                 * by the appropriate power of ten, and convert to float.
-                 */
-                long lValue = (long)iValue;
-                for ( int i=kDigits; i < nDigits; i++ ){
-                    lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-                }
-                double dValue = (double)lValue;
-                exp = decExponent-nDigits;
-                dValue *= small10pow[exp];
-                fValue = (float)dValue;
-                return (isNegative)? -fValue : fValue;
-
-            }
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by weeding out obviously out-of-range
-             * results, then convert to double and go to
-             * common hard-case code.
-             */
-            if ( decExponent > singleMaxDecimalExponent+1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * Infinity. Cut to the chase.
-                 */
-                return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-            } else if ( decExponent < singleMinDecimalExponent-1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * zero. Cut to the chase.
-                 */
-                return (isNegative)? -0.0f : 0.0f;
-            }
-
-            /*
-             * Here, we do 'way too much work, but throwing away
-             * our partial results, and going and doing the whole
-             * thing as double, then throwing away half the bits that computes
-             * when we convert back to float.
-             *
-             * The alternative is to reproduce the whole multiple-precision
-             * algorithm for float precision, or to try to parameterize it
-             * for common usage. The former will take about 400 lines of code,
-             * and the latter I tried without success. Thus the semi-hack
-             * answer here.
-             */
-            mustSetRoundDir = !fromHex;
-            double dValue = doubleValue();
-            return stickyRound( dValue );
-        }
-    }
-
-
-    /*
-     * All the positive powers of 10 that can be
-     * represented exactly in double/float.
-     */
-    private static final double small10pow[] = {
-        1.0e0,
-        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
-        1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
-        1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
-        1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
-        1.0e21, 1.0e22
-    };
-
-    private static final float singleSmall10pow[] = {
-        1.0e0f,
-        1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
-        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
-    };
-
-    private static final double big10pow[] = {
-        1e16, 1e32, 1e64, 1e128, 1e256 };
-    private static final double tiny10pow[] = {
-        1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
-    private static final int maxSmallTen = small10pow.length-1;
-    private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
-    private static final int small5pow[] = {
-        1,
-        5,
-        5*5,
-        5*5*5,
-        5*5*5*5,
-        5*5*5*5*5,
-        5*5*5*5*5*5,
-        5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5*5
-    };
-
-
-    private static final long long5pow[] = {
-        1L,
-        5L,
-        5L*5,
-        5L*5*5,
-        5L*5*5*5,
-        5L*5*5*5*5,
-        5L*5*5*5*5*5,
-        5L*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-    };
-
-    // approximately ceil( log2( long5pow[i] ) )
-    private static final int n5bits[] = {
-        0,
-        3,
-        5,
-        7,
-        10,
-        12,
-        14,
-        17,
-        19,
-        21,
-        24,
-        26,
-        28,
-        31,
-        33,
-        35,
-        38,
-        40,
-        42,
-        45,
-        47,
-        49,
-        52,
-        54,
-        56,
-        59,
-        61,
-    };
-
-    private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
-    private static final char notANumber[] = { 'N', 'a', 'N' };
-    private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
-
-
-    /*
-     * Grammar is compatible with hexadecimal floating-point constants
-     * described in section 6.4.4.2 of the C99 specification.
-     */
-    private static Pattern hexFloatPattern = null;
-    private static synchronized Pattern getHexFloatPattern() {
-        if (hexFloatPattern == null) {
-           hexFloatPattern = Pattern.compile(
-                   //1           234                   56                7                   8      9
-                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
-                    );
-        }
-        return hexFloatPattern;
-    }
-
-    /*
-     * Convert string s to a suitable floating decimal; uses the
-     * double constructor and set the roundDir variable appropriately
-     * in case the value is later converted to a float.
-     */
-    FloatingDecimal parseHexString(String s) {
-        // Verify string is a member of the hexadecimal floating-point
-        // string language.
-        Matcher m = getHexFloatPattern().matcher(s);
-        boolean validInput = m.matches();
-
-        if (!validInput) {
-            // Input does not match pattern
-            throw new NumberFormatException("For input string: \"" + s + "\"");
-        } else { // validInput
-            /*
-             * We must isolate the sign, significand, and exponent
-             * fields.  The sign value is straightforward.  Since
-             * floating-point numbers are stored with a normalized
-             * representation, the significand and exponent are
-             * interrelated.
-             *
-             * After extracting the sign, we normalized the
-             * significand as a hexadecimal value, calculating an
-             * exponent adjust for any shifts made during
-             * normalization.  If the significand is zero, the
-             * exponent doesn't need to be examined since the output
-             * will be zero.
-             *
-             * Next the exponent in the input string is extracted.
-             * Afterwards, the significand is normalized as a *binary*
-             * value and the input value's normalized exponent can be
-             * computed.  The significand bits are copied into a
-             * double significand; if the string has more logical bits
-             * than can fit in a double, the extra bits affect the
-             * round and sticky bits which are used to round the final
-             * value.
-             */
-
-            //  Extract significand sign
-            String group1 = m.group(1);
-            double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
-
-
-            //  Extract Significand magnitude
-            /*
-             * Based on the form of the significand, calculate how the
-             * binary exponent needs to be adjusted to create a
-             * normalized *hexadecimal* floating-point number; that
-             * is, a number where there is one nonzero hex digit to
-             * the left of the (hexa)decimal point.  Since we are
-             * adjusting a binary, not hexadecimal exponent, the
-             * exponent is adjusted by a multiple of 4.
-             *
-             * There are a number of significand scenarios to consider;
-             * letters are used in indicate nonzero digits:
-             *
-             * 1. 000xxxx       =>      x.xxx   normalized
-             *    increase exponent by (number of x's - 1)*4
-             *
-             * 2. 000xxx.yyyy =>        x.xxyyyy        normalized
-             *    increase exponent by (number of x's - 1)*4
-             *
-             * 3. .000yyy  =>   y.yy    normalized
-             *    decrease exponent by (number of zeros + 1)*4
-             *
-             * 4. 000.00000yyy => y.yy normalized
-             *    decrease exponent by (number of zeros to right of point + 1)*4
-             *
-             * If the significand is exactly zero, return a properly
-             * signed zero.
-             */
-
-            String significandString =null;
-            int signifLength = 0;
-            int exponentAdjust = 0;
-            {
-                int leftDigits  = 0; // number of meaningful digits to
-                                     // left of "decimal" point
-                                     // (leading zeros stripped)
-                int rightDigits = 0; // number of digits to right of
-                                     // "decimal" point; leading zeros
-                                     // must always be accounted for
-                /*
-                 * The significand is made up of either
-                 *
-                 * 1. group 4 entirely (integer portion only)
-                 *
-                 * OR
-                 *
-                 * 2. the fractional portion from group 7 plus any
-                 * (optional) integer portions from group 6.
-                 */
-                String group4;
-                if( (group4 = m.group(4)) != null) {  // Integer-only significand
-                    // Leading zeros never matter on the integer portion
-                    significandString = stripLeadingZeros(group4);
-                    leftDigits = significandString.length();
-                }
-                else {
-                    // Group 6 is the optional integer; leading zeros
-                    // never matter on the integer portion
-                    String group6 = stripLeadingZeros(m.group(6));
-                    leftDigits = group6.length();
-
-                    // fraction
-                    String group7 = m.group(7);
-                    rightDigits = group7.length();
-
-                    // Turn "integer.fraction" into "integer"+"fraction"
-                    significandString =
-                        ((group6 == null)?"":group6) + // is the null
-                        // check necessary?
-                        group7;
-                }
-
-                significandString = stripLeadingZeros(significandString);
-                signifLength  = significandString.length();
-
-                /*
-                 * Adjust exponent as described above
-                 */
-                if (leftDigits >= 1) {  // Cases 1 and 2
-                    exponentAdjust = 4*(leftDigits - 1);
-                } else {                // Cases 3 and 4
-                    exponentAdjust = -4*( rightDigits - signifLength + 1);
-                }
-
-                // If the significand is zero, the exponent doesn't
-                // matter; return a properly signed zero.
-
-                if (signifLength == 0) { // Only zeros in input
-                    return loadDouble(sign * 0.0);
-                }
-            }
-
-            //  Extract Exponent
-            /*
-             * Use an int to read in the exponent value; this should
-             * provide more than sufficient range for non-contrived
-             * inputs.  If reading the exponent in as an int does
-             * overflow, examine the sign of the exponent and
-             * significand to determine what to do.
-             */
-            String group8 = m.group(8);
-            boolean positiveExponent = ( group8 == null ) || group8.equals("+");
-            long unsignedRawExponent;
-            try {
-                unsignedRawExponent = Integer.parseInt(m.group(9));
-            }
-            catch (NumberFormatException e) {
-                // At this point, we know the exponent is
-                // syntactically well-formed as a sequence of
-                // digits.  Therefore, if an NumberFormatException
-                // is thrown, it must be due to overflowing int's
-                // range.  Also, at this point, we have already
-                // checked for a zero significand.  Thus the signs
-                // of the exponent and significand determine the
-                // final result:
-                //
-                //                      significand
-                //                      +               -
-                // exponent     +       +infinity       -infinity
-                //              -       +0.0            -0.0
-                return loadDouble(sign * (positiveExponent ?
-                                          Double.POSITIVE_INFINITY : 0.0));
-            }
-
-            long rawExponent =
-                (positiveExponent ? 1L : -1L) * // exponent sign
-                unsignedRawExponent;            // exponent magnitude
-
-            // Calculate partially adjusted exponent
-            long exponent = rawExponent + exponentAdjust ;
-
-            // Starting copying non-zero bits into proper position in
-            // a long; copy explicit bit too; this will be masked
-            // later for normal values.
-
-            boolean round = false;
-            boolean sticky = false;
-            int bitsCopied=0;
-            int nextShift=0;
-            long significand=0L;
-            // First iteration is different, since we only copy
-            // from the leading significand bit; one more exponent
-            // adjust will be needed...
-
-            // IMPORTANT: make leadingDigit a long to avoid
-            // surprising shift semantics!
-            long leadingDigit = getHexDigit(significandString, 0);
-
-            /*
-             * Left shift the leading digit (53 - (bit position of
-             * leading 1 in digit)); this sets the top bit of the
-             * significand to 1.  The nextShift value is adjusted
-             * to take into account the number of bit positions of
-             * the leadingDigit actually used.  Finally, the
-             * exponent is adjusted to normalize the significand
-             * as a binary value, not just a hex value.
-             */
-            if (leadingDigit == 1) {
-                significand |= leadingDigit << 52;
-                nextShift = 52 - 4;
-                /* exponent += 0 */     }
-            else if (leadingDigit <= 3) { // [2, 3]
-                significand |= leadingDigit << 51;
-                nextShift = 52 - 5;
-                exponent += 1;
-            }
-            else if (leadingDigit <= 7) { // [4, 7]
-                significand |= leadingDigit << 50;
-                nextShift = 52 - 6;
-                exponent += 2;
-            }
-            else if (leadingDigit <= 15) { // [8, f]
-                significand |= leadingDigit << 49;
-                nextShift = 52 - 7;
-                exponent += 3;
-            } else {
-                throw new AssertionError("Result from digit conversion too large!");
-            }
-            // The preceding if-else could be replaced by a single
-            // code block based on the high-order bit set in
-            // leadingDigit.  Given leadingOnePosition,
-
-            // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
-            // nextShift = 52 - (3 + leadingOnePosition);
-            // exponent += (leadingOnePosition-1);
-
-
-            /*
-             * Now the exponent variable is equal to the normalized
-             * binary exponent.  Code below will make representation
-             * adjustments if the exponent is incremented after
-             * rounding (includes overflows to infinity) or if the
-             * result is subnormal.
-             */
-
-            // Copy digit into significand until the significand can't
-            // hold another full hex digit or there are no more input
-            // hex digits.
-            int i = 0;
-            for(i = 1;
-                i < signifLength && nextShift >= 0;
-                i++) {
-                long currentDigit = getHexDigit(significandString, i);
-                significand |= (currentDigit << nextShift);
-                nextShift-=4;
-            }
-
-            // After the above loop, the bulk of the string is copied.
-            // Now, we must copy any partial hex digits into the
-            // significand AND compute the round bit and start computing
-            // sticky bit.
-
-            if ( i < signifLength ) { // at least one hex input digit exists
-                long currentDigit = getHexDigit(significandString, i);
-
-                // from nextShift, figure out how many bits need
-                // to be copied, if any
-                switch(nextShift) { // must be negative
-                case -1:
-                    // three bits need to be copied in; can
-                    // set round bit
-                    significand |= ((currentDigit & 0xEL) >> 1);
-                    round = (currentDigit & 0x1L)  != 0L;
-                    break;
-
-                case -2:
-                    // two bits need to be copied in; can
-                    // set round and start sticky
-                    significand |= ((currentDigit & 0xCL) >> 2);
-                    round = (currentDigit &0x2L)  != 0L;
-                    sticky = (currentDigit & 0x1L) != 0;
-                    break;
-
-                case -3:
-                    // one bit needs to be copied in
-                    significand |= ((currentDigit & 0x8L)>>3);
-                    // Now set round and start sticky, if possible
-                    round = (currentDigit &0x4L)  != 0L;
-                    sticky = (currentDigit & 0x3L) != 0;
-                    break;
-
-                case -4:
-                    // all bits copied into significand; set
-                    // round and start sticky
-                    round = ((currentDigit & 0x8L) != 0);  // is top bit set?
-                    // nonzeros in three low order bits?
-                    sticky = (currentDigit & 0x7L) != 0;
-                    break;
-
-                default:
-                    throw new AssertionError("Unexpected shift distance remainder.");
-                    // break;
-                }
-
-                // Round is set; sticky might be set.
-
-                // For the sticky bit, it suffices to check the
-                // current digit and test for any nonzero digits in
-                // the remaining unprocessed input.
-                i++;
-                while(i < signifLength && !sticky) {
-                    currentDigit =  getHexDigit(significandString,i);
-                    sticky = sticky || (currentDigit != 0);
-                    i++;
-                }
-
-            }
-            // else all of string was seen, round and sticky are
-            // correct as false.
-
-
-            // Check for overflow and update exponent accordingly.
-
-            if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
-                // overflow to properly signed infinity
-                return loadDouble(sign * Double.POSITIVE_INFINITY);
-            } else {  // Finite return value
-                if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
-                    exponent >= DoubleConsts.MIN_EXPONENT) {
-
-                    // The result returned in this block cannot be a
-                    // zero or subnormal; however after the
-                    // significand is adjusted from rounding, we could
-                    // still overflow in infinity.
-
-                    // AND exponent bits into significand; if the
-                    // significand is incremented and overflows from
-                    // rounding, this combination will update the
-                    // exponent correctly, even in the case of
-                    // Double.MAX_VALUE overflowing to infinity.
-
-                    significand = (( ((long)exponent +
-                                     (long)DoubleConsts.EXP_BIAS) <<
-                                     (DoubleConsts.SIGNIFICAND_WIDTH-1))
-                                   & DoubleConsts.EXP_BIT_MASK) |
-                        (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
-                }  else  {  // Subnormal or zero
-                    // (exponent < DoubleConsts.MIN_EXPONENT)
-
-                    if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
-                        // No way to round back to nonzero value
-                        // regardless of significand if the exponent is
-                        // less than -1075.
-                        return loadDouble(sign * 0.0);
-                    } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
-                        /*
-                         * Find bit position to round to; recompute
-                         * round and sticky bits, and shift
-                         * significand right appropriately.
-                         */
-
-                        sticky = sticky || round;
-                        round = false;
-
-                        // Number of bits of significand to preserve is
-                        // exponent - abs_min_exp +1
-                        // check:
-                        // -1075 +1074 + 1 = 0
-                        // -1023 +1074 + 1 = 52
-
-                        int bitsDiscarded = 53 -
-                            ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
-                        assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
-                        // What to do here:
-                        // First, isolate the new round bit
-                        round = (significand & (1L << (bitsDiscarded -1))) != 0L;
-                        if (bitsDiscarded > 1) {
-                            // create mask to update sticky bits; low
-                            // order bitsDiscarded bits should be 1
-                            long mask = ~((~0L) << (bitsDiscarded -1));
-                            sticky = sticky || ((significand & mask) != 0L ) ;
-                        }
-
-                        // Now, discard the bits
-                        significand = significand >> bitsDiscarded;
-
-                        significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp.
-                                          (long)DoubleConsts.EXP_BIAS) <<
-                                         (DoubleConsts.SIGNIFICAND_WIDTH-1))
-                                       & DoubleConsts.EXP_BIT_MASK) |
-                            (DoubleConsts.SIGNIF_BIT_MASK & significand);
-                    }
-                }
-
-                // The significand variable now contains the currently
-                // appropriate exponent bits too.
-
-                /*
-                 * Determine if significand should be incremented;
-                 * making this determination depends on the least
-                 * significant bit and the round and sticky bits.
-                 *
-                 * Round to nearest even rounding table, adapted from
-                 * table 4.7 in "Computer Arithmetic" by IsraelKoren.
-                 * The digit to the left of the "decimal" point is the
-                 * least significant bit, the digits to the right of
-                 * the point are the round and sticky bits
-                 *
-                 * Number       Round(x)
-                 * x0.00        x0.
-                 * x0.01        x0.
-                 * x0.10        x0.
-                 * x0.11        x1. = x0. +1
-                 * x1.00        x1.
-                 * x1.01        x1.
-                 * x1.10        x1. + 1
-                 * x1.11        x1. + 1
-                 */
-                boolean incremented = false;
-                boolean leastZero  = ((significand & 1L) == 0L);
-                if( (  leastZero  && round && sticky ) ||
-                    ((!leastZero) && round )) {
-                    incremented = true;
-                    significand++;
-                }
-
-                loadDouble(FpUtils.rawCopySign(
-                                               Double.longBitsToDouble(significand),
-                                               sign));
-
-                /*
-                 * Set roundingDir variable field of fd properly so
-                 * that the input string can be properly rounded to a
-                 * float value.  There are two cases to consider:
-                 *
-                 * 1. rounding to double discards sticky bit
-                 * information that would change the result of a float
-                 * rounding (near halfway case between two floats)
-                 *
-                 * 2. rounding to double rounds up when rounding up
-                 * would not occur when rounding to float.
-                 *
-                 * For former case only needs to be considered when
-                 * the bits rounded away when casting to float are all
-                 * zero; otherwise, float round bit is properly set
-                 * and sticky will already be true.
-                 *
-                 * The lower exponent bound for the code below is the
-                 * minimum (normalized) subnormal exponent - 1 since a
-                 * value with that exponent can round up to the
-                 * minimum subnormal value and the sticky bit
-                 * information must be preserved (i.e. case 1).
-                 */
-                if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
-                    (exponent <= FloatConsts.MAX_EXPONENT ) ){
-                    // Outside above exponent range, the float value
-                    // will be zero or infinity.
-
-                    /*
-                     * If the low-order 28 bits of a rounded double
-                     * significand are 0, the double could be a
-                     * half-way case for a rounding to float.  If the
-                     * double value is a half-way case, the double
-                     * significand may have to be modified to round
-                     * the the right float value (see the stickyRound
-                     * method).  If the rounding to double has lost
-                     * what would be float sticky bit information, the
-                     * double significand must be incremented.  If the
-                     * double value's significand was itself
-                     * incremented, the float value may end up too
-                     * large so the increment should be undone.
-                     */
-                    if ((significand & 0xfffffffL) ==  0x0L) {
-                        // For negative values, the sign of the
-                        // roundDir is the same as for positive values
-                        // since adding 1 increasing the significand's
-                        // magnitude and subtracting 1 decreases the
-                        // significand's magnitude.  If neither round
-                        // nor sticky is true, the double value is
-                        // exact and no adjustment is required for a
-                        // proper float rounding.
-                        if( round || sticky) {
-                            if (leastZero) { // prerounding lsb is 0
-                                // If round and sticky were both true,
-                                // and the least significant
-                                // significand bit were 0, the rounded
-                                // significand would not have its
-                                // low-order bits be zero.  Therefore,
-                                // we only need to adjust the
-                                // significand if round XOR sticky is
-                                // true.
-                                if (round ^ sticky) {
-                                    this.roundDir =  1;
-                                }
-                            }
-                            else { // prerounding lsb is 1
-                                // If the prerounding lsb is 1 and the
-                                // resulting significand has its
-                                // low-order bits zero, the significand
-                                // was incremented.  Here, we undo the
-                                // increment, which will ensure the
-                                // right guard and sticky bits for the
-                                // float rounding.
-                                if (round)
-                                    this.roundDir =  -1;
-                            }
-                        }
-                    }
-                }
-
-                this.fromHex = true;
-                return this;
-            }
-        }
-    }
-
-    /**
-     * Return <code>s</code> with any leading zeros removed.
-     */
-    static String stripLeadingZeros(String s) {
-        return  s.replaceFirst("^0+", "");
-    }
-
-    /**
-     * Extract a hexadecimal digit from position <code>position</code>
-     * of string <code>s</code>.
-     */
-    static int getHexDigit(String s, int position) {
-        int value = Character.digit(s.charAt(position), 16);
-        if (value <= -1 || value >= 16) {
-            throw new AssertionError("Unexpected failure of digit conversion of " +
-                                     s.charAt(position));
-        }
-        return value;
-    }
-
-
-}
diff --git a/ojluni/src/main/java/java/lang/Runtime.java b/ojluni/src/main/java/java/lang/Runtime.java
index 61c2502..eb01061 100755
--- a/ojluni/src/main/java/java/lang/Runtime.java
+++ b/ojluni/src/main/java/java/lang/Runtime.java
@@ -868,7 +868,7 @@
      */
     @CallerSensitive
     public void load(String filename) {
-        load0(VMStack.getStackClass2(), filename);
+        load0(VMStack.getStackClass1(), filename);
     }
 
     // Fixes b/25859957 regression. Depending on private methods is bad, mkay.
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 94b949e..ea5a642 100755
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -34,6 +34,8 @@
 import java.util.Comparator;
 import java.util.Formatter;
 import java.util.Locale;
+import java.util.Objects;
+import java.util.StringJoiner;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -42,23 +44,23 @@
 import libcore.util.EmptyArray;
 
 /**
- * The <code>String</code> class represents character strings. All
- * string literals in Java programs, such as <code>"abc"</code>, are
+ * The {@code String} class represents character strings. All
+ * string literals in Java programs, such as {@code "abc"}, are
  * implemented as instances of this class.
  * <p>
  * Strings are constant; their values cannot be changed after they
  * are created. String buffers support mutable strings.
  * Because String objects are immutable they can be shared. For example:
- * <p><blockquote><pre>
+ * <blockquote><pre>
  *     String str = "abc";
  * </pre></blockquote><p>
  * is equivalent to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
  *     char data[] = {'a', 'b', 'c'};
  *     String str = new String(data);
  * </pre></blockquote><p>
  * Here are some more examples of how strings can be used:
- * <p><blockquote><pre>
+ * <blockquote><pre>
  *     System.out.println("abc");
  *     String cde = "cde";
  *     System.out.println("abc" + cde);
@@ -66,7 +68,7 @@
  *     String d = cde.substring(1, 2);
  * </pre></blockquote>
  * <p>
- * The class <code>String</code> includes methods for examining
+ * The class {@code String} includes methods for examining
  * individual characters of the sequence, for comparing strings, for
  * searching strings, for extracting substrings, and for creating a
  * copy of a string with all characters translated to uppercase or to
@@ -76,10 +78,10 @@
  * The Java language provides special support for the string
  * concatenation operator (&nbsp;+&nbsp;), and for conversion of
  * other objects to strings. String concatenation is implemented
- * through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
- * class and its <code>append</code> method.
+ * through the {@code StringBuilder}(or {@code StringBuffer})
+ * class and its {@code append} method.
  * String conversions are implemented through the method
- * <code>toString</code>, defined by <code>Object</code> and
+ * {@code toString}, defined by {@code Object} and
  * inherited by all classes in Java. For additional information on
  * string concatenation and conversion, see Gosling, Joy, and Steele,
  * <i>The Java Language Specification</i>.
@@ -88,16 +90,16 @@
  * or method in this class will cause a {@link NullPointerException} to be
  * thrown.
  *
- * <p>A <code>String</code> represents a string in the UTF-16 format
+ * <p>A {@code String} represents a string in the UTF-16 format
  * in which <em>supplementary characters</em> are represented by <em>surrogate
  * pairs</em> (see the section <a href="Character.html#unicode">Unicode
- * Character Representations</a> in the <code>Character</code> class for
+ * Character Representations</a> in the {@code Character} class for
  * more information).
- * Index values refer to <code>char</code> code units, so a supplementary
- * character uses two positions in a <code>String</code>.
- * <p>The <code>String</code> class provides methods for dealing with
+ * Index values refer to {@code char} code units, so a supplementary
+ * character uses two positions in a {@code String}.
+ * <p>The {@code String} class provides methods for dealing with
  * Unicode code points (i.e., characters), in addition to those for
- * dealing with Unicode code units (i.e., <code>char</code> values).
+ * dealing with Unicode code units (i.e., {@code char} values).
  *
  * @author  Lee Boynton
  * @author  Arthur van Hoff
@@ -113,7 +115,7 @@
 public final class String
     implements java.io.Serializable, Comparable<String>, CharSequence {
 
-    // The associated character storage is managed by the runtime. We only
+    // dThe associated character storage is managed by the runtime. We only
     // keep track of the length here.
     //
     // private final char value[];
@@ -128,17 +130,12 @@
     /**
      * Class String is special cased within the Serialization Stream Protocol.
      *
-     * A String instance is written initially into an ObjectOutputStream in the
-     * following format:
-     * <pre>
-     *      <code>TC_STRING</code> (utf String)
-     * </pre>
-     * The String is written by method <code>DataOutput.writeUTF</code>.
-     * A new handle is generated to  refer to all future references to the
-     * string instance within the stream.
+     * A String instance is written into an ObjectOutputStream according to
+     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
+     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
      */
     private static final ObjectStreamField[] serialPersistentFields =
-            new ObjectStreamField[0];
+        new ObjectStreamField[0];
 
     /**
      * Initializes a newly created {@code String} object so that it represents
@@ -542,10 +539,10 @@
     }
 
     /**
-     * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
+     * Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
      *
-     * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise
-     * <tt>false</tt>
+     * @return {@code true} if {@link #length()} is {@code 0}, otherwise
+     * {@code false}
      *
      * @since 1.6
      */
@@ -554,20 +551,20 @@
     }
 
     /**
-     * Returns the <code>char</code> value at the
-     * specified index. An index ranges from <code>0</code> to
-     * <code>length() - 1</code>. The first <code>char</code> value of the sequence
-     * is at index <code>0</code>, the next at index <code>1</code>,
+     * Returns the {@code char} value at the
+     * specified index. An index ranges from {@code 0} to
+     * {@code length() - 1}. The first {@code char} value of the sequence
+     * is at index {@code 0}, the next at index {@code 1},
      * and so on, as for array indexing.
      *
-     * <p>If the <code>char</code> value specified by the index is a
+     * <p>If the {@code char} value specified by the index is a
      * <a href="Character.html#unicode">surrogate</a>, the surrogate
      * value is returned.
      *
-     * @param      index   the index of the <code>char</code> value.
-     * @return     the <code>char</code> value at the specified index of this string.
-     *             The first <code>char</code> value is at index <code>0</code>.
-     * @exception  IndexOutOfBoundsException  if the <code>index</code>
+     * @param      index   the index of the {@code char} value.
+     * @return     the {@code char} value at the specified index of this string.
+     *             The first {@code char} value is at index {@code 0}.
+     * @exception  IndexOutOfBoundsException  if the {@code index}
      *             argument is negative or not less than the length of this
      *             string.
      */
@@ -577,22 +574,22 @@
 
     /**
      * Returns the character (Unicode code point) at the specified
-     * index. The index refers to <code>char</code> values
-     * (Unicode code units) and ranges from <code>0</code> to
-     * {@link #length()}<code> - 1</code>.
+     * index. The index refers to {@code char} values
+     * (Unicode code units) and ranges from {@code 0} to
+     * {@link #length()}{@code  - 1}.
      *
-     * <p> If the <code>char</code> value specified at the given index
+     * <p> If the {@code char} value specified at the given index
      * is in the high-surrogate range, the following index is less
-     * than the length of this <code>String</code>, and the
-     * <code>char</code> value at the following index is in the
+     * than the length of this {@code String}, and the
+     * {@code char} value at the following index is in the
      * low-surrogate range, then the supplementary code point
      * corresponding to this surrogate pair is returned. Otherwise,
-     * the <code>char</code> value at the given index is returned.
+     * the {@code char} value at the given index is returned.
      *
-     * @param      index the index to the <code>char</code> values
+     * @param      index the index to the {@code char} values
      * @return     the code point value of the character at the
-     *             <code>index</code>
-     * @exception  IndexOutOfBoundsException  if the <code>index</code>
+     *             {@code index}
+     * @exception  IndexOutOfBoundsException  if the {@code index}
      *             argument is negative or not less than the length of this
      *             string.
      * @since      1.5
@@ -606,22 +603,22 @@
 
     /**
      * Returns the character (Unicode code point) before the specified
-     * index. The index refers to <code>char</code> values
-     * (Unicode code units) and ranges from <code>1</code> to {@link
+     * index. The index refers to {@code char} values
+     * (Unicode code units) and ranges from {@code 1} to {@link
      * CharSequence#length() length}.
      *
-     * <p> If the <code>char</code> value at <code>(index - 1)</code>
-     * is in the low-surrogate range, <code>(index - 2)</code> is not
-     * negative, and the <code>char</code> value at <code>(index -
-     * 2)</code> is in the high-surrogate range, then the
+     * <p> If the {@code char} value at {@code (index - 1)}
+     * is in the low-surrogate range, {@code (index - 2)} is not
+     * negative, and the {@code char} value at {@code (index -
+     * 2)} is in the high-surrogate range, then the
      * supplementary code point value of the surrogate pair is
-     * returned. If the <code>char</code> value at <code>index -
-     * 1</code> is an unpaired low-surrogate or a high-surrogate, the
+     * returned. If the {@code char} value at {@code index -
+     * 1} is an unpaired low-surrogate or a high-surrogate, the
      * surrogate value is returned.
      *
      * @param     index the index following the code point that should be returned
      * @return    the Unicode code point value before the given index.
-     * @exception IndexOutOfBoundsException if the <code>index</code>
+     * @exception IndexOutOfBoundsException if the {@code index}
      *            argument is less than 1 or greater than the length
      *            of this string.
      * @since     1.5
@@ -636,23 +633,23 @@
 
     /**
      * Returns the number of Unicode code points in the specified text
-     * range of this <code>String</code>. The text range begins at the
-     * specified <code>beginIndex</code> and extends to the
-     * <code>char</code> at index <code>endIndex - 1</code>. Thus the
-     * length (in <code>char</code>s) of the text range is
-     * <code>endIndex-beginIndex</code>. Unpaired surrogates within
+     * range of this {@code String}. The text range begins at the
+     * specified {@code beginIndex} and extends to the
+     * {@code char} at index {@code endIndex - 1}. Thus the
+     * length (in {@code char}s) of the text range is
+     * {@code endIndex-beginIndex}. Unpaired surrogates within
      * the text range count as one code point each.
      *
-     * @param beginIndex the index to the first <code>char</code> of
+     * @param beginIndex the index to the first {@code char} of
      * the text range.
-     * @param endIndex the index after the last <code>char</code> of
+     * @param endIndex the index after the last {@code char} of
      * the text range.
      * @return the number of Unicode code points in the specified text
      * range
      * @exception IndexOutOfBoundsException if the
-     * <code>beginIndex</code> is negative, or <code>endIndex</code>
-     * is larger than the length of this <code>String</code>, or
-     * <code>beginIndex</code> is larger than <code>endIndex</code>.
+     * {@code beginIndex} is negative, or {@code endIndex}
+     * is larger than the length of this {@code String}, or
+     * {@code beginIndex} is larger than {@code endIndex}.
      * @since  1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
@@ -663,23 +660,23 @@
     }
 
     /**
-     * Returns the index within this <code>String</code> that is
-     * offset from the given <code>index</code> by
-     * <code>codePointOffset</code> code points. Unpaired surrogates
-     * within the text range given by <code>index</code> and
-     * <code>codePointOffset</code> count as one code point each.
+     * Returns the index within this {@code String} that is
+     * offset from the given {@code index} by
+     * {@code codePointOffset} code points. Unpaired surrogates
+     * within the text range given by {@code index} and
+     * {@code codePointOffset} count as one code point each.
      *
      * @param index the index to be offset
      * @param codePointOffset the offset in code points
-     * @return the index within this <code>String</code>
-     * @exception IndexOutOfBoundsException if <code>index</code>
+     * @return the index within this {@code String}
+     * @exception IndexOutOfBoundsException if {@code index}
      *   is negative or larger then the length of this
-     *   <code>String</code>, or if <code>codePointOffset</code> is positive
-     *   and the substring starting with <code>index</code> has fewer
-     *   than <code>codePointOffset</code> code points,
-     *   or if <code>codePointOffset</code> is negative and the substring
-     *   before <code>index</code> has fewer than the absolute value
-     *   of <code>codePointOffset</code> code points.
+     *   {@code String}, or if {@code codePointOffset} is positive
+     *   and the substring starting with {@code index} has fewer
+     *   than {@code codePointOffset} code points,
+     *   or if {@code codePointOffset} is negative and the substring
+     *   before {@code index} has fewer than the absolute value
+     *   of {@code codePointOffset} code points.
      * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
@@ -690,17 +687,25 @@
     }
 
     /**
+     * Copy characters from this string into dst starting at dstBegin.
+     * This method doesn't perform any range checking.
+     */
+    void getChars(char dst[], int dstBegin) {
+        getCharsNoCheck(0, count, dst, dstBegin);
+    }
+
+    /**
      * Copies characters from this string into the destination character
      * array.
      * <p>
-     * The first character to be copied is at index <code>srcBegin</code>;
-     * the last character to be copied is at index <code>srcEnd-1</code>
+     * The first character to be copied is at index {@code srcBegin};
+     * the last character to be copied is at index {@code srcEnd-1}
      * (thus the total number of characters to be copied is
-     * <code>srcEnd-srcBegin</code>). The characters are copied into the
-     * subarray of <code>dst</code> starting at index <code>dstBegin</code>
+     * {@code srcEnd-srcBegin}). The characters are copied into the
+     * subarray of {@code dst} starting at index {@code dstBegin}
      * and ending at index:
-     * <p><blockquote><pre>
-     *     dstbegin + (srcEnd-srcBegin) - 1
+     * <blockquote><pre>
+     *     dstBegin + (srcEnd-srcBegin) - 1
      * </pre></blockquote>
      *
      * @param      srcBegin   index of the first character in the string
@@ -711,13 +716,13 @@
      * @param      dstBegin   the start offset in the destination array.
      * @exception IndexOutOfBoundsException If any of the following
      *            is true:
-     *            <ul><li><code>srcBegin</code> is negative.
-     *            <li><code>srcBegin</code> is greater than <code>srcEnd</code>
-     *            <li><code>srcEnd</code> is greater than the length of this
+     *            <ul><li>{@code srcBegin} is negative.
+     *            <li>{@code srcBegin} is greater than {@code srcEnd}
+     *            <li>{@code srcEnd} is greater than the length of this
      *                string
-     *            <li><code>dstBegin</code> is negative
-     *            <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
-     *                <code>dst.length</code></ul>
+     *            <li>{@code dstBegin} is negative
+     *            <li>{@code dstBegin+(srcEnd-srcBegin)} is larger than
+     *                {@code dst.length}</ul>
      */
     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
         if (dst == null) {
@@ -775,7 +780,7 @@
      * dst} starting at index {@code dstBegin} and ending at index:
      *
      * <blockquote><pre>
-     *     dstbegin + (srcEnd-srcBegin) - 1
+     *     dstBegin + (srcEnd-srcBegin) - 1
      * </pre></blockquote>
      *
      * @deprecated  This method does not properly convert characters into
@@ -848,6 +853,7 @@
      */
     public byte[] getBytes(String charsetName)
             throws UnsupportedEncodingException {
+        if (charsetName == null) throw new NullPointerException();
         return getBytes(Charset.forNameUEE(charsetName));
     }
 
@@ -943,7 +949,8 @@
     /**
      * Compares this string to the specified {@code StringBuffer}.  The result
      * is {@code true} if and only if this {@code String} represents the same
-     * sequence of characters as the specified {@code StringBuffer}.
+     * sequence of characters as the specified {@code StringBuffer}. This method
+     * synchronizes on the {@code StringBuffer}.
      *
      * @param  sb
      *         The {@code StringBuffer} to compare this {@code String} against
@@ -955,15 +962,29 @@
      * @since  1.4
      */
     public boolean contentEquals(StringBuffer sb) {
-        synchronized (sb) {
-            return contentEquals((CharSequence) sb);
+        return contentEquals((CharSequence)sb);
+    }
+
+    private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
+        char v2[] = sb.getValue();
+        int n = count;
+        if (n != sb.length()) {
+            return false;
         }
+        for (int i = 0; i < n; i++) {
+            if (charAt(i) != v2[i]) {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
-     * Compares this string to the specified {@code CharSequence}.  The result
-     * is {@code true} if and only if this {@code String} represents the same
-     * sequence of char values as the specified sequence.
+     * Compares this string to the specified {@code CharSequence}.  The
+     * result is {@code true} if and only if this {@code String} represents the
+     * same sequence of char values as the specified sequence. Note that if the
+     * {@code CharSequence} is a {@code StringBuffer} then the method
+     * synchronizes on it.
      *
      * @param  cs
      *         The sequence to compare this {@code String} against
@@ -975,30 +996,29 @@
      * @since  1.5
      */
     public boolean contentEquals(CharSequence cs) {
-        if (count != cs.length())
-            return false;
         // Argument is a StringBuffer, StringBuilder
         if (cs instanceof AbstractStringBuilder) {
-            char v2[] = ((AbstractStringBuilder) cs).getValue();
-            int i = 0;
-            int n = count;
-            while (n-- != 0) {
-                if (charAt(i) != v2[i])
-                    return false;
-                i++;
+            if (cs instanceof StringBuffer) {
+                synchronized(cs) {
+                   return nonSyncContentEquals((AbstractStringBuilder)cs);
+                }
+            } else {
+                return nonSyncContentEquals((AbstractStringBuilder)cs);
             }
-            return true;
         }
         // Argument is a String
-        if (cs.equals(this))
-            return true;
+        if (cs instanceof String) {
+            return equals(cs);
+        }
         // Argument is a generic CharSequence
-        int i = 0;
         int n = count;
-        while (n-- != 0) {
-            if (charAt(i) != cs.charAt(i))
+        if (n != cs.length()) {
+            return false;
+        }
+        for (int i = 0; i < n; i++) {
+            if (charAt(i) != cs.charAt(i)) {
                 return false;
-            i++;
+            }
         }
         return true;
     }
@@ -1042,14 +1062,14 @@
      * Compares two strings lexicographically.
      * The comparison is based on the Unicode value of each character in
      * the strings. The character sequence represented by this
-     * <code>String</code> object is compared lexicographically to the
+     * {@code String} object is compared lexicographically to the
      * character sequence represented by the argument string. The result is
-     * a negative integer if this <code>String</code> object
+     * a negative integer if this {@code String} object
      * lexicographically precedes the argument string. The result is a
-     * positive integer if this <code>String</code> object lexicographically
+     * positive integer if this {@code String} object lexicographically
      * follows the argument string. The result is zero if the strings
-     * are equal; <code>compareTo</code> returns <code>0</code> exactly when
-     * the {@link #equals(Object)} method would return <code>true</code>.
+     * are equal; {@code compareTo} returns {@code 0} exactly when
+     * the {@link #equals(Object)} method would return {@code true}.
      * <p>
      * This is the definition of lexicographic ordering. If two strings are
      * different, then either they have different characters at some index
@@ -1058,32 +1078,32 @@
      * positions, let <i>k</i> be the smallest such index; then the string
      * whose character at position <i>k</i> has the smaller value, as
      * determined by using the &lt; operator, lexicographically precedes the
-     * other string. In this case, <code>compareTo</code> returns the
-     * difference of the two character values at position <code>k</code> in
+     * other string. In this case, {@code compareTo} returns the
+     * difference of the two character values at position {@code k} in
      * the two string -- that is, the value:
      * <blockquote><pre>
      * this.charAt(k)-anotherString.charAt(k)
      * </pre></blockquote>
      * If there is no index position at which they differ, then the shorter
      * string lexicographically precedes the longer string. In this case,
-     * <code>compareTo</code> returns the difference of the lengths of the
+     * {@code compareTo} returns the difference of the lengths of the
      * strings -- that is, the value:
      * <blockquote><pre>
      * this.length()-anotherString.length()
      * </pre></blockquote>
      *
-     * @param   anotherString   the <code>String</code> to be compared.
-     * @return  the value <code>0</code> if the argument string is equal to
-     *          this string; a value less than <code>0</code> if this string
+     * @param   anotherString   the {@code String} to be compared.
+     * @return  the value {@code 0} if the argument string is equal to
+     *          this string; a value less than {@code 0} if this string
      *          is lexicographically less than the string argument; and a
-     *          value greater than <code>0</code> if this string is
+     *          value greater than {@code 0} if this string is
      *          lexicographically greater than the string argument.
      */
     public native int compareTo(String anotherString);
 
     /**
-     * A Comparator that orders <code>String</code> objects as by
-     * <code>compareToIgnoreCase</code>. This comparator is serializable.
+     * A Comparator that orders {@code String} objects as by
+     * {@code compareToIgnoreCase}. This comparator is serializable.
      * <p>
      * Note that this Comparator does <em>not</em> take locale into account,
      * and will result in an unsatisfactory ordering for certain locales.
@@ -1122,14 +1142,17 @@
             }
             return n1 - n2;
         }
+
+        /** Replaces the de-serialized object. */
+        private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
     }
 
     /**
      * Compares two strings lexicographically, ignoring case
      * differences. This method returns an integer whose sign is that of
-     * calling <code>compareTo</code> with normalized versions of the strings
+     * calling {@code compareTo} with normalized versions of the strings
      * where case differences have been eliminated by calling
-     * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on
+     * {@code Character.toLowerCase(Character.toUpperCase(character))} on
      * each character.
      * <p>
      * Note that this method does <em>not</em> take locale into account,
@@ -1137,7 +1160,7 @@
      * The java.text package provides <em>collators</em> to allow
      * locale-sensitive ordering.
      *
-     * @param   str   the <code>String</code> to be compared.
+     * @param   str   the {@code String} to be compared.
      * @return  a negative integer, zero, or a positive integer as the
      *          specified String is greater than, equal to, or less
      *          than this String, ignoring case considerations.
@@ -1151,23 +1174,24 @@
     /**
      * Tests if two string regions are equal.
      * <p>
-     * A substring of this <tt>String</tt> object is compared to a substring
+     * A substring of this {@code String} object is compared to a substring
      * of the argument other. The result is true if these substrings
      * represent identical character sequences. The substring of this
-     * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
-     * and has length <tt>len</tt>. The substring of other to be compared
-     * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
-     * result is <tt>false</tt> if and only if at least one of the following
+     * {@code String} object to be compared begins at index {@code toffset}
+     * and has length {@code len}. The substring of other to be compared
+     * begins at index {@code ooffset} and has length {@code len}. The
+     * result is {@code false} if and only if at least one of the following
      * is true:
-     * <ul><li><tt>toffset</tt> is negative.
-     * <li><tt>ooffset</tt> is negative.
-     * <li><tt>toffset+len</tt> is greater than the length of this
-     * <tt>String</tt> object.
-     * <li><tt>ooffset+len</tt> is greater than the length of the other
+     * <ul><li>{@code toffset} is negative.
+     * <li>{@code ooffset} is negative.
+     * <li>{@code toffset+len} is greater than the length of this
+     * {@code String} object.
+     * <li>{@code ooffset+len} is greater than the length of the other
      * argument.
-     * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
+     * <li>There is some nonnegative integer <i>k</i> less than {@code len}
      * such that:
-     * <tt>this.charAt(toffset+<i>k</i>)&nbsp;!=&nbsp;other.charAt(ooffset+<i>k</i>)</tt>
+     * {@code this.charAt(toffset + }<i>k</i>{@code ) != other.charAt(ooffset + }
+     * <i>k</i>{@code )}
      * </ul>
      *
      * @param   toffset   the starting offset of the subregion in this string.
@@ -1175,9 +1199,9 @@
      * @param   ooffset   the starting offset of the subregion in the string
      *                    argument.
      * @param   len       the number of characters to compare.
-     * @return  <code>true</code> if the specified subregion of this string
+     * @return  {@code true} if the specified subregion of this string
      *          exactly matches the specified subregion of the string argument;
-     *          <code>false</code> otherwise.
+     *          {@code false} otherwise.
      */
     public boolean regionMatches(int toffset, String other, int ooffset,
             int len) {
@@ -1200,28 +1224,28 @@
     /**
      * Tests if two string regions are equal.
      * <p>
-     * A substring of this <tt>String</tt> object is compared to a substring
-     * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
+     * A substring of this {@code String} object is compared to a substring
+     * of the argument {@code other}. The result is {@code true} if these
      * substrings represent character sequences that are the same, ignoring
-     * case if and only if <tt>ignoreCase</tt> is true. The substring of
-     * this <tt>String</tt> object to be compared begins at index
-     * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
-     * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
-     * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
+     * case if and only if {@code ignoreCase} is true. The substring of
+     * this {@code String} object to be compared begins at index
+     * {@code toffset} and has length {@code len}. The substring of
+     * {@code other} to be compared begins at index {@code ooffset} and
+     * has length {@code len}. The result is {@code false} if and only if
      * at least one of the following is true:
-     * <ul><li><tt>toffset</tt> is negative.
-     * <li><tt>ooffset</tt> is negative.
-     * <li><tt>toffset+len</tt> is greater than the length of this
-     * <tt>String</tt> object.
-     * <li><tt>ooffset+len</tt> is greater than the length of the other
+     * <ul><li>{@code toffset} is negative.
+     * <li>{@code ooffset} is negative.
+     * <li>{@code toffset+len} is greater than the length of this
+     * {@code String} object.
+     * <li>{@code ooffset+len} is greater than the length of the other
      * argument.
-     * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative
-     * integer <i>k</i> less than <tt>len</tt> such that:
+     * <li>{@code ignoreCase} is {@code false} and there is some nonnegative
+     * integer <i>k</i> less than {@code len} such that:
      * <blockquote><pre>
      * this.charAt(toffset+k) != other.charAt(ooffset+k)
      * </pre></blockquote>
-     * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
-     * integer <i>k</i> less than <tt>len</tt> such that:
+     * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
+     * integer <i>k</i> less than {@code len} such that:
      * <blockquote><pre>
      * Character.toLowerCase(this.charAt(toffset+k)) !=
      Character.toLowerCase(other.charAt(ooffset+k))
@@ -1233,7 +1257,7 @@
      * </pre></blockquote>
      * </ul>
      *
-     * @param   ignoreCase   if <code>true</code>, ignore case when comparing
+     * @param   ignoreCase   if {@code true}, ignore case when comparing
      *                       characters.
      * @param   toffset      the starting offset of the subregion in this
      *                       string.
@@ -1241,10 +1265,10 @@
      * @param   ooffset      the starting offset of the subregion in the string
      *                       argument.
      * @param   len          the number of characters to compare.
-     * @return  <code>true</code> if the specified subregion of this string
+     * @return  {@code true} if the specified subregion of this string
      *          matches the specified subregion of the string argument;
-     *          <code>false</code> otherwise. Whether the matching is exact
-     *          or case insensitive depends on the <code>ignoreCase</code>
+     *          {@code false} otherwise. Whether the matching is exact
+     *          or case insensitive depends on the {@code ignoreCase}
      *          argument.
      */
     public boolean regionMatches(boolean ignoreCase, int toffset,
@@ -1292,12 +1316,12 @@
      *
      * @param   prefix    the prefix.
      * @param   toffset   where to begin looking in this string.
-     * @return  <code>true</code> if the character sequence represented by the
+     * @return  {@code true} if the character sequence represented by the
      *          argument is a prefix of the substring of this object starting
-     *          at index <code>toffset</code>; <code>false</code> otherwise.
-     *          The result is <code>false</code> if <code>toffset</code> is
+     *          at index {@code toffset}; {@code false} otherwise.
+     *          The result is {@code false} if {@code toffset} is
      *          negative or greater than the length of this
-     *          <code>String</code> object; otherwise the result is the same
+     *          {@code String} object; otherwise the result is the same
      *          as the result of the expression
      *          <pre>
      *          this.substring(toffset).startsWith(prefix)
@@ -1323,12 +1347,12 @@
      * Tests if this string starts with the specified prefix.
      *
      * @param   prefix   the prefix.
-     * @return  <code>true</code> if the character sequence represented by the
+     * @return  {@code true} if the character sequence represented by the
      *          argument is a prefix of the character sequence represented by
-     *          this string; <code>false</code> otherwise.
-     *          Note also that <code>true</code> will be returned if the
+     *          this string; {@code false} otherwise.
+     *          Note also that {@code true} will be returned if the
      *          argument is an empty string or is equal to this
-     *          <code>String</code> object as determined by the
+     *          {@code String} object as determined by the
      *          {@link #equals(Object)} method.
      * @since   1. 0
      */
@@ -1340,11 +1364,11 @@
      * Tests if this string ends with the specified suffix.
      *
      * @param   suffix   the suffix.
-     * @return  <code>true</code> if the character sequence represented by the
+     * @return  {@code true} if the character sequence represented by the
      *          argument is a suffix of the character sequence represented by
-     *          this object; <code>false</code> otherwise. Note that the
-     *          result will be <code>true</code> if the argument is the
-     *          empty string or is equal to this <code>String</code> object
+     *          this object; {@code false} otherwise. Note that the
+     *          result will be {@code true} if the argument is the
+     *          empty string or is equal to this {@code String} object
      *          as determined by the {@link #equals(Object)} method.
      */
     public boolean endsWith(String suffix) {
@@ -1353,13 +1377,13 @@
 
     /**
      * Returns a hash code for this string. The hash code for a
-     * <code>String</code> object is computed as
+     * {@code String} object is computed as
      * <blockquote><pre>
      * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
      * </pre></blockquote>
-     * using <code>int</code> arithmetic, where <code>s[i]</code> is the
-     * <i>i</i>th character of the string, <code>n</code> is the length of
-     * the string, and <code>^</code> indicates exponentiation.
+     * using {@code int} arithmetic, where {@code s[i]} is the
+     * <i>i</i>th character of the string, {@code n} is the length of
+     * the string, and {@code ^} indicates exponentiation.
      * (The hash value of the empty string is zero.)
      *
      * @return  a hash code value for this object.
@@ -1378,26 +1402,26 @@
     /**
      * Returns the index within this string of the first occurrence of
      * the specified character. If a character with value
-     * <code>ch</code> occurs in the character sequence represented by
-     * this <code>String</code> object, then the index (in Unicode
+     * {@code ch} occurs in the character sequence represented by
+     * this {@code String} object, then the index (in Unicode
      * code units) of the first such occurrence is returned. For
-     * values of <code>ch</code> in the range from 0 to 0xFFFF
+     * values of {@code ch} in the range from 0 to 0xFFFF
      * (inclusive), this is the smallest value <i>k</i> such that:
      * <blockquote><pre>
      * this.charAt(<i>k</i>) == ch
      * </pre></blockquote>
-     * is true. For other values of <code>ch</code>, it is the
+     * is true. For other values of {@code ch}, it is the
      * smallest value <i>k</i> such that:
      * <blockquote><pre>
      * this.codePointAt(<i>k</i>) == ch
      * </pre></blockquote>
      * is true. In either case, if no such character occurs in this
-     * string, then <code>-1</code> is returned.
+     * string, then {@code -1} is returned.
      *
      * @param   ch   a character (Unicode code point).
      * @return  the index of the first occurrence of the character in the
      *          character sequence represented by this object, or
-     *          <code>-1</code> if the character does not occur.
+     *          {@code -1} if the character does not occur.
      */
     public int indexOf(int ch) {
         return indexOf(ch, 0);
@@ -1407,39 +1431,39 @@
      * Returns the index within this string of the first occurrence of the
      * specified character, starting the search at the specified index.
      * <p>
-     * If a character with value <code>ch</code> occurs in the
-     * character sequence represented by this <code>String</code>
-     * object at an index no smaller than <code>fromIndex</code>, then
+     * If a character with value {@code ch} occurs in the
+     * character sequence represented by this {@code String}
+     * object at an index no smaller than {@code fromIndex}, then
      * the index of the first such occurrence is returned. For values
-     * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive),
+     * of {@code ch} in the range from 0 to 0xFFFF (inclusive),
      * this is the smallest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+     * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
      * </pre></blockquote>
-     * is true. For other values of <code>ch</code>, it is the
+     * is true. For other values of {@code ch}, it is the
      * smallest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+     * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
      * </pre></blockquote>
      * is true. In either case, if no such character occurs in this
-     * string at or after position <code>fromIndex</code>, then
-     * <code>-1</code> is returned.
+     * string at or after position {@code fromIndex}, then
+     * {@code -1} is returned.
      *
      * <p>
-     * There is no restriction on the value of <code>fromIndex</code>. If it
+     * There is no restriction on the value of {@code fromIndex}. If it
      * is negative, it has the same effect as if it were zero: this entire
      * string may be searched. If it is greater than the length of this
      * string, it has the same effect as if it were equal to the length of
-     * this string: <code>-1</code> is returned.
+     * this string: {@code -1} is returned.
      *
-     * <p>All indices are specified in <code>char</code> values
+     * <p>All indices are specified in {@code char} values
      * (Unicode code units).
      *
      * @param   ch          a character (Unicode code point).
      * @param   fromIndex   the index to start the search from.
      * @return  the index of the first occurrence of the character in the
      *          character sequence represented by this object that is greater
-     *          than or equal to <code>fromIndex</code>, or <code>-1</code>
+     *          than or equal to {@code fromIndex}, or {@code -1}
      *          if the character does not occur.
      */
     public int indexOf(int ch, int fromIndex) {
@@ -1486,26 +1510,26 @@
 
     /**
      * Returns the index within this string of the last occurrence of
-     * the specified character. For values of <code>ch</code> in the
+     * the specified character. For values of {@code ch} in the
      * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
      * units) returned is the largest value <i>k</i> such that:
      * <blockquote><pre>
      * this.charAt(<i>k</i>) == ch
      * </pre></blockquote>
-     * is true. For other values of <code>ch</code>, it is the
+     * is true. For other values of {@code ch}, it is the
      * largest value <i>k</i> such that:
      * <blockquote><pre>
      * this.codePointAt(<i>k</i>) == ch
      * </pre></blockquote>
      * is true.  In either case, if no such character occurs in this
-     * string, then <code>-1</code> is returned.  The
-     * <code>String</code> is searched backwards starting at the last
+     * string, then {@code -1} is returned.  The
+     * {@code String} is searched backwards starting at the last
      * character.
      *
      * @param   ch   a character (Unicode code point).
      * @return  the index of the last occurrence of the character in the
      *          character sequence represented by this object, or
-     *          <code>-1</code> if the character does not occur.
+     *          {@code -1} if the character does not occur.
      */
     public int lastIndexOf(int ch) {
         return lastIndexOf(ch, count - 1);
@@ -1514,27 +1538,27 @@
     /**
      * Returns the index within this string of the last occurrence of
      * the specified character, searching backward starting at the
-     * specified index. For values of <code>ch</code> in the range
+     * specified index. For values of {@code ch} in the range
      * from 0 to 0xFFFF (inclusive), the index returned is the largest
      * value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+     * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
      * </pre></blockquote>
-     * is true. For other values of <code>ch</code>, it is the
+     * is true. For other values of {@code ch}, it is the
      * largest value <i>k</i> such that:
      * <blockquote><pre>
-     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+     * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
      * </pre></blockquote>
      * is true. In either case, if no such character occurs in this
-     * string at or before position <code>fromIndex</code>, then
-     * <code>-1</code> is returned.
+     * string at or before position {@code fromIndex}, then
+     * {@code -1} is returned.
      *
-     * <p>All indices are specified in <code>char</code> values
+     * <p>All indices are specified in {@code char} values
      * (Unicode code units).
      *
      * @param   ch          a character (Unicode code point).
      * @param   fromIndex   the index to start the search from. There is no
-     *          restriction on the value of <code>fromIndex</code>. If it is
+     *          restriction on the value of {@code fromIndex}. If it is
      *          greater than or equal to the length of this string, it has
      *          the same effect as if it were equal to one less than the
      *          length of this string: this entire string may be searched.
@@ -1542,7 +1566,7 @@
      *          -1 is returned.
      * @return  the index of the last occurrence of the character in the
      *          character sequence represented by this object that is less
-     *          than or equal to <code>fromIndex</code>, or <code>-1</code>
+     *          than or equal to {@code fromIndex}, or {@code -1}
      *          if the character does not occur before that point.
      */
     public int lastIndexOf(int ch, int fromIndex) {
@@ -1602,7 +1626,7 @@
      *
      * <p>The returned index is the smallest value <i>k</i> for which:
      * <blockquote><pre>
-     * <i>k</i> &gt;= fromIndex && this.startsWith(str, <i>k</i>)
+     * <i>k</i> &gt;= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
@@ -1617,7 +1641,7 @@
     }
 
     /**
-     * Code shared by String and StringBuffer to do searches. The
+     * Code shared by String and AbstractStringBuilder to do searches. The
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
@@ -1739,7 +1763,7 @@
      *
      * <p>The returned index is the largest value <i>k</i> for which:
      * <blockquote><pre>
-     * <i>k</i> &lt;= fromIndex && this.startsWith(str, <i>k</i>)
+     * <i>k</i> {@code <=} fromIndex {@code &&} this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
@@ -1754,16 +1778,12 @@
     }
 
     /**
-     * Code shared by String and StringBuffer to do searches. The
+     * Code shared by String and AbstractStringBuilder to do searches. The
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
      * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
      * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
      * @param   fromIndex    the index to begin searching from.
      */
     static int lastIndexOf(String source,
@@ -1849,7 +1869,7 @@
         int min = sourceOffset + targetCount - 1;
         int i = min + fromIndex;
 
-        startSearchForLastChar:
+    startSearchForLastChar:
         while (true) {
             while (i >= min && source[i] != strLastChar) {
                 i--;
@@ -1872,7 +1892,7 @@
     }
 
     /**
-     * Returns a new string that is a substring of this string. The
+     * Returns a string that is a substring of this string. The
      * substring begins with the character at the specified index and
      * extends to the end of this string. <p>
      * Examples:
@@ -1885,8 +1905,8 @@
      * @param      beginIndex   the beginning index, inclusive.
      * @return     the specified substring.
      * @exception  IndexOutOfBoundsException  if
-     *             <code>beginIndex</code> is negative or larger than the
-     *             length of this <code>String</code> object.
+     *             {@code beginIndex} is negative or larger than the
+     *             length of this {@code String} object.
      */
     public String substring(int beginIndex) {
         if (beginIndex < 0) {
@@ -1900,10 +1920,10 @@
     }
 
     /**
-     * Returns a new string that is a substring of this string. The
-     * substring begins at the specified <code>beginIndex</code> and
-     * extends to the character at index <code>endIndex - 1</code>.
-     * Thus the length of the substring is <code>endIndex-beginIndex</code>.
+     * Returns a string that is a substring of this string. The
+     * substring begins at the specified {@code beginIndex} and
+     * extends to the character at index {@code endIndex - 1}.
+     * Thus the length of the substring is {@code endIndex-beginIndex}.
      * <p>
      * Examples:
      * <blockquote><pre>
@@ -1915,20 +1935,22 @@
      * @param      endIndex     the ending index, exclusive.
      * @return     the specified substring.
      * @exception  IndexOutOfBoundsException  if the
-     *             <code>beginIndex</code> is negative, or
-     *             <code>endIndex</code> is larger than the length of
-     *             this <code>String</code> object, or
-     *             <code>beginIndex</code> is larger than
-     *             <code>endIndex</code>.
+     *             {@code beginIndex} is negative, or
+     *             {@code endIndex} is larger than the length of
+     *             this {@code String} object, or
+     *             {@code beginIndex} is larger than
+     *             {@code endIndex}.
      */
     public String substring(int beginIndex, int endIndex) {
         if (beginIndex < 0) {
             throw new StringIndexOutOfBoundsException(this, beginIndex);
         }
-
+        if (endIndex > count) {
+            throw new StringIndexOutOfBoundsException(this, endIndex);
+        }
         int subLen = endIndex - beginIndex;
-        if (endIndex > count || subLen < 0) {
-            throw new StringIndexOutOfBoundsException(this, beginIndex, subLen);
+        if (subLen < 0) {
+            throw new StringIndexOutOfBoundsException(subLen);
         }
 
         return ((beginIndex == 0) && (endIndex == count)) ? this
@@ -1938,7 +1960,7 @@
     private native String fastSubstring(int start, int length);
 
     /**
-     * Returns a new character sequence that is a subsequence of this sequence.
+     * Returns a character sequence that is a subsequence of this sequence.
      *
      * <p> An invocation of this method of the form
      *
@@ -1950,17 +1972,18 @@
      * <blockquote><pre>
      * str.substring(begin,&nbsp;end)</pre></blockquote>
      *
-     * This method is defined so that the <tt>String</tt> class can implement
-     * the {@link CharSequence} interface. </p>
+     * @apiNote
+     * This method is defined so that the {@code String} class can implement
+     * the {@link CharSequence} interface.
      *
-     * @param      beginIndex   the begin index, inclusive.
-     * @param      endIndex     the end index, exclusive.
-     * @return     the specified subsequence.
+     * @param   beginIndex   the begin index, inclusive.
+     * @param   endIndex     the end index, exclusive.
+     * @return  the specified subsequence.
      *
      * @throws  IndexOutOfBoundsException
-     *          if <tt>beginIndex</tt> or <tt>endIndex</tt> are negative,
-     *          if <tt>endIndex</tt> is greater than <tt>length()</tt>,
-     *          or if <tt>beginIndex</tt> is greater than <tt>startIndex</tt>
+     *          if {@code beginIndex} or {@code endIndex} is negative,
+     *          if {@code endIndex} is greater than {@code length()},
+     *          or if {@code beginIndex} is greater than {@code endIndex}
      *
      * @since 1.4
      * @spec JSR-51
@@ -1972,11 +1995,11 @@
     /**
      * Concatenates the specified string to the end of this string.
      * <p>
-     * If the length of the argument string is <code>0</code>, then this
-     * <code>String</code> object is returned. Otherwise, a new
-     * <code>String</code> object is created, representing a character
+     * If the length of the argument string is {@code 0}, then this
+     * {@code String} object is returned. Otherwise, a
+     * {@code String} object is returned that represents a character
      * sequence that is the concatenation of the character sequence
-     * represented by this <code>String</code> object and the character
+     * represented by this {@code String} object and the character
      * sequence represented by the argument string.<p>
      * Examples:
      * <blockquote><pre>
@@ -1984,25 +2007,25 @@
      * "to".concat("get").concat("her") returns "together"
      * </pre></blockquote>
      *
-     * @param   str   the <code>String</code> that is concatenated to the end
-     *                of this <code>String</code>.
+     * @param   str   the {@code String} that is concatenated to the end
+     *                of this {@code String}.
      * @return  a string that represents the concatenation of this object's
      *          characters followed by the string argument's characters.
      */
     public native String concat(String str);
 
     /**
-     * Returns a new string resulting from replacing all occurrences of
-     * <code>oldChar</code> in this string with <code>newChar</code>.
+     * Returns a string resulting from replacing all occurrences of
+     * {@code oldChar} in this string with {@code newChar}.
      * <p>
-     * If the character <code>oldChar</code> does not occur in the
-     * character sequence represented by this <code>String</code> object,
-     * then a reference to this <code>String</code> object is returned.
-     * Otherwise, a new <code>String</code> object is created that
+     * If the character {@code oldChar} does not occur in the
+     * character sequence represented by this {@code String} object,
+     * then a reference to this {@code String} object is returned.
+     * Otherwise, a {@code String} object is returned that
      * represents a character sequence identical to the character sequence
-     * represented by this <code>String</code> object, except that every
-     * occurrence of <code>oldChar</code> is replaced by an occurrence
-     * of <code>newChar</code>.
+     * represented by this {@code String} object, except that every
+     * occurrence of {@code oldChar} is replaced by an occurrence
+     * of {@code newChar}.
      * <p>
      * Examples:
      * <blockquote><pre>
@@ -2018,7 +2041,7 @@
      * @param   oldChar   the old character.
      * @param   newChar   the new character.
      * @return  a string derived from this string by replacing every
-     *          occurrence of <code>oldChar</code> with <code>newChar</code>.
+     *          occurrence of {@code oldChar} with {@code newChar}.
      */
     public String replace(char oldChar, char newChar) {
         String replaced = this;
@@ -2040,17 +2063,18 @@
      * href="../util/regex/Pattern.html#sum">regular expression</a>.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.matches(</tt><i>regex</i><tt>)</tt> yields exactly the
+     * <i>str</i>{@code .matches(}<i>regex</i>{@code )} yields exactly the
      * same result as the expression
      *
-     * <blockquote><tt> {@link java.util.regex.Pattern}.{@link
-     * java.util.regex.Pattern#matches(String,CharSequence)
-     * matches}(</tt><i>regex</i><tt>,</tt> <i>str</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#matches(String,CharSequence)
+     * matches(<i>regex</i>, <i>str</i>)}
+     * </blockquote>
      *
      * @param   regex
      *          the regular expression to which this string is to be matched
      *
-     * @return  <tt>true</tt> if, and only if, this string matches the
+     * @return  {@code true} if, and only if, this string matches the
      *          given regular expression
      *
      * @throws  PatternSyntaxException
@@ -2070,8 +2094,7 @@
      * sequence of char values.
      *
      * @param s the sequence to search for
-     * @return true if this string contains <code>s</code>, false otherwise
-     * @throws NullPointerException if <code>s</code> is <code>null</code>
+     * @return true if this string contains {@code s}, false otherwise
      * @since 1.5
      */
     public boolean contains(CharSequence s) {
@@ -2084,18 +2107,20 @@
      * given replacement.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.replaceFirst(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+     * <i>str</i>{@code .replaceFirst(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
      * yields exactly the same result as the expression
      *
-     * <blockquote><tt>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}(</tt><i>regex</i><tt>).{@link
-     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
-     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceFirst
-     * replaceFirst}(</tt><i>repl</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+     * java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
+     * </code>
+     * </blockquote>
      *
      *<p>
-     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+     * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
      * replacement string may cause the results to be different than if it were
      * being treated as a literal replacement string; see
      * {@link java.util.regex.Matcher#replaceFirst}.
@@ -2107,7 +2132,7 @@
      * @param   replacement
      *          the string to be substituted for the first match
      *
-     * @return  The resulting <tt>String</tt>
+     * @return  The resulting {@code String}
      *
      * @throws  PatternSyntaxException
      *          if the regular expression's syntax is invalid
@@ -2127,18 +2152,20 @@
      * given replacement.
      *
      * <p> An invocation of this method of the form
-     * <i>str</i><tt>.replaceAll(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+     * <i>str</i>{@code .replaceAll(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
      * yields exactly the same result as the expression
      *
-     * <blockquote><tt>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}(</tt><i>regex</i><tt>).{@link
-     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
-     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceAll
-     * replaceAll}(</tt><i>repl</i><tt>)</tt></blockquote>
+     * <blockquote>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+     * java.util.regex.Matcher#replaceAll replaceAll}(<i>repl</i>)
+     * </code>
+     * </blockquote>
      *
      *<p>
-     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+     * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
      * replacement string may cause the results to be different than if it were
      * being treated as a literal replacement string; see
      * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}.
@@ -2150,7 +2177,7 @@
      * @param   replacement
      *          the string to be substituted for each match
      *
-     * @return  The resulting <tt>String</tt>
+     * @return  The resulting {@code String}
      *
      * @throws  PatternSyntaxException
      *          if the regular expression's syntax is invalid
@@ -2246,7 +2273,12 @@
      * expression does not match any part of the input then the resulting array
      * has just one element, namely this string.
      *
-     * <p> The <tt>limit</tt> parameter controls the number of times the
+     * <p> When there is a positive-width match at the beginning of this
+     * string then an empty leading substring is included at the beginning
+     * of the resulting array. A zero-width match at the beginning however
+     * never produces such empty leading substring.
+     *
+     * <p> The {@code limit} parameter controls the number of times the
      * pattern is applied and therefore affects the length of the resulting
      * array.  If the limit <i>n</i> is greater than zero then the pattern
      * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
@@ -2257,7 +2289,7 @@
      * the pattern will be applied as many times as possible, the array can
      * have any length, and trailing empty strings will be discarded.
      *
-     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the
+     * <p> The string {@code "boo:and:foo"}, for example, yields the
      * following results with these parameters:
      *
      * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
@@ -2268,33 +2300,34 @@
      * </tr>
      * <tr><td align=center>:</td>
      *     <td align=center>2</td>
-     *     <td><tt>{ "boo", "and:foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and:foo" }}</td></tr>
      * <tr><td align=center>:</td>
      *     <td align=center>5</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>:</td>
      *     <td align=center>-2</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>5</td>
-     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>-2</td>
-     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
      * <tr><td align=center>o</td>
      *     <td align=center>0</td>
-     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f" }}</td></tr>
      * </table></blockquote>
      *
      * <p> An invocation of this method of the form
-     * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+     * <i>str.</i>{@code split(}<i>regex</i>{@code ,}&nbsp;<i>n</i>{@code )}
      * yields the same result as the expression
      *
      * <blockquote>
-     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
-     * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link
-     * java.util.regex.Pattern#split(java.lang.CharSequence,int)
-     * split}<tt>(</tt><i>str</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+     * <code>
+     * {@link java.util.regex.Pattern}.{@link
+     * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+     * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(<i>str</i>,&nbsp;<i>n</i>)
+     * </code>
      * </blockquote>
      *
      *
@@ -2334,7 +2367,7 @@
      * argument of zero.  Trailing empty strings are therefore not included in
      * the resulting array.
      *
-     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the following
+     * <p> The string {@code "boo:and:foo"}, for example, yields the following
      * results with these expressions:
      *
      * <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result">
@@ -2343,9 +2376,9 @@
      *  <th>Result</th>
      * </tr>
      * <tr><td align=center>:</td>
-     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+     *     <td>{@code { "boo", "and", "foo" }}</td></tr>
      * <tr><td align=center>o</td>
-     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+     *     <td>{@code { "b", "", ":and:f" }}</td></tr>
      * </table></blockquote>
      *
      *
@@ -2368,11 +2401,95 @@
     }
 
     /**
-     * Converts all of the characters in this <code>String</code> to lower
-     * case using the rules of the given <code>Locale</code>.  Case mapping is based
+     * Returns a new String composed of copies of the
+     * {@code CharSequence elements} joined together with a copy of
+     * the specified {@code delimiter}.
+     *
+     * <blockquote>For example,
+     * <pre>{@code
+     *     String message = String.join("-", "Java", "is", "cool");
+     *     // message returned is: "Java-is-cool"
+     * }</pre></blockquote>
+     *
+     * Note that if an element is null, then {@code "null"} is added.
+     *
+     * @param  delimiter the delimiter that separates each element
+     * @param  elements the elements to join together.
+     *
+     * @return a new {@code String} that is composed of the {@code elements}
+     *         separated by the {@code delimiter}
+     *
+     * @throws NullPointerException If {@code delimiter} or {@code elements}
+     *         is {@code null}
+     *
+     * @see java.util.StringJoiner
+     * @since 1.8
+     */
+    public static String join(CharSequence delimiter, CharSequence... elements) {
+        Objects.requireNonNull(delimiter);
+        Objects.requireNonNull(elements);
+        // Number of elements not likely worth Arrays.stream overhead.
+        StringJoiner joiner = new StringJoiner(delimiter);
+        for (CharSequence cs: elements) {
+            joiner.add(cs);
+        }
+        return joiner.toString();
+    }
+
+    /**
+     * Returns a new {@code String} composed of copies of the
+     * {@code CharSequence elements} joined together with a copy of the
+     * specified {@code delimiter}.
+     *
+     * <blockquote>For example,
+     * <pre>{@code
+     *     List<String> strings = new LinkedList<>();
+     *     strings.add("Java");strings.add("is");
+     *     strings.add("cool");
+     *     String message = String.join(" ", strings);
+     *     //message returned is: "Java is cool"
+     *
+     *     Set<String> strings = new LinkedHashSet<>();
+     *     strings.add("Java"); strings.add("is");
+     *     strings.add("very"); strings.add("cool");
+     *     String message = String.join("-", strings);
+     *     //message returned is: "Java-is-very-cool"
+     * }</pre></blockquote>
+     *
+     * Note that if an individual element is {@code null}, then {@code "null"} is added.
+     *
+     * @param  delimiter a sequence of characters that is used to separate each
+     *         of the {@code elements} in the resulting {@code String}
+     * @param  elements an {@code Iterable} that will have its {@code elements}
+     *         joined together.
+     *
+     * @return a new {@code String} that is composed from the {@code elements}
+     *         argument
+     *
+     * @throws NullPointerException If {@code delimiter} or {@code elements}
+     *         is {@code null}
+     *
+     * @see    #join(CharSequence,CharSequence...)
+     * @see    java.util.StringJoiner
+     * @since 1.8
+     */
+    public static String join(CharSequence delimiter,
+            Iterable<? extends CharSequence> elements) {
+        Objects.requireNonNull(delimiter);
+        Objects.requireNonNull(elements);
+        StringJoiner joiner = new StringJoiner(delimiter);
+        for (CharSequence cs: elements) {
+            joiner.add(cs);
+        }
+        return joiner.toString();
+    }
+
+    /**
+     * Converts all of the characters in this {@code String} to lower
+     * case using the rules of the given {@code Locale}.  Case mapping is based
      * on the Unicode Standard version specified by the {@link java.lang.Character Character}
      * class. Since case mappings are not always 1:1 char mappings, the resulting
-     * <code>String</code> may be a different length than the original <code>String</code>.
+     * {@code String} may be a different length than the original {@code String}.
      * <p>
      * Examples of lowercase  mappings are in the following table:
      * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description">
@@ -2413,7 +2530,7 @@
      * </table>
      *
      * @param locale use the case transformation rules for this locale
-     * @return the <code>String</code>, converted to lowercase.
+     * @return the {@code String}, converted to lowercase.
      * @see     java.lang.String#toLowerCase()
      * @see     java.lang.String#toUpperCase()
      * @see     java.lang.String#toUpperCase(Locale)
@@ -2424,22 +2541,22 @@
     }
 
     /**
-     * Converts all of the characters in this <code>String</code> to lower
+     * Converts all of the characters in this {@code String} to lower
      * case using the rules of the default locale. This is equivalent to calling
-     * <code>toLowerCase(Locale.getDefault())</code>.
+     * {@code toLowerCase(Locale.getDefault())}.
      * <p>
      * <b>Note:</b> This method is locale sensitive, and may produce unexpected
      * results if used for strings that are intended to be interpreted locale
      * independently.
      * Examples are programming language identifiers, protocol keys, and HTML
      * tags.
-     * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale
-     * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the
+     * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale
+     * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the
      * LATIN SMALL LETTER DOTLESS I character.
      * To obtain correct results for locale insensitive strings, use
-     * <code>toLowerCase(Locale.ENGLISH)</code>.
+     * {@code toLowerCase(Locale.ROOT)}.
      * <p>
-     * @return  the <code>String</code>, converted to lowercase.
+     * @return  the {@code String}, converted to lowercase.
      * @see     java.lang.String#toLowerCase(Locale)
      */
     public String toLowerCase() {
@@ -2447,14 +2564,14 @@
     }
 
     /**
-     * Converts all of the characters in this <code>String</code> to upper
-     * case using the rules of the given <code>Locale</code>. Case mapping is based
+     * Converts all of the characters in this {@code String} to upper
+     * case using the rules of the given {@code Locale}. Case mapping is based
      * on the Unicode Standard version specified by the {@link java.lang.Character Character}
      * class. Since case mappings are not always 1:1 char mappings, the resulting
-     * <code>String</code> may be a different length than the original <code>String</code>.
+     * {@code String} may be a different length than the original {@code String}.
      * <p>
      * Examples of locale-sensitive and 1:M case mappings are in the following table.
-     * <p>
+     *
      * <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
      * <tr>
      *   <th>Language Code of Locale</th>
@@ -2488,7 +2605,7 @@
      * </tr>
      * </table>
      * @param locale use the case transformation rules for this locale
-     * @return the <code>String</code>, converted to uppercase.
+     * @return the {@code String}, converted to uppercase.
      * @see     java.lang.String#toUpperCase()
      * @see     java.lang.String#toLowerCase()
      * @see     java.lang.String#toLowerCase(Locale)
@@ -2499,22 +2616,22 @@
     }
 
     /**
-     * Converts all of the characters in this <code>String</code> to upper
+     * Converts all of the characters in this {@code String} to upper
      * case using the rules of the default locale. This method is equivalent to
-     * <code>toUpperCase(Locale.getDefault())</code>.
+     * {@code toUpperCase(Locale.getDefault())}.
      * <p>
      * <b>Note:</b> This method is locale sensitive, and may produce unexpected
      * results if used for strings that are intended to be interpreted locale
      * independently.
      * Examples are programming language identifiers, protocol keys, and HTML
      * tags.
-     * For instance, <code>"title".toUpperCase()</code> in a Turkish locale
-     * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the
+     * For instance, {@code "title".toUpperCase()} in a Turkish locale
+     * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the
      * LATIN CAPITAL LETTER I WITH DOT ABOVE character.
      * To obtain correct results for locale insensitive strings, use
-     * <code>toUpperCase(Locale.ENGLISH)</code>.
+     * {@code toUpperCase(Locale.ROOT)}.
      * <p>
-     * @return  the <code>String</code>, converted to uppercase.
+     * @return  the {@code String}, converted to uppercase.
      * @see     java.lang.String#toUpperCase(Locale)
      */
     public String toUpperCase() {
@@ -2522,33 +2639,33 @@
     }
 
     /**
-     * Returns a copy of the string, with leading and trailing whitespace
-     * omitted.
+     * Returns a string whose value is this string, with any leading and trailing
+     * whitespace removed.
      * <p>
-     * If this <code>String</code> object represents an empty character
+     * If this {@code String} object represents an empty character
      * sequence, or the first and last characters of character sequence
-     * represented by this <code>String</code> object both have codes
-     * greater than <code>'&#92;u0020'</code> (the space character), then a
-     * reference to this <code>String</code> object is returned.
+     * represented by this {@code String} object both have codes
+     * greater than {@code '\u005Cu0020'} (the space character), then a
+     * reference to this {@code String} object is returned.
      * <p>
      * Otherwise, if there is no character with a code greater than
-     * <code>'&#92;u0020'</code> in the string, then a new
-     * <code>String</code> object representing an empty string is created
-     * and returned.
+     * {@code '\u005Cu0020'} in the string, then a
+     * {@code String} object representing an empty string is
+     * returned.
      * <p>
      * Otherwise, let <i>k</i> be the index of the first character in the
-     * string whose code is greater than <code>'&#92;u0020'</code>, and let
+     * string whose code is greater than {@code '\u005Cu0020'}, and let
      * <i>m</i> be the index of the last character in the string whose code
-     * is greater than <code>'&#92;u0020'</code>. A new <code>String</code>
-     * object is created, representing the substring of this string that
+     * is greater than {@code '\u005Cu0020'}. A {@code String}
+     * object is returned, representing the substring of this string that
      * begins with the character at index <i>k</i> and ends with the
      * character at index <i>m</i>-that is, the result of
-     * <code>this.substring(<i>k</i>,&nbsp;<i>m</i>+1)</code>.
+     * {@code this.substring(k, m + 1)}.
      * <p>
      * This method may be used to trim whitespace (as defined above) from
      * the beginning and end of a string.
      *
-     * @return  A copy of this string with leading and trailing white
+     * @return  A string whose value is this string, with any leading and trailing white
      *          space removed, or this string if it has no leading or
      *          trailing white space.
      */
@@ -2602,10 +2719,10 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -2632,7 +2749,7 @@
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -2646,10 +2763,10 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
-     *         href="../util/Formatter.html#syntax">conversion</a>.
+     *         {@code null} argument depends on the
+     *         <a href="../util/Formatter.html#syntax">conversion</a>.
      *
-     * @throws  IllegalFormatException
+     * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
      *          specifier that is incompatible with the given arguments,
      *          insufficient arguments given the format string, or other
@@ -2671,12 +2788,12 @@
     }
 
     /**
-     * Returns the string representation of the <code>Object</code> argument.
+     * Returns the string representation of the {@code Object} argument.
      *
-     * @param   obj   an <code>Object</code>.
-     * @return  if the argument is <code>null</code>, then a string equal to
-     *          <code>"null"</code>; otherwise, the value of
-     *          <code>obj.toString()</code> is returned.
+     * @param   obj   an {@code Object}.
+     * @return  if the argument is {@code null}, then a string equal to
+     *          {@code "null"}; otherwise, the value of
+     *          {@code obj.toString()} is returned.
      * @see     java.lang.Object#toString()
      */
     public static String valueOf(Object obj) {
@@ -2684,14 +2801,14 @@
     }
 
     /**
-     * Returns the string representation of the <code>char</code> array
+     * Returns the string representation of the {@code char} array
      * argument. The contents of the character array are copied; subsequent
-     * modification of the character array does not affect the newly
-     * created string.
+     * modification of the character array does not affect the returned
+     * string.
      *
-     * @param   data   a <code>char</code> array.
-     * @return  a newly allocated string representing the same sequence of
-     *          characters contained in the character array argument.
+     * @param   data     the character array.
+     * @return  a {@code String} that contains the characters of the
+     *          character array.
      */
     public static String valueOf(char data[]) {
         return StringFactory.newStringFromChars(data);
@@ -2699,38 +2816,40 @@
 
     /**
      * Returns the string representation of a specific subarray of the
-     * <code>char</code> array argument.
+     * {@code char} array argument.
      * <p>
-     * The <code>offset</code> argument is the index of the first
-     * character of the subarray. The <code>count</code> argument
+     * The {@code offset} argument is the index of the first
+     * character of the subarray. The {@code count} argument
      * specifies the length of the subarray. The contents of the subarray
      * are copied; subsequent modification of the character array does not
-     * affect the newly created string.
+     * affect the returned string.
      *
      * @param   data     the character array.
-     * @param   offset   the initial offset into the value of the
-     *                  <code>String</code>.
-     * @param   count    the length of the value of the <code>String</code>.
-     * @return  a string representing the sequence of characters contained
-     *          in the subarray of the character array argument.
-     * @exception IndexOutOfBoundsException if <code>offset</code> is
-     *          negative, or <code>count</code> is negative, or
-     *          <code>offset+count</code> is larger than
-     *          <code>data.length</code>.
+     * @param   offset   initial offset of the subarray.
+     * @param   count    length of the subarray.
+     * @return  a {@code String} that contains the characters of the
+     *          specified subarray of the character array.
+     * @exception IndexOutOfBoundsException if {@code offset} is
+     *          negative, or {@code count} is negative, or
+     *          {@code offset+count} is larger than
+     *          {@code data.length}.
      */
     public static String valueOf(char data[], int offset, int count) {
         return StringFactory.newStringFromChars(data, offset, count);
     }
 
     /**
-     * Returns a String that represents the character sequence in the
-     * array specified.
+     * Equivalent to {@link #valueOf(char[], int, int)}.
      *
      * @param   data     the character array.
      * @param   offset   initial offset of the subarray.
      * @param   count    length of the subarray.
-     * @return  a <code>String</code> that contains the characters of the
+     * @return  a {@code String} that contains the characters of the
      *          specified subarray of the character array.
+     * @exception IndexOutOfBoundsException if {@code offset} is
+     *          negative, or {@code count} is negative, or
+     *          {@code offset+count} is larger than
+     *          {@code data.length}.
      */
     public static String copyValueOf(char data[], int offset, int count) {
         // All public String constructors now copy the data.
@@ -2738,11 +2857,10 @@
     }
 
     /**
-     * Returns a String that represents the character sequence in the
-     * array specified.
+     * Equivalent to {@link #valueOf(char[])}.
      *
      * @param   data   the character array.
-     * @return  a <code>String</code> that contains the characters of the
+     * @return  a {@code String} that contains the characters of the
      *          character array.
      */
     public static String copyValueOf(char data[]) {
@@ -2750,37 +2868,37 @@
     }
 
     /**
-     * Returns the string representation of the <code>boolean</code> argument.
+     * Returns the string representation of the {@code boolean} argument.
      *
-     * @param   b   a <code>boolean</code>.
-     * @return  if the argument is <code>true</code>, a string equal to
-     *          <code>"true"</code> is returned; otherwise, a string equal to
-     *          <code>"false"</code> is returned.
+     * @param   b   a {@code boolean}.
+     * @return  if the argument is {@code true}, a string equal to
+     *          {@code "true"} is returned; otherwise, a string equal to
+     *          {@code "false"} is returned.
      */
     public static String valueOf(boolean b) {
         return b ? "true" : "false";
     }
 
     /**
-     * Returns the string representation of the <code>char</code>
+     * Returns the string representation of the {@code char}
      * argument.
      *
-     * @param   c   a <code>char</code>.
-     * @return  a string of length <code>1</code> containing
-     *          as its single character the argument <code>c</code>.
+     * @param   c   a {@code char}.
+     * @return  a string of length {@code 1} containing
+     *          as its single character the argument {@code c}.
      */
     public static String valueOf(char c) {
         return StringFactory.newStringFromChars(0, 1, new char[] { c });
     }
 
     /**
-     * Returns the string representation of the <code>int</code> argument.
+     * Returns the string representation of the {@code int} argument.
      * <p>
      * The representation is exactly the one returned by the
-     * <code>Integer.toString</code> method of one argument.
+     * {@code Integer.toString} method of one argument.
      *
-     * @param   i   an <code>int</code>.
-     * @return  a string representation of the <code>int</code> argument.
+     * @param   i   an {@code int}.
+     * @return  a string representation of the {@code int} argument.
      * @see     java.lang.Integer#toString(int, int)
      */
     public static String valueOf(int i) {
@@ -2788,13 +2906,13 @@
     }
 
     /**
-     * Returns the string representation of the <code>long</code> argument.
+     * Returns the string representation of the {@code long} argument.
      * <p>
      * The representation is exactly the one returned by the
-     * <code>Long.toString</code> method of one argument.
+     * {@code Long.toString} method of one argument.
      *
-     * @param   l   a <code>long</code>.
-     * @return  a string representation of the <code>long</code> argument.
+     * @param   l   a {@code long}.
+     * @return  a string representation of the {@code long} argument.
      * @see     java.lang.Long#toString(long)
      */
     public static String valueOf(long l) {
@@ -2802,13 +2920,13 @@
     }
 
     /**
-     * Returns the string representation of the <code>float</code> argument.
+     * Returns the string representation of the {@code float} argument.
      * <p>
      * The representation is exactly the one returned by the
-     * <code>Float.toString</code> method of one argument.
+     * {@code Float.toString} method of one argument.
      *
-     * @param   f   a <code>float</code>.
-     * @return  a string representation of the <code>float</code> argument.
+     * @param   f   a {@code float}.
+     * @return  a string representation of the {@code float} argument.
      * @see     java.lang.Float#toString(float)
      */
     public static String valueOf(float f) {
@@ -2816,13 +2934,13 @@
     }
 
     /**
-     * Returns the string representation of the <code>double</code> argument.
+     * Returns the string representation of the {@code double} argument.
      * <p>
      * The representation is exactly the one returned by the
-     * <code>Double.toString</code> method of one argument.
+     * {@code Double.toString} method of one argument.
      *
-     * @param   d   a <code>double</code>.
-     * @return  a  string representation of the <code>double</code> argument.
+     * @param   d   a {@code double}.
+     * @return  a  string representation of the {@code double} argument.
      * @see     java.lang.Double#toString(double)
      */
     public static String valueOf(double d) {
@@ -2833,17 +2951,17 @@
      * Returns a canonical representation for the string object.
      * <p>
      * A pool of strings, initially empty, is maintained privately by the
-     * class <code>String</code>.
+     * class {@code String}.
      * <p>
      * When the intern method is invoked, if the pool already contains a
-     * string equal to this <code>String</code> object as determined by
+     * string equal to this {@code String} object as determined by
      * the {@link #equals(Object)} method, then the string from the pool is
-     * returned. Otherwise, this <code>String</code> object is added to the
-     * pool and a reference to this <code>String</code> object is returned.
+     * returned. Otherwise, this {@code String} object is added to the
+     * pool and a reference to this {@code String} object is returned.
      * <p>
-     * It follows that for any two strings <code>s</code> and <code>t</code>,
-     * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
-     * if and only if <code>s.equals(t)</code> is <code>true</code>.
+     * It follows that for any two strings {@code s} and {@code t},
+     * {@code s.intern() == t.intern()} is {@code true}
+     * if and only if {@code s.equals(t)} is {@code true}.
      * <p>
      * All literal strings and string-valued constant expressions are
      * interned. String literals are defined in section 3.10.5 of the
diff --git a/ojluni/src/main/java/java/lang/StringBuffer.java b/ojluni/src/main/java/java/lang/StringBuffer.java
old mode 100755
new mode 100644
index d832881..95a583d
--- a/ojluni/src/main/java/java/lang/StringBuffer.java
+++ b/ojluni/src/main/java/java/lang/StringBuffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2008, 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
@@ -25,6 +25,7 @@
 
 package java.lang;
 
+import java.util.Arrays;
 
 /**
  * A thread-safe, mutable sequence of characters.
@@ -39,39 +40,52 @@
  * that is consistent with the order of the method calls made by each of
  * the individual threads involved.
  * <p>
- * The principal operations on a <code>StringBuffer</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * The principal operations on a {@code StringBuffer} are the
+ * {@code append} and {@code insert} methods, which are
  * overloaded so as to accept data of any type. Each effectively
  * converts a given datum to a string and then appends or inserts the
  * characters of that string to the string buffer. The
- * <code>append</code> method always adds these characters at the end
- * of the buffer; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the buffer; the {@code insert} method adds the characters at
  * a specified point.
  * <p>
- * For example, if <code>z</code> refers to a string buffer object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * buffer to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string buffer to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string buffer object
+ * whose current contents are {@code "start"}, then
+ * the method call {@code z.append("le")} would cause the string
+ * buffer to contain {@code "startle"}, whereas
+ * {@code z.insert(4, "le")} would alter the string buffer to
+ * contain {@code "starlet"}.
  * <p>
- * In general, if sb refers to an instance of a <code>StringBuffer</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(),&nbsp;x)</code>.
+ * In general, if sb refers to an instance of a {@code StringBuffer},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(), x)}.
  * <p>
  * Whenever an operation occurs involving a source sequence (such as
- * appending or inserting from a source sequence) this class synchronizes
+ * appending or inserting from a source sequence), this class synchronizes
  * only on the string buffer performing the operation, not on the source.
+ * Note that while {@code StringBuffer} is designed to be safe to use
+ * concurrently from multiple threads, if the constructor or the
+ * {@code append} or {@code insert} operation is passed a source sequence
+ * that is shared across threads, the calling code must ensure
+ * that the operation has a consistent and unchanging view of the source
+ * sequence for the duration of the operation.
+ * This could be satisfied by the caller holding a lock during the
+ * operation's call, by using an immutable source sequence, or by not
+ * sharing the source sequence across threads.
  * <p>
  * Every string buffer has a capacity. As long as the length of the
  * character sequence contained in the string buffer does not exceed
  * the capacity, it is not necessary to allocate a new internal
  * buffer array. If the internal buffer overflows, it is
  * automatically made larger.
- *
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ * <p>
  * As of  release JDK 5, this class has been supplemented with an equivalent
  * class designed for use by a single thread, {@link StringBuilder}.  The
- * <tt>StringBuilder</tt> class should generally be used in preference to
+ * {@code StringBuilder} class should generally be used in preference to
  * this one, as it supports all of the same operations but it is faster, as
  * it performs no synchronization.
  *
@@ -82,9 +96,15 @@
  */
  public final class StringBuffer
     extends AbstractStringBuilder
-    implements java.io.Serializable, Appendable, CharSequence
+    implements java.io.Serializable, CharSequence
 {
 
+    /**
+     * A cache of the last value returned by toString. Cleared
+     * whenever the StringBuffer is modified.
+     */
+    private transient char[] toStringCache;
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     static final long serialVersionUID = 3388685877147921107L;
 
@@ -101,8 +121,8 @@
      * the specified initial capacity.
      *
      * @param      capacity  the initial capacity.
-     * @exception  NegativeArraySizeException  if the <code>capacity</code>
-     *               argument is less than <code>0</code>.
+     * @exception  NegativeArraySizeException  if the {@code capacity}
+     *               argument is less than {@code 0}.
      */
     public StringBuffer(int capacity) {
         super(capacity);
@@ -111,10 +131,9 @@
     /**
      * Constructs a string buffer initialized to the contents of the
      * specified string. The initial capacity of the string buffer is
-     * <code>16</code> plus the length of the string argument.
+     * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @exception NullPointerException if <code>str</code> is <code>null</code>
      */
     public StringBuffer(String str) {
         super(str.length() + 16);
@@ -123,16 +142,15 @@
 
     /**
      * Constructs a string buffer that contains the same characters
-     * as the specified <code>CharSequence</code>. The initial capacity of
-     * the string buffer is <code>16</code> plus the length of the
-     * <code>CharSequence</code> argument.
+     * as the specified {@code CharSequence}. The initial capacity of
+     * the string buffer is {@code 16} plus the length of the
+     * {@code CharSequence} argument.
      * <p>
-     * If the length of the specified <code>CharSequence</code> is
+     * If the length of the specified {@code CharSequence} is
      * less than or equal to zero, then an empty buffer of capacity
-     * <code>16</code> is returned.
+     * {@code 16} is returned.
      *
      * @param      seq   the sequence to copy.
-     * @exception NullPointerException if <code>seq</code> is <code>null</code>
      * @since 1.5
      */
     public StringBuffer(CharSequence seq) {
@@ -140,15 +158,18 @@
         append(seq);
     }
 
+    @Override
     public synchronized int length() {
         return count;
     }
 
+    @Override
     public synchronized int capacity() {
         return value.length;
     }
 
 
+    @Override
     public synchronized void ensureCapacity(int minimumCapacity) {
         if (minimumCapacity > value.length) {
             expandCapacity(minimumCapacity);
@@ -158,6 +179,7 @@
     /**
      * @since      1.5
      */
+    @Override
     public synchronized void trimToSize() {
         super.trimToSize();
     }
@@ -166,7 +188,9 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized void setLength(int newLength) {
+        toStringCache = null;
         super.setLength(newLength);
     }
 
@@ -174,6 +198,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized char charAt(int index) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
@@ -183,6 +208,7 @@
     /**
      * @since      1.5
      */
+    @Override
     public synchronized int codePointAt(int index) {
         return super.codePointAt(index);
     }
@@ -190,6 +216,7 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int codePointBefore(int index) {
         return super.codePointBefore(index);
     }
@@ -197,6 +224,7 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int codePointCount(int beginIndex, int endIndex) {
         return super.codePointCount(beginIndex, endIndex);
     }
@@ -204,14 +232,15 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int offsetByCodePoints(int index, int codePointOffset) {
         return super.offsetByCodePoints(index, codePointOffset);
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                       int dstBegin)
     {
@@ -222,95 +251,111 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized void setCharAt(int index, char ch) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
+        toStringCache = null;
         value[index] = ch;
     }
 
+    @Override
     public synchronized StringBuffer append(Object obj) {
+        toStringCache = null;
         super.append(String.valueOf(obj));
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(String str) {
+        toStringCache = null;
         super.append(str);
         return this;
     }
 
     /**
-     * Appends the specified <tt>StringBuffer</tt> to this sequence.
+     * Appends the specified {@code StringBuffer} to this sequence.
      * <p>
-     * The characters of the <tt>StringBuffer</tt> argument are appended,
-     * in order, to the contents of this <tt>StringBuffer</tt>, increasing the
-     * length of this <tt>StringBuffer</tt> by the length of the argument.
-     * If <tt>sb</tt> is <tt>null</tt>, then the four characters
-     * <tt>"null"</tt> are appended to this <tt>StringBuffer</tt>.
+     * The characters of the {@code StringBuffer} argument are appended,
+     * in order, to the contents of this {@code StringBuffer}, increasing the
+     * length of this {@code StringBuffer} by the length of the argument.
+     * If {@code sb} is {@code null}, then the four characters
+     * {@code "null"} are appended to this {@code StringBuffer}.
      * <p>
      * Let <i>n</i> be the length of the old character sequence, the one
-     * contained in the <tt>StringBuffer</tt> just prior to execution of the
-     * <tt>append</tt> method. Then the character at index <i>k</i> in
+     * contained in the {@code StringBuffer} just prior to execution of the
+     * {@code append} method. Then the character at index <i>k</i> in
      * the new character sequence is equal to the character at index <i>k</i>
      * in the old character sequence, if <i>k</i> is less than <i>n</i>;
      * otherwise, it is equal to the character at index <i>k-n</i> in the
-     * argument <code>sb</code>.
+     * argument {@code sb}.
      * <p>
-     * This method synchronizes on <code>this</code> (the destination)
-     * object but does not synchronize on the source (<code>sb</code>).
+     * This method synchronizes on {@code this}, the destination
+     * object, but does not synchronize on the source ({@code sb}).
      *
-     * @param   sb   the <tt>StringBuffer</tt> to append.
+     * @param   sb   the {@code StringBuffer} to append.
      * @return  a reference to this object.
      * @since 1.4
      */
     public synchronized StringBuffer append(StringBuffer sb) {
+        toStringCache = null;
         super.append(sb);
         return this;
     }
 
+    /**
+     * @since 1.8
+     */
+    @Override
+    synchronized StringBuffer append(AbstractStringBuilder asb) {
+        toStringCache = null;
+        super.append(asb);
+        return this;
+    }
 
     /**
-     * Appends the specified <code>CharSequence</code> to this
+     * Appends the specified {@code CharSequence} to this
      * sequence.
      * <p>
-     * The characters of the <code>CharSequence</code> argument are appended,
+     * The characters of the {@code CharSequence} argument are appended,
      * in order, increasing the length of this sequence by the length of the
      * argument.
      *
      * <p>The result of this method is exactly the same as if it were an
      * invocation of this.append(s, 0, s.length());
      *
-     * <p>This method synchronizes on this (the destination)
-     * object but does not synchronize on the source (<code>s</code>).
+     * <p>This method synchronizes on {@code this}, the destination
+     * object, but does not synchronize on the source ({@code s}).
      *
-     * <p>If <code>s</code> is <code>null</code>, then the four characters
-     * <code>"null"</code> are appended.
+     * <p>If {@code s} is {@code null}, then the four characters
+     * {@code "null"} are appended.
      *
-     * @param   s the <code>CharSequence</code> to append.
+     * @param   s the {@code CharSequence} to append.
      * @return  a reference to this object.
      * @since 1.5
      */
-    public StringBuffer append(CharSequence s) {
-        // Note, synchronization achieved via other invocations
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
-        return this.append(s, 0, s.length());
+    @Override
+    public synchronized StringBuffer append(CharSequence s) {
+        toStringCache = null;
+        super.append(s);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public synchronized StringBuffer append(CharSequence s, int start, int end)
     {
+        toStringCache = null;
         super.append(s, start, end);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(char[] str) {
+        toStringCache = null;
         super.append(str);
         return this;
     }
@@ -318,22 +363,30 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer append(char[] str, int offset, int len) {
+        toStringCache = null;
         super.append(str, offset, len);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(boolean b) {
+        toStringCache = null;
         super.append(b);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(char c) {
+        toStringCache = null;
         super.append(c);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(int i) {
+        toStringCache = null;
         super.append(i);
         return this;
     }
@@ -341,22 +394,30 @@
     /**
      * @since 1.5
      */
+    @Override
     public synchronized StringBuffer appendCodePoint(int codePoint) {
+        toStringCache = null;
         super.appendCodePoint(codePoint);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(long lng) {
+        toStringCache = null;
         super.append(lng);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(float f) {
+        toStringCache = null;
         super.append(f);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(double d) {
+        toStringCache = null;
         super.append(d);
         return this;
     }
@@ -365,7 +426,9 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer delete(int start, int end) {
+        toStringCache = null;
         super.delete(start, end);
         return this;
     }
@@ -374,7 +437,9 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer deleteCharAt(int index) {
+        toStringCache = null;
         super.deleteCharAt(index);
         return this;
     }
@@ -383,7 +448,9 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer replace(int start, int end, String str) {
+        toStringCache = null;
         super.replace(start, end, str);
         return this;
     }
@@ -392,6 +459,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized String substring(int start) {
         return substring(start, count);
     }
@@ -400,6 +468,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized CharSequence subSequence(int start, int end) {
         return super.substring(start, end);
     }
@@ -408,6 +477,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized String substring(int start, int end) {
         return super.substring(start, end);
     }
@@ -416,9 +486,11 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer insert(int index, char[] str, int offset,
                                             int len)
     {
+        toStringCache = null;
         super.insert(index, str, offset, len);
         return this;
     }
@@ -426,7 +498,9 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, Object obj) {
+        toStringCache = null;
         super.insert(offset, String.valueOf(obj));
         return this;
     }
@@ -434,7 +508,9 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, String str) {
+        toStringCache = null;
         super.insert(offset, str);
         return this;
     }
@@ -442,7 +518,9 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, char[] str) {
+        toStringCache = null;
         super.insert(offset, str);
         return this;
     }
@@ -451,22 +529,24 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public StringBuffer insert(int dstOffset, CharSequence s) {
-        // Note, synchronization achieved via other invocations
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.insert(dstOffset, (String)s);
-        return this.insert(dstOffset, s, 0, s.length());
+        // Note, synchronization achieved via invocations of other StringBuffer methods
+        // after narrowing of s to specific type
+        // Ditto for toStringCache clearing
+        super.insert(dstOffset, s);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public synchronized StringBuffer insert(int dstOffset, CharSequence s,
-                                            int start, int end)
+            int start, int end)
     {
+        toStringCache = null;
         super.insert(dstOffset, s, start, end);
         return this;
     }
@@ -474,14 +554,21 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
-    public StringBuffer insert(int offset, boolean b) {
-        return insert(offset, String.valueOf(b));
+    @Override
+    public  StringBuffer insert(int offset, boolean b) {
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of b to String by super class method
+        // Ditto for toStringCache clearing
+        super.insert(offset, b);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, char c) {
+        toStringCache = null;
         super.insert(offset, c);
         return this;
     }
@@ -489,76 +576,101 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, int i) {
-        return insert(offset, String.valueOf(i));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of i to String by super class method
+        // Ditto for toStringCache clearing
+        super.insert(offset, i);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, long l) {
-        return insert(offset, String.valueOf(l));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of l to String by super class method
+        // Ditto for toStringCache clearing
+        super.insert(offset, l);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, float f) {
-        return insert(offset, String.valueOf(f));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of f to String by super class method
+        // Ditto for toStringCache clearing
+        super.insert(offset, f);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, double d) {
-        return insert(offset, String.valueOf(d));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of d to String by super class method
+        // Ditto for toStringCache clearing
+        super.insert(offset, d);
+        return this;
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        // Note, synchronization achieved via invocations of other StringBuffer methods
+        return super.indexOf(str);
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.indexOf(str, fromIndex);
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public int lastIndexOf(String str) {
-        // Note, synchronization achieved via other invocations
+        // Note, synchronization achieved via invocations of other StringBuffer methods
         return lastIndexOf(str, count);
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.lastIndexOf(str, fromIndex);
     }
 
     /**
      * @since   JDK1.0.2
      */
+    @Override
     public synchronized StringBuffer reverse() {
+        toStringCache = null;
         super.reverse();
         return this;
     }
 
+    @Override
     public synchronized String toString() {
-        return new String(value, 0, count);
+        if (toStringCache == null) {
+            toStringCache = Arrays.copyOfRange(value, 0, count);
+        }
+        return new String(toStringCache, 0, count);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/lang/StringBuilder.java b/ojluni/src/main/java/java/lang/StringBuilder.java
old mode 100755
new mode 100644
index e16522d..42642c7
--- a/ojluni/src/main/java/java/lang/StringBuilder.java
+++ b/ojluni/src/main/java/java/lang/StringBuilder.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * 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
@@ -29,42 +29,46 @@
 
 /**
  * A mutable sequence of characters.  This class provides an API compatible
- * with <code>StringBuffer</code>, but with no guarantee of synchronization.
+ * with {@code StringBuffer}, but with no guarantee of synchronization.
  * This class is designed for use as a drop-in replacement for
- * <code>StringBuffer</code> in places where the string buffer was being
+ * {@code StringBuffer} in places where the string buffer was being
  * used by a single thread (as is generally the case).   Where possible,
  * it is recommended that this class be used in preference to
- * <code>StringBuffer</code> as it will be faster under most implementations.
+ * {@code StringBuffer} as it will be faster under most implementations.
  *
- * <p>The principal operations on a <code>StringBuilder</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * <p>The principal operations on a {@code StringBuilder} are the
+ * {@code append} and {@code insert} methods, which are
  * overloaded so as to accept data of any type. Each effectively
  * converts a given datum to a string and then appends or inserts the
  * characters of that string to the string builder. The
- * <code>append</code> method always adds these characters at the end
- * of the builder; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the builder; the {@code insert} method adds the characters at
  * a specified point.
  * <p>
- * For example, if <code>z</code> refers to a string builder object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * builder to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string builder to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string builder object
+ * whose current contents are "{@code start}", then
+ * the method call {@code z.append("le")} would cause the string
+ * builder to contain "{@code startle}", whereas
+ * {@code z.insert(4, "le")} would alter the string builder to
+ * contain "{@code starlet}".
  * <p>
- * In general, if sb refers to an instance of a <code>StringBuilder</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(),&nbsp;x)</code>.
- *
+ * In general, if sb refers to an instance of a {@code StringBuilder},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(), x)}.
+ * <p>
  * Every string builder has a capacity. As long as the length of the
  * character sequence contained in the string builder does not exceed
  * the capacity, it is not necessary to allocate a new internal
  * buffer. If the internal buffer overflows, it is automatically made larger.
  *
- * <p>Instances of <code>StringBuilder</code> are not safe for
+ * <p>Instances of {@code StringBuilder} are not safe for
  * use by multiple threads. If such synchronization is required then it is
  * recommended that {@link java.lang.StringBuffer} be used.
  *
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
  * @author      Michael McCloskey
  * @see         java.lang.StringBuffer
  * @see         java.lang.String
@@ -72,7 +76,7 @@
  */
 public final class StringBuilder
     extends AbstractStringBuilder
-    implements java.io.Serializable, Appendable, CharSequence
+    implements java.io.Serializable, CharSequence
 {
 
     /** use serialVersionUID for interoperability */
@@ -88,11 +92,11 @@
 
     /**
      * Constructs a string builder with no characters in it and an
-     * initial capacity specified by the <code>capacity</code> argument.
+     * initial capacity specified by the {@code capacity} argument.
      *
      * @param      capacity  the initial capacity.
-     * @throws     NegativeArraySizeException  if the <code>capacity</code>
-     *               argument is less than <code>0</code>.
+     * @throws     NegativeArraySizeException  if the {@code capacity}
+     *               argument is less than {@code 0}.
      */
     public StringBuilder(int capacity) {
         super(capacity);
@@ -101,10 +105,9 @@
     /**
      * Constructs a string builder initialized to the contents of the
      * specified string. The initial capacity of the string builder is
-     * <code>16</code> plus the length of the string argument.
+     * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @throws    NullPointerException if <code>str</code> is <code>null</code>
      */
     public StringBuilder(String str) {
         super(str.length() + 16);
@@ -113,57 +116,45 @@
 
     /**
      * Constructs a string builder that contains the same characters
-     * as the specified <code>CharSequence</code>. The initial capacity of
-     * the string builder is <code>16</code> plus the length of the
-     * <code>CharSequence</code> argument.
+     * as the specified {@code CharSequence}. The initial capacity of
+     * the string builder is {@code 16} plus the length of the
+     * {@code CharSequence} argument.
      *
      * @param      seq   the sequence to copy.
-     * @throws    NullPointerException if <code>seq</code> is <code>null</code>
      */
     public StringBuilder(CharSequence seq) {
         this(seq.length() + 16);
         append(seq);
     }
 
+    @Override
     public StringBuilder append(Object obj) {
         return append(String.valueOf(obj));
     }
 
+    @Override
     public StringBuilder append(String str) {
         super.append(str);
         return this;
     }
 
-    // Appends the specified string builder to this sequence.
-    private StringBuilder append(StringBuilder sb) {
-        if (sb == null)
-            return append("null");
-        int len = sb.length();
-        int newcount = count + len;
-        if (newcount > value.length)
-            expandCapacity(newcount);
-        sb.getChars(0, len, value, count);
-        count = newcount;
-        return this;
-    }
-
     /**
-     * Appends the specified <tt>StringBuffer</tt> to this sequence.
+     * Appends the specified {@code StringBuffer} to this sequence.
      * <p>
-     * The characters of the <tt>StringBuffer</tt> argument are appended,
+     * The characters of the {@code StringBuffer} argument are appended,
      * in order, to this sequence, increasing the
      * length of this sequence by the length of the argument.
-     * If <tt>sb</tt> is <tt>null</tt>, then the four characters
-     * <tt>"null"</tt> are appended to this sequence.
+     * If {@code sb} is {@code null}, then the four characters
+     * {@code "null"} are appended to this sequence.
      * <p>
      * Let <i>n</i> be the length of this character sequence just prior to
-     * execution of the <tt>append</tt> method. Then the character at index
+     * execution of the {@code append} method. Then the character at index
      * <i>k</i> in the new character sequence is equal to the character at
      * index <i>k</i> in the old character sequence, if <i>k</i> is less than
      * <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i>
-     * in the argument <code>sb</code>.
+     * in the argument {@code sb}.
      *
-     * @param   sb   the <tt>StringBuffer</tt> to append.
+     * @param   sb   the {@code StringBuffer} to append.
      * @return  a reference to this object.
      */
     public StringBuilder append(StringBuffer sb) {
@@ -171,28 +162,22 @@
         return this;
     }
 
-    /**
-     */
+    @Override
     public StringBuilder append(CharSequence s) {
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
-        if (s instanceof StringBuilder)
-            return this.append((StringBuilder)s);
-        return this.append(s, 0, s.length());
+        super.append(s);
+        return this;
     }
 
     /**
      * @throws     IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder append(CharSequence s, int start, int end) {
         super.append(s, start, end);
         return this;
     }
 
+    @Override
     public StringBuilder append(char[] str) {
         super.append(str);
         return this;
@@ -201,36 +186,43 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder append(char[] str, int offset, int len) {
         super.append(str, offset, len);
         return this;
     }
 
+    @Override
     public StringBuilder append(boolean b) {
         super.append(b);
         return this;
     }
 
+    @Override
     public StringBuilder append(char c) {
         super.append(c);
         return this;
     }
 
+    @Override
     public StringBuilder append(int i) {
         super.append(i);
         return this;
     }
 
+    @Override
     public StringBuilder append(long lng) {
         super.append(lng);
         return this;
     }
 
+    @Override
     public StringBuilder append(float f) {
         super.append(f);
         return this;
     }
 
+    @Override
     public StringBuilder append(double d) {
         super.append(d);
         return this;
@@ -239,6 +231,7 @@
     /**
      * @since 1.5
      */
+    @Override
     public StringBuilder appendCodePoint(int codePoint) {
         super.appendCodePoint(codePoint);
         return this;
@@ -247,6 +240,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder delete(int start, int end) {
         super.delete(start, end);
         return this;
@@ -255,6 +249,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder deleteCharAt(int index) {
         super.deleteCharAt(index);
         return this;
@@ -263,6 +258,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder replace(int start, int end, String str) {
         super.replace(start, end, str);
         return this;
@@ -271,6 +267,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int index, char[] str, int offset,
                                 int len)
     {
@@ -281,13 +278,16 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, Object obj) {
-        return insert(offset, String.valueOf(obj));
+            super.insert(offset, obj);
+            return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, String str) {
         super.insert(offset, str);
         return this;
@@ -296,6 +296,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, char[] str) {
         super.insert(offset, str);
         return this;
@@ -304,17 +305,16 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int dstOffset, CharSequence s) {
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.insert(dstOffset, (String)s);
-        return this.insert(dstOffset, s, 0, s.length());
+            super.insert(dstOffset, s);
+            return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int dstOffset, CharSequence s,
                                 int start, int end)
     {
@@ -325,6 +325,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, boolean b) {
         super.insert(offset, b);
         return this;
@@ -333,6 +334,7 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, char c) {
         super.insert(offset, c);
         return this;
@@ -341,66 +343,66 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, int i) {
-        return insert(offset, String.valueOf(i));
+        super.insert(offset, i);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, long l) {
-        return insert(offset, String.valueOf(l));
+        super.insert(offset, l);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, float f) {
-        return insert(offset, String.valueOf(f));
+        super.insert(offset, f);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, double d) {
-        return insert(offset, String.valueOf(d));
+        super.insert(offset, d);
+        return this;
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
+    @Override
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        return super.indexOf(str);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
+    @Override
     public int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.indexOf(str, fromIndex);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
+    @Override
     public int lastIndexOf(String str) {
-        return lastIndexOf(str, count);
+        return super.lastIndexOf(str);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
+    @Override
     public int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.lastIndexOf(str, fromIndex);
     }
 
+    @Override
     public StringBuilder reverse() {
         super.reverse();
         return this;
     }
 
+    @Override
     public String toString() {
         if (count == 0) {
             return "";
@@ -409,13 +411,13 @@
     }
 
     /**
-     * Save the state of the <tt>StringBuilder</tt> instance to a stream
+     * Save the state of the {@code StringBuilder} instance to a stream
      * (that is, serialize it).
      *
      * @serialData the number of characters currently stored in the string
-     *             builder (<tt>int</tt>), followed by the characters in the
-     *             string builder (<tt>char[]</tt>).   The length of the
-     *             <tt>char</tt> array may be greater than the number of
+     *             builder ({@code int}), followed by the characters in the
+     *             string builder ({@code char[]}).   The length of the
+     *             {@code char} array may be greater than the number of
      *             characters currently stored in the string builder, in which
      *             case extra characters are ignored.
      */
diff --git a/ojluni/src/main/java/java/lang/annotation/Native.java b/ojluni/src/main/java/java/lang/annotation/Native.java
index 2f2a5a8..861c1ff 100644
--- a/ojluni/src/main/java/java/lang/annotation/Native.java
+++ b/ojluni/src/main/java/java/lang/annotation/Native.java
@@ -35,7 +35,6 @@
  * if so, what declarations it should contain.
  *
  * @since 1.8
- * @hide  TODO unhide
  */
 @Documented
 @Target(ElementType.FIELD)
diff --git a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
index 8311f76..4ecad5b 100755
--- a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
@@ -65,6 +65,14 @@
     private final static boolean connectDisabled = os.contains("OS X");
 
     /**
+     * Load net library into runtime.
+     * TODO(yikong): Move clinit code to registration function
+     */
+    static {
+        init();
+    }
+
+    /**
      * Creates a datagram socket
      */
     protected synchronized void create() throws SocketException {
@@ -386,4 +394,7 @@
     protected boolean nativeConnectDisabled() {
         return connectDisabled;
     }
+
+    native int dataAvailable();
+    private static native void init();
 }
diff --git a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
index 746c19e..330e014 100755
--- a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
@@ -647,7 +647,3 @@
     public final static int SHUT_RD = 0;
     public final static int SHUT_WR = 1;
 }
-
-class InetAddressContainer {
-    InetAddress addr;
-}
diff --git a/ojluni/src/main/java/java/net/DatagramPacket.java b/ojluni/src/main/java/java/net/DatagramPacket.java
index 62001d7..1ce7cad 100755
--- a/ojluni/src/main/java/java/net/DatagramPacket.java
+++ b/ojluni/src/main/java/java/net/DatagramPacket.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, 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
@@ -133,8 +133,7 @@
      *
      * @since 1.4
      */
-    public DatagramPacket(byte buf[], int offset, int length,
-                          SocketAddress address) throws SocketException {
+    public DatagramPacket(byte buf[], int offset, int length, SocketAddress address) {
         setData(buf, offset, length);
         setSocketAddress(address);
     }
@@ -169,8 +168,7 @@
      * @since 1.4
      * @see     java.net.InetAddress
      */
-    public DatagramPacket(byte buf[], int length,
-                          SocketAddress address) throws SocketException {
+    public DatagramPacket(byte buf[], int length, SocketAddress address) {
         this(buf, 0, length, address);
     }
 
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index 03ecf94..6d43ad0 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -89,6 +89,17 @@
      */
     boolean oldImpl = false;
 
+    /**
+     * Set when a socket is ST_CONNECTED until we are certain
+     * that any packets which might have been received prior
+     * to calling connect() but not read by the application
+     * have been read. During this time we check the source
+     * address of all packets received to be sure they are from
+     * the connected destination. Other packets are read but
+     * silently dropped.
+     */
+    private boolean explicitFilter = false;
+    private int bytesLeftToFilter;
     /*
      * Connection state:
      * ST_NOT_CONNECTED = socket not connected
@@ -166,6 +177,15 @@
 
           // socket is now connected by the impl
           connectState = ST_CONNECTED;
+          // Do we need to filter some packets?
+          int avail = getImpl().dataAvailable();
+          if (avail == -1) {
+              throw new SocketException();
+          }
+          explicitFilter = avail > 0;
+          if (explicitFilter) {
+              bytesLeftToFilter = getReceiveBufferSize();
+          }
           // ----- END android -----
         }
 
@@ -512,6 +532,7 @@
             connectedAddress = null;
             connectedPort = -1;
             connectState = ST_NOT_CONNECTED;
+            explicitFilter = false;
         }
     }
 
@@ -777,10 +798,12 @@
                     } // end of while
                 }
             }
-            if (connectState == ST_CONNECTED_NO_IMPL) {
+            if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
                 // We have to do the filtering the old fashioned way since
                 // the native impl doesn't support connect or the connect
-                // via the impl failed.
+                // via the impl failed, or .. "explicitFilter" may be set when
+                // a socket is connected via the impl, for a period of time
+                // when packets from other sources might be queued on socket.
                 boolean stop = false;
                 while (!stop) {
                     InetAddress peekAddress = null;
@@ -799,8 +822,12 @@
                     if ((!connectedAddress.equals(peekAddress)) ||
                         (connectedPort != peekPort)) {
                         // throw the packet away and silently continue
-                        DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
+                        DatagramPacket tmp = new DatagramPacket(
+                                                new byte[1024], 1024);
                         getImpl().receive(tmp);
+                        if (explicitFilter) {
+                            bytesLeftToFilter -= tmp.getLength();
+                        }
                     } else {
                         stop = true;
                     }
@@ -809,6 +836,15 @@
             // If the security check succeeds, or the datagram is
             // connected then receive the packet
             getImpl().receive(p);
+            if (explicitFilter) {
+                bytesLeftToFilter -= p.getLength();
+                if (bytesLeftToFilter <= 0) {
+                    explicitFilter = false;
+                } else {
+                    // break out of filter, if there is no more data queued
+                    explicitFilter = getImpl().dataAvailable() > 0;
+                }
+            }
         }
     }
 
diff --git a/ojluni/src/main/java/java/net/DatagramSocketImpl.java b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
index 0f0bf81..bbabc03 100755
--- a/ojluni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
@@ -47,6 +47,12 @@
      */
     protected FileDescriptor fd;
 
+    int dataAvailable() {
+        // default impl returns zero, which disables the calling
+        // functionality
+        return 0;
+    }
+
     /**
      * Creates a datagram socket.
      * @exception SocketException if there is an error in the
diff --git a/ojluni/src/main/java/sun/net/www/ApplicationLaunchException.java b/ojluni/src/main/java/java/net/InetAddressContainer.java
old mode 100755
new mode 100644
similarity index 70%
rename from ojluni/src/main/java/sun/net/www/ApplicationLaunchException.java
rename to ojluni/src/main/java/java/net/InetAddressContainer.java
index 3394cd3..28b6402
--- a/ojluni/src/main/java/sun/net/www/ApplicationLaunchException.java
+++ b/ojluni/src/main/java/java/net/InetAddressContainer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, 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
@@ -23,19 +23,8 @@
  * questions.
  */
 
-package sun.net.www;
+package java.net;
 
-/**
- * An exception thrown by the MimeLauncher when it is unable to launch
- * an external content viewer.
- *
- * @author      Sunita Mani
- */
-
-public class ApplicationLaunchException extends Exception {
-    private static final long serialVersionUID = -4782286141289536883L;
-
-    public ApplicationLaunchException(String reason) {
-        super(reason);
-    }
+class InetAddressContainer {
+    InetAddress addr;
 }
diff --git a/ojluni/src/main/java/java/net/URL.java b/ojluni/src/main/java/java/net/URL.java
index 8af827c..15d09d1 100755
--- a/ojluni/src/main/java/java/net/URL.java
+++ b/ojluni/src/main/java/java/net/URL.java
@@ -1193,15 +1193,15 @@
             // Makes okhttp the default http/https handler
             if (handler == null) {
                 try {
+                    // BEGIN android-changed
+                    // Use of okhttp for http and https
+                    // Removed unnecessary use of reflection for sun classes
                     if (protocol.equals("file")) {
-                        handler = (URLStreamHandler)Class.
-                            forName("sun.net.www.protocol.file.Handler").newInstance();
+                        handler = new sun.net.www.protocol.file.Handler();
                     } else if (protocol.equals("ftp")) {
-                        handler = (URLStreamHandler)Class.
-                            forName("sun.net.www.protocol.ftp.Handler").newInstance();
+                        handler = new sun.net.www.protocol.ftp.Handler();
                     } else if (protocol.equals("jar")) {
-                        handler = (URLStreamHandler)Class.
-                            forName("sun.net.www.protocol.jar.Handler").newInstance();
+                        handler = new sun.net.www.protocol.jar.Handler();
                     } else if (protocol.equals("http")) {
                         handler = (URLStreamHandler)Class.
                             forName("com.android.okhttp.HttpHandler").newInstance();
@@ -1209,6 +1209,7 @@
                         handler = (URLStreamHandler)Class.
                             forName("com.android.okhttp.HttpsHandler").newInstance();
                     }
+                    // END android-changed
                 } catch (Exception e) {
                     throw new AssertionError(e);
                 }
diff --git a/ojluni/src/main/java/java/text/RuleBasedCollator.java b/ojluni/src/main/java/java/text/RuleBasedCollator.java
index c54de11..3c82624 100755
--- a/ojluni/src/main/java/java/text/RuleBasedCollator.java
+++ b/ojluni/src/main/java/java/text/RuleBasedCollator.java
@@ -307,6 +307,9 @@
     /**
      * Gets the table-based rules for the collation object.
      *
+     * <p>On Android, the returned string will be empty unless this instance was
+     * constructed using {@link #RuleBasedCollator(String)}.
+     *
      * @return returns the collation rules that the table collation object
      * was created from.
      */
diff --git a/ojluni/src/main/java/java/util/Formatter.java b/ojluni/src/main/java/java/util/Formatter.java
index 9a4e234..ebfdd2d 100755
--- a/ojluni/src/main/java/java/util/Formatter.java
+++ b/ojluni/src/main/java/java/util/Formatter.java
@@ -3299,13 +3299,10 @@
                 int prec = (precision == -1 ? 6 : precision);
 
                 FormattedFloatingDecimal fd
-                    = new FormattedFloatingDecimal(value, prec,
+                    = FormattedFloatingDecimal.valueOf(value, prec,
                         FormattedFloatingDecimal.Form.SCIENTIFIC);
 
-                char[] v = new char[MAX_FD_CHARS];
-                int len = fd.getChars(v);
-
-                char[] mant = addZeros(mantissa(v, len), prec);
+                char[] mant = addZeros(fd.getMantissa(), prec);
 
                 // If the precision is zero and the '#' flag is set, add the
                 // requested decimal point.
@@ -3313,7 +3310,7 @@
                     mant = addDot(mant);
 
                 char[] exp = (value == 0.0)
-                    ? new char[] {'+','0','0'} : exponent(v, len);
+                    ? new char[] {'+','0','0'} : fd.getExponent();
 
                 int newW = width;
                 if (width != -1)
@@ -3340,15 +3337,10 @@
                 int prec = (precision == -1 ? 6 : precision);
 
                 FormattedFloatingDecimal fd
-                    = new FormattedFloatingDecimal(value, prec,
-                        FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
+                        = FormattedFloatingDecimal.valueOf(value, prec,
+                          FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
 
-                // MAX_FD_CHARS + 1 (round?)
-                char[] v = new char[MAX_FD_CHARS + 1
-                                   + Math.abs(fd.getExponent())];
-                int len = fd.getChars(v);
-
-                char[] mant = addZeros(mantissa(v, len), prec);
+                char[] mant = addZeros(fd.getMantissa(), prec);
 
                 // If the precision is zero and the '#' flag is set, add the
                 // requested decimal point.
@@ -3366,23 +3358,29 @@
                 else if (precision == 0)
                     prec = 1;
 
-                FormattedFloatingDecimal fd
-                    = new FormattedFloatingDecimal(value, prec,
-                        FormattedFloatingDecimal.Form.GENERAL);
+                char[] exp;
+                char[] mant;
+                int expRounded;
+                if (value == 0.0) {
+                    exp = null;
+                    mant = new char[] {'0'};
+                    expRounded = 0;
+                } else {
+                    FormattedFloatingDecimal fd
+                        = FormattedFloatingDecimal.valueOf(value, prec,
+                          FormattedFloatingDecimal.Form.GENERAL);
+                    exp = fd.getExponent();
+                    mant = fd.getMantissa();
+                    expRounded = fd.getExponentRounded();
+                }
 
-                // MAX_FD_CHARS + 1 (round?)
-                char[] v = new char[MAX_FD_CHARS + 1
-                                   + Math.abs(fd.getExponent())];
-                int len = fd.getChars(v);
-
-                char[] exp = exponent(v, len);
                 if (exp != null) {
                     prec -= 1;
                 } else {
-                    prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1;
+                    prec -= expRounded + 1;
                 }
 
-                char[] mant = addZeros(mantissa(v, len), prec);
+                mant = addZeros(mant, prec);
                 // If the precision is zero and the '#' flag is set, add the
                 // requested decimal point.
                 if (f.contains(Flags.ALTERNATE) && (prec == 0))
diff --git a/ojluni/src/main/java/java/util/stream/ReferencePipeline.java b/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
index 8957ee5..ddec43e 100644
--- a/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
+++ b/ojluni/src/main/java/java/util/stream/ReferencePipeline.java
@@ -436,8 +436,9 @@
         // super type of U an ArrayStoreException will be thrown.
         @SuppressWarnings("rawtypes")
         IntFunction rawGenerator = (IntFunction) generator;
-        return (A[]) Nodes.flatten(evaluateToArrayNode(rawGenerator), rawGenerator)
-                              .asArray(rawGenerator);
+        // TODO(b/29399275): Eclipse compiler requires explicit (Node<A[]>) cast below.
+        return (A[]) Nodes.flatten((Node<A[]>) evaluateToArrayNode(rawGenerator), rawGenerator)
+                .asArray(rawGenerator);
     }
 
     @Override
diff --git a/ojluni/src/main/java/sun/misc/FDBigInteger.java b/ojluni/src/main/java/sun/misc/FDBigInteger.java
new file mode 100644
index 0000000..77d6fbc
--- /dev/null
+++ b/ojluni/src/main/java/sun/misc/FDBigInteger.java
@@ -0,0 +1,1508 @@
+/*
+ * 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
+ * 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.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+    //
+    // This class contains many comments that start with "/*@" mark.
+    // They are behavourial specification in
+    // the Java Modelling Language (JML):
+    // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+    //
+
+    /*@
+    @ public pure model static \bigint UNSIGNED(int v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 32);
+    @ }
+    @
+    @ public pure model static \bigint UNSIGNED(long v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 64);
+    @ }
+    @
+    @ public pure model static \bigint AP(int[] data, int len) {
+    @     return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+    @ }
+    @
+    @ public pure model static \bigint pow52(int p5, int p2) {
+    @     ghost \bigint v = 1;
+    @     for (int i = 0; i < p5; i++) v *= 5;
+    @     return v << p2;
+    @ }
+    @
+    @ public pure model static \bigint pow10(int p10) {
+    @     return pow52(p10, p10);
+    @ }
+    @*/
+
+    static final int[] SMALL_5_POW = {
+            1,
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+    };
+
+    static final long[] LONG_5_POW = {
+            1L,
+            5L,
+            5L * 5,
+            5L * 5 * 5,
+            5L * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+    };
+
+    // Maximum size of cache of powers of 5 as FDBigIntegers.
+    private static final int MAX_FIVE_POW = 340;
+
+    // Cache of big powers of 5 as FDBigIntegers.
+    private static final FDBigInteger POW_5_CACHE[];
+
+    // Initialize FDBigInteger cache of powers of 5.
+    static {
+        POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+        int i = 0;
+        while (i < SMALL_5_POW.length) {
+            FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+            pow5.makeImmutable();
+            POW_5_CACHE[i] = pow5;
+            i++;
+        }
+        FDBigInteger prev = POW_5_CACHE[i - 1];
+        while (i < MAX_FIVE_POW) {
+            POW_5_CACHE[i] = prev = prev.mult(5);
+            prev.makeImmutable();
+            i++;
+        }
+    }
+
+    // Zero as an FDBigInteger.
+    public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+    // Ensure ZERO is immutable.
+    static {
+        ZERO.makeImmutable();
+    }
+
+    // Constant for casting an int to a long via bitwise AND.
+    private final static long LONG_MASK = 0xffffffffL;
+
+    //@ spec_public non_null;
+    private int data[];  // value: data[0] is least significant
+    //@ spec_public;
+    private int offset;  // number of least significant zero padding ints
+    //@ spec_public;
+    private int nWords;  // data[nWords-1]!=0, all values above are zero
+                 // if nWords==0 -> this FDBigInteger is zero
+    //@ spec_public;
+    private boolean isImmutable = false;
+
+    /*@
+     @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ public invariant nWords == 0 ==> offset == 0;
+     @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+     @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+     @ public pure model \bigint value() {
+     @     return AP(data, nWords) << (offset*32);
+     @ }
+     @*/
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from data and padding. The
+     * <code>data</code> parameter has the least significant <code>int</code> at
+     * the zeroth index. The <code>offset</code> parameter gives the number of
+     * zero <code>int</code>s to be inferred below the least significant element
+     * of <code>data</code>.
+     *
+     * @param data An array containing all non-zero <code>int</code>s of the value.
+     * @param offset An offset indicating the number of zero <code>int</code>s to pad
+     * below the least significant element of <code>data</code>.
+     */
+    /*@
+     @ requires data != null && offset >= 0;
+     @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+     @ ensures this.data == \old(data);
+     @*/
+    private FDBigInteger(int[] data, int offset) {
+        this.data = data;
+        this.offset = offset;
+        this.nWords = data.length;
+        trimLeadingZeros();
+    }
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from a starting value and some
+     * decimal digits.
+     *
+     * @param lValue The starting value.
+     * @param digits The decimal digits.
+     * @param kDigits The initial index into <code>digits</code>.
+     * @param nDigits The final index into <code>digits</code>.
+     */
+    /*@
+     @ requires digits != null;
+     @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+     @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+     @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+     @*/
+    public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+        int n = Math.max((nDigits + 8) / 9, 2);        // estimate size needed.
+        data = new int[n];      // allocate enough space
+        data[0] = (int) lValue;    // starting value
+        data[1] = (int) (lValue >>> 32);
+        offset = 0;
+        nWords = 2;
+        int i = kDigits;
+        int limit = nDigits - 5;       // slurp digits 5 at a time.
+        int v;
+        while (i < limit) {
+            int ilim = i + 5;
+            v = (int) digits[i++] - (int) '0';
+            while (i < ilim) {
+                v = 10 * v + (int) digits[i++] - (int) '0';
+            }
+            multAddMe(100000, v); // ... where 100000 is 10^5.
+        }
+        int factor = 1;
+        v = 0;
+        while (i < nDigits) {
+            v = 10 * v + (int) digits[i++] - (int) '0';
+            factor *= 10;
+        }
+        if (factor != 1) {
+            multAddMe(factor, v);
+        }
+        trimLeadingZeros();
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfPow52(int p5, int p2) {
+        if (p5 != 0) {
+            if (p2 == 0) {
+                return big5pow(p5);
+            } else if (p5 < SMALL_5_POW.length) {
+                int pow5 = SMALL_5_POW[p5];
+                int wordcount = p2 >> 5;
+                int bitcount = p2 & 0x1f;
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{pow5}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            pow5 << bitcount,
+                            pow5 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                return big5pow(p5).leftShift(p2);
+            }
+        } else {
+            return valueOfPow2(p2);
+        }
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param value The constant factor.
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+        assert p5 >= 0 : p5;
+        assert p2 >= 0 : p2;
+        int v0 = (int) value;
+        int v1 = (int) (value >>> 32);
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        if (p5 != 0) {
+            if (p5 < SMALL_5_POW.length) {
+                long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+                long carry = (v0 & LONG_MASK) * pow5;
+                v0 = (int) carry;
+                carry >>>= 32;
+                carry = (v1 & LONG_MASK) * pow5 + carry;
+                v1 = (int) carry;
+                int v2 = (int) (carry >>> 32);
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            v0 << bitcount,
+                            (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                            (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+                            v2 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                int[] r;
+                if (v1 == 0) {
+                    r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, r);
+                } else {
+                    r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, v1, r);
+                }
+                return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+            }
+        } else if (p2 != 0) {
+            if (bitcount == 0) {
+                return new FDBigInteger(new int[]{v0, v1}, wordcount);
+            } else {
+                return new FDBigInteger(new int[]{
+                         v0 << bitcount,
+                        (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                        v1 >>> (32 - bitcount)
+                }, wordcount);
+            }
+        }
+        return new FDBigInteger(new int[]{v0, v1}, 0);
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>2<sup>p2</sup></code>.
+     *
+     * @param p2 The exponent of 2.
+     * @return <code>2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == pow52(0, p2);
+     @*/
+    private static FDBigInteger valueOfPow2(int p2) {
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+    }
+
+    /**
+     * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+     * the offset and number of non-zero leading words accordingly.
+     */
+    /*@
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires nWords == 0 ==> offset == 0;
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    private /*@ helper @*/ void trimLeadingZeros() {
+        int i = nWords;
+        if (i > 0 && (data[--i] == 0)) {
+            //for (; i > 0 && data[i - 1] == 0; i--) ;
+            while(i > 0 && data[i - 1] == 0) {
+                i--;
+            }
+            this.nWords = i;
+            if (i == 0) { // all words are zero
+                this.offset = 0;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+     * normalization bias is a left shift such that after it the highest word
+     * of the value will have the 4 highest bits equal to zero:
+     * <code>(highestWord & 0xf0000000) == 0</code>, but the next bit should be 1
+     * <code>(highestWord & 0x08000000) != 0</code>.
+     *
+     * @return The normalization bias.
+     */
+    /*@
+     @ requires this.value() > 0;
+     @*/
+    public /*@ pure @*/ int getNormalizationBias() {
+        if (nWords == 0) {
+            throw new IllegalArgumentException("Zero value cannot be normalized");
+        }
+        int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+        return (zeros < 4) ? 28 + zeros : zeros - 4;
+    }
+
+    // TODO: Why is anticount param needed if it is always 32 - bitcount?
+    /**
+     * Left shifts the contents of one int array into another.
+     *
+     * @param src The source array.
+     * @param idx The initial index of the source array.
+     * @param result The destination array.
+     * @param bitcount The left shift.
+     * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+     * @param prev The prior source value.
+     */
+    /*@
+     @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+     @ requires src.length >= idx && result.length > idx;
+     @ assignable result[*];
+     @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+     @*/
+    private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+        for (; idx > 0; idx--) {
+            int v = (prev << bitcount);
+            prev = src[idx - 1];
+            v |= (prev >>> anticount);
+            result[idx] = v;
+        }
+        int v = prev << bitcount;
+        result[0] = v;
+    }
+
+    /**
+     * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+     * in-place unless the <code>FDBigInteger</code> is immutable in which case
+     * a new instance of <code>FDBigInteger</code> is returned.
+     *
+     * @param shift The number of bits to shift left.
+     * @return The shifted <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0 || shift == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @*/
+    public FDBigInteger leftShift(int shift) {
+        if (shift == 0 || nWords == 0) {
+            return this;
+        }
+        int wordcount = shift >> 5;
+        int bitcount = shift & 0x1f;
+        if (this.isImmutable) {
+            if (bitcount == 0) {
+                return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+            } else {
+                int anticount = 32 - bitcount;
+                int idx = nWords - 1;
+                int prev = data[idx];
+                int hi = prev >>> anticount;
+                int[] result;
+                if (hi != 0) {
+                    result = new int[nWords + 1];
+                    result[nWords] = hi;
+                } else {
+                    result = new int[nWords];
+                }
+                leftShift(data,idx,result,bitcount,anticount,prev);
+                return new FDBigInteger(result, offset + wordcount);
+            }
+        } else {
+            if (bitcount != 0) {
+                int anticount = 32 - bitcount;
+                if ((data[0] << bitcount) == 0) {
+                    int idx = 0;
+                    int prev = data[idx];
+                    for (; idx < nWords - 1; idx++) {
+                        int v = (prev >>> anticount);
+                        prev = data[idx + 1];
+                        v |= (prev << bitcount);
+                        data[idx] = v;
+                    }
+                    int v = prev >>> anticount;
+                    data[idx] = v;
+                    if(v==0) {
+                        nWords--;
+                    }
+                    offset++;
+                } else {
+                    int idx = nWords - 1;
+                    int prev = data[idx];
+                    int hi = prev >>> anticount;
+                    int[] result = data;
+                    int[] src = data;
+                    if (hi != 0) {
+                        if(nWords == data.length) {
+                            data = result = new int[nWords + 1];
+                        }
+                        result[nWords++] = hi;
+                    }
+                    leftShift(src,idx,result,bitcount,anticount,prev);
+                }
+            }
+            offset += wordcount;
+            return this;
+        }
+    }
+
+    /**
+     * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+     *
+     * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ ensures \result == 0;
+     @
+     @  also
+     @
+     @ requires this.value() > 0;
+     @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+     @*/
+    private /*@ pure @*/ int size() {
+        return nWords + offset;
+    }
+
+
+    /**
+     * Computes
+     * <pre>
+     * q = (int)( this / S )
+     * this = 10 * ( this mod S )
+     * Return q.
+     * </pre>
+     * This is the iteration step of digit development for output.
+     * We assume that S has been normalized, as above, and that
+     * "this" has been left-shifted accordingly.
+     * Also assumed, of course, is that the result, q, can be expressed
+     * as an integer, 0 <= q < 10.
+     *
+     * @param The divisor of this <code>FDBigInteger</code>.
+     * @return <code>q = (int)(this / S)</code>.
+     */
+    /*@
+     @ requires !this.isImmutable;
+     @ requires this.size() <= S.size();
+     @ requires this.data.length + this.offset >= S.size();
+     @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == \old(this.value() / S.value());
+     @ ensures this.value() == \old(10 * (this.value() % S.value()));
+     @*/
+    public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+        assert !this.isImmutable : "cannot modify immutable value";
+        // ensure that this and S have the same number of
+        // digits. If S is properly normalized and q < 10 then
+        // this must be so.
+        int thSize = this.size();
+        int sSize = S.size();
+        if (thSize < sSize) {
+            // this value is significantly less than S, result of division is zero.
+            // just mult this by 10.
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if(p!=0) {
+                this.data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return 0;
+        } else if (thSize > sSize) {
+            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.
+        long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+        long diff = multDiffMe(q, S);
+        if (diff != 0L) {
+            //@ assert q != 0;
+            //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+            //@ assert this.offset <= S.offset;
+
+            // q is too big.
+            // add S back in until this turns +. This should
+            // not be very many times!
+            long sum = 0L;
+            int tStart = S.offset - this.offset;
+            //@ assert tStart >= 0;
+            int[] sd = S.data;
+            int[] td = this.data;
+            while (sum == 0L) {
+                for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+                    sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (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!
+        int p = multAndCarryBy10(this.data, this.nWords, this.data);
+        assert p == 0 : p; // Carry out of *10
+        trimLeadingZeros();
+        return (int) q;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+     * performed in place unless the <code>FDBigInteger</code> is immutable in
+     * which case a new <code>FDBigInteger</code> will be returned.
+     *
+     * @return The <code>FDBigInteger</code> multiplied by 10.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @*/
+    public FDBigInteger multBy10() {
+        if (nWords == 0) {
+            return this;
+        }
+        if (isImmutable) {
+            int[] res = new int[nWords + 1];
+            res[nWords] = multAndCarryBy10(data, nWords, res);
+            return new FDBigInteger(res, offset);
+        } else {
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if (p != 0) {
+                if (nWords == data.length) {
+                    if (data[0] == 0) {
+                        System.arraycopy(data, 1, data, 0, --nWords);
+                        offset++;
+                    } else {
+                        data = Arrays.copyOf(data, data.length + 1);
+                    }
+                }
+                data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return this;
+        }
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+     * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+     * will be returned.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return
+     */
+    /*@
+     @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @*/
+    public FDBigInteger multByPow52(int p5, int p2) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        FDBigInteger res = this;
+        if (p5 != 0) {
+            int[] r;
+            int extraSize = (p2 != 0) ? 1 : 0;
+            if (p5 < SMALL_5_POW.length) {
+                r = new int[this.nWords + 1 + extraSize];
+                mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+                res = new FDBigInteger(r, this.offset);
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                r = new int[this.nWords + pow5.size() + extraSize];
+                mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+                res = new FDBigInteger(r, this.offset + pow5.offset);
+            }
+        }
+        return res.leftShift(p2);
+    }
+
+    /**
+     * Multiplies two big integers represented as int arrays.
+     *
+     * @param s1 The first array factor.
+     * @param s1Len The number of elements of <code>s1</code> to use.
+     * @param s2 The second array factor.
+     * @param s2Len The number of elements of <code>s2</code> to use.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires s1 != dst && s2 != dst;
+     @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+     @ assignable dst[0 .. s1Len + s2Len - 1];
+     @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+     @*/
+    private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+        for (int i = 0; i < s1Len; i++) {
+            long v = s1[i] & LONG_MASK;
+            long p = 0L;
+            for (int j = 0; j < s2Len; j++) {
+                p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+                dst[i + j] = (int) p;
+                p >>>= 32;
+            }
+            dst[i + s2Len] = (int) p;
+        }
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the subtrahend is immutable, store the result in this(minuend).
+     * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires this.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend;
+        if (this.isImmutable) {
+            minuend = new FDBigInteger(this.data.clone(), this.offset);
+        } else {
+            minuend = this;
+        }
+        int offsetDiff = subtrahend.offset - minuend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            // need to expand minuend
+            int rLen = minLen - offsetDiff;
+            if (rLen < mData.length) {
+                System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+                Arrays.fill(mData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+                minuend.data = mData = r;
+            }
+            minuend.offset = subtrahend.offset;
+            minuend.nWords = minLen = rLen;
+            offsetDiff = 0;
+        }
+        long borrow = 0L;
+        int mIndex = offsetDiff;
+        for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        for (; borrow != 0 && mIndex < minLen; mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        minuend.trimLeadingZeros();
+        return minuend;
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the this(minuend) is immutable, store the result in subtrahend.
+     * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+     @ ensures \result == subtrahend;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend = this;
+        if (subtrahend.isImmutable) {
+            subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+        }
+        int offsetDiff = minuend.offset - subtrahend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            int rLen = minLen;
+            if (rLen < sData.length) {
+                System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+                Arrays.fill(sData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+                subtrahend.data = sData = r;
+            }
+            subtrahend.offset = minuend.offset;
+            subLen -= offsetDiff;
+            offsetDiff = 0;
+        } else {
+            int rLen = minLen + offsetDiff;
+            if (rLen >= sData.length) {
+                subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+            }
+        }
+        //@ assert minuend == this && minuend.value() == \old(this.value());
+        //@ assert mData == minuend.data && minLen == minuend.nWords;
+        //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+        //@ assert sData == subtrahend.data;
+        //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+        //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+        //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+        //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+        int sIndex = 0;
+        long borrow = 0L;
+        for (; sIndex < offsetDiff; sIndex++) {
+            long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        //@ assert sIndex == offsetDiff;
+        for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+            //@ assert sIndex == offsetDiff + mIndex;
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        subtrahend.nWords = sIndex;
+        subtrahend.trimLeadingZeros();
+        return subtrahend;
+
+    }
+
+    /**
+     * Determines whether all elements of an array are zero for all indices less
+     * than a given index.
+     *
+     * @param a The array to be examined.
+     * @param from The index strictly below which elements are to be examined.
+     * @return Zero if all elements in range are zero, 1 otherwise.
+     */
+    /*@
+     @ requires 0 <= from && from <= a.length;
+     @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+     @*/
+    private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+        while (from > 0) {
+            if (a[--from] != 0) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+     * integer accordingly as:
+     * <pre>
+     * >0: this > other
+     *  0: this == other
+     * <0: this < other
+     * </pre>
+     *
+     * @param other The <code>FDBigInteger</code> to compare.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmp(FDBigInteger other) {
+        int aSize = nWords + offset;
+        int bSize = other.nWords + other.offset;
+        if (aSize > bSize) {
+            return 1;
+        } else if (aSize < bSize) {
+            return -1;
+        }
+        int aLen = nWords;
+        int bLen = other.nWords;
+        while (aLen > 0 && bLen > 0) {
+            int a = data[--aLen];
+            int b = other.data[--bLen];
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+        }
+        if (aLen > 0) {
+            return checkZeroTail(data, aLen);
+        }
+        if (bLen > 0) {
+            return -checkZeroTail(other.data, bLen);
+        }
+        return 0;
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     * Returns an integer accordingly as:
+     * <pre>
+     * >0: this > other
+     *  0: this == other
+     * <0: this < other
+     * </pre>
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() >  pow52(p5, p2) ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+        if (p5 == 0) {
+            int wordcount = p2 >> 5;
+            int bitcount = p2 & 0x1f;
+            int size = this.nWords + this.offset;
+            if (size > wordcount + 1) {
+                return 1;
+            } else if (size < wordcount + 1) {
+                return -1;
+            }
+            int a = this.data[this.nWords -1];
+            int b = 1 << bitcount;
+            if (a != b) {
+                return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+            return checkZeroTail(this.data, this.nWords - 1);
+        }
+        return this.cmp(big5pow(p5).leftShift(p2));
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+     * value according to the comparison as:
+     * <pre>
+     * -1: this <  x + y
+     *  0: this == x + y
+     *  1: this >  x + y
+     * </pre>
+     * @param x The first addend of the sum to compare.
+     * @param y The second addend of the sum to compare.
+     * @return -1, 0, or 1 according to the result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+        FDBigInteger big;
+        FDBigInteger small;
+        int xSize = x.size();
+        int ySize = y.size();
+        int bSize;
+        int sSize;
+        if (xSize >= ySize) {
+            big = x;
+            small = y;
+            bSize = xSize;
+            sSize = ySize;
+        } else {
+            big = y;
+            small = x;
+            bSize = ySize;
+            sSize = xSize;
+        }
+        int thSize = this.size();
+        if (bSize == 0) {
+            return thSize == 0 ? 0 : 1;
+        }
+        if (sSize == 0) {
+            return this.cmp(big);
+        }
+        if (bSize > thSize) {
+            return -1;
+        }
+        if (bSize + 1 < thSize) {
+            return 1;
+        }
+        long top = (big.data[big.nWords - 1] & LONG_MASK);
+        if (sSize == bSize) {
+            top += (small.data[small.nWords - 1] & LONG_MASK);
+        }
+        if ((top >>> 32) == 0) {
+            if (((top + 1) >>> 32) == 0) {
+                // good case - no carry extension
+                if (bSize < thSize) {
+                    return 1;
+                }
+                // here sum.nWords == this.nWords
+                long v = (this.data[this.nWords - 1] & LONG_MASK);
+                if (v < top) {
+                    return -1;
+                }
+                if (v > top + 1) {
+                    return 1;
+                }
+            }
+        } else { // (top>>>32)!=0 guaranteed carry extension
+            if (bSize + 1 > thSize) {
+                return -1;
+            }
+            // here sum.nWords == this.nWords
+            top >>>= 32;
+            long v = (this.data[this.nWords - 1] & LONG_MASK);
+            if (v < top) {
+                return -1;
+            }
+            if (v > top + 1) {
+                return 1;
+            }
+        }
+        return this.cmp(big.add(small));
+    }
+
+    /**
+     * Makes this <code>FDBigInteger</code> immutable.
+     */
+    /*@
+     @ assignable this.isImmutable;
+     @ ensures this.isImmutable;
+     @*/
+    public void makeImmutable() {
+        this.isImmutable = true;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by an integer.
+     *
+     * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+     * @return This <code>FDBigInteger</code> multiplied by an integer.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+     @*/
+    private FDBigInteger mult(int i) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        int[] r = new int[nWords + 1];
+        mult(data, nWords, i, r);
+        return new FDBigInteger(r, offset);
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> factor by which to multiply.
+     * @return The product of this and the parameter <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == other;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * other.value());
+     @*/
+    private FDBigInteger mult(FDBigInteger other) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        if (this.size() == 1) {
+            return other.mult(data[0]);
+        }
+        if (other.nWords == 0) {
+            return other;
+        }
+        if (other.size() == 1) {
+            return this.mult(other.data[0]);
+        }
+        int[] r = new int[nWords + other.nWords];
+        mult(this.data, this.nWords, other.data, other.nWords, r);
+        return new FDBigInteger(r, this.offset + other.offset);
+    }
+
+    /**
+     * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> to add.
+     * @return The sum of the <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() + other.value());
+     @*/
+    private FDBigInteger add(FDBigInteger other) {
+        FDBigInteger big, small;
+        int bigLen, smallLen;
+        int tSize = this.size();
+        int oSize = other.size();
+        if (tSize >= oSize) {
+            big = this;
+            bigLen = tSize;
+            small = other;
+            smallLen = oSize;
+        } else {
+            big = other;
+            bigLen = oSize;
+            small = this;
+            smallLen = tSize;
+        }
+        int[] r = new int[bigLen + 1];
+        int i = 0;
+        long carry = 0L;
+        for (; i < smallLen; i++) {
+            carry += (i < big.offset   ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+                   + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        for (; i < bigLen; i++) {
+            carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        r[bigLen] = (int) carry;
+        return new FDBigInteger(r, 0);
+    }
+
+
+    /**
+     * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+     * result is computed in place. This method is intended only to be invoked
+     * from
+     * <code>
+     * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+     * </code>.
+     *
+     * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+     * @param addend The value to add to the product of this
+     * <code>FDBigInteger</code> and <code>iv</code>.
+     */
+    /*@
+     @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+     @ assignable this.data[*];
+     @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+     @*/
+    private /*@ helper @*/ void multAddMe(int iv, int addend) {
+        long v = iv & LONG_MASK;
+        // unroll 0th iteration, doing addition.
+        long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+        data[0] = (int) p;
+        p >>>= 32;
+        for (int i = 1; i < nWords; i++) {
+            p += v * (data[i] & LONG_MASK);
+            data[i] = (int) p;
+            p >>>= 32;
+        }
+        if (p != 0L) {
+            data[nWords++] = (int) p; // will fail noisily if illegal!
+        }
+    }
+
+    //
+    // original doc:
+    //
+    // do this -=q*S
+    // returns borrow
+    //
+    /**
+     * Multiplies the parameters and subtracts them from this
+     * <code>FDBigInteger</code>.
+     *
+     * @param q The integer parameter.
+     * @param S The <code>FDBigInteger</code> parameter.
+     * @return <code>this - q*S</code>.
+     */
+    /*@
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    /*@
+     @ requires 0 < q && q <= (1L << 31);
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires !this.isImmutable;
+     @ requires this.size() == S.size();
+     @ requires this != S;
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures -q <= \result && \result <= 0;
+     @ ensures this.size() == \old(this.size());
+     @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+     @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+     @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+     @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+     @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+     @
+     @  also
+     @
+     @ requires q == 0;
+     @ assignable \nothing;
+     @ ensures \result == 0;
+     @*/
+    private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+        long diff = 0L;
+        if (q != 0) {
+            int deltaSize = S.offset - this.offset;
+            if (deltaSize >= 0) {
+                int[] sd = S.data;
+                int[] td = this.data;
+                for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+            } else {
+                deltaSize = -deltaSize;
+                int[] rd = new int[nWords + deltaSize];
+                int sIndex = 0;
+                int rIndex = 0;
+                int[] sd = S.data;
+                for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+                    diff -= q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                int tIndex = 0;
+                int[] td = this.data;
+                for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                this.nWords += deltaSize;
+                this.offset -= deltaSize;
+                this.data = rd;
+            }
+        }
+        return diff;
+    }
+
+
+    /**
+     * Multiplies by 10 a big integer represented as an array. The final carry
+     * is returned.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param dst The product array.
+     * @return The final carry of the multiplication.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen;
+     @ assignable dst[0 .. srcLen - 1];
+     @ ensures 0 <= \result && \result < 10;
+     @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+     @*/
+    private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * 10L + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        return (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is an <code>int</code>.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param value The constant factor by which to multiply.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+     @ assignable dst[0 .. srcLen];
+     @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+     @*/
+    private static void mult(int[] src, int srcLen, int value, int[] dst) {
+        long val = value & LONG_MASK;
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * val + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is a long represent as two <code>int</code>s.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param v0 The lower 32 bits of the long factor.
+     * @param v1 The upper 32 bits of the long factor.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src != dst;
+     @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+     @ assignable dst[0 .. srcLen + 1];
+     @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+     @*/
+    private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+        long v = v0 & LONG_MASK;
+        long carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = v * (src[j] & LONG_MASK) + carry;
+            dst[j] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+        v = v1 & LONG_MASK;
+        carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+            dst[j + 1] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen + 1] = (int) carry;
+    }
+
+    // Fails assertion for negative exponent.
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5pow(int p) {
+        assert p >= 0 : p; // negative power of 5
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        return big5powRec(p);
+    }
+
+    // slow path
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5powRec(int p) {
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        // construct the value.
+        // recursively.
+        int q, r;
+        // in order to compute 5^p,
+        // compute its square root, 5^(p/2) and square.
+        // or, let q = p / 2, r = p -q, then
+        // 5^p = 5^(q+r) = 5^q * 5^r
+        q = p >> 1;
+        r = p - q;
+        FDBigInteger bigq = big5powRec(q);
+        if (r < SMALL_5_POW.length) {
+            return bigq.mult(SMALL_5_POW[r]);
+        } else {
+            return bigq.mult(big5powRec(r));
+        }
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+     *
+     * @return The hexadecimal string representation.
+     */
+    public String toHexString(){
+        if(nWords ==0) {
+            return "0";
+        }
+        StringBuilder sb = new StringBuilder((nWords +offset)*8);
+        for(int i= nWords -1; i>=0; i--) {
+            String subStr = Integer.toHexString(data[i]);
+            for(int j = subStr.length(); j<8; j++) {
+                sb.append('0');
+            }
+            sb.append(subStr);
+        }
+        for(int i=offset; i>0; i--) {
+            sb.append("00000000");
+        }
+        return sb.toString();
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+     *
+     * @return The <code>BigInteger</code> representation.
+     */
+    public BigInteger toBigInteger() {
+        byte[] magnitude = new byte[nWords * 4 + 1];
+        for (int i = 0; i < nWords; i++) {
+            int w = data[i];
+            magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+            magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+            magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+            magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+        }
+        return new BigInteger(magnitude).shiftLeft(offset * 32);
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a string.
+     *
+     * @return The string representation.
+     */
+    @Override
+    public String toString(){
+        return toBigInteger().toString();
+    }
+}
diff --git a/ojluni/src/main/java/sun/misc/FloatingDecimal.java b/ojluni/src/main/java/sun/misc/FloatingDecimal.java
new file mode 100644
index 0000000..ddd8790
--- /dev/null
+++ b/ojluni/src/main/java/sun/misc/FloatingDecimal.java
@@ -0,0 +1,2541 @@
+/*
+ * 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
+ * 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.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+    //
+    // Constants of the implementation;
+    // most are IEEE-754 related.
+    // (There are more really boring constants at the end.)
+    //
+    static final int    EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+    static final long   FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+    static final long   EXP_ONE   = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+    static final int    MAX_SMALL_BIN_EXP = 62;
+    static final int    MIN_SMALL_BIN_EXP = -( 63 / 3 );
+    static final int    MAX_DECIMAL_DIGITS = 15;
+    static final int    MAX_DECIMAL_EXPONENT = 308;
+    static final int    MIN_DECIMAL_EXPONENT = -324;
+    static final int    BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+    static final int    MAX_NDIGITS = 1100;
+
+    static final int    SINGLE_EXP_SHIFT  =   FloatConsts.SIGNIFICAND_WIDTH - 1;
+    static final int    SINGLE_FRACT_HOB  =   1<<SINGLE_EXP_SHIFT;
+    static final int    SINGLE_MAX_DECIMAL_DIGITS = 7;
+    static final int    SINGLE_MAX_DECIMAL_EXPONENT = 38;
+    static final int    SINGLE_MIN_DECIMAL_EXPONENT = -45;
+    static final int    SINGLE_MAX_NDIGITS = 200;
+
+    static final int    INT_DECIMAL_DIGITS = 9;
+
+    /**
+     * Converts a double precision floating point value to a <code>String</code>.
+     *
+     * @param d The double precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(double d) {
+        return getBinaryToASCIIConverter(d).toJavaFormatString();
+    }
+
+    /**
+     * Converts a single precision floating point value to a <code>String</code>.
+     *
+     * @param f The single precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(float f) {
+        return getBinaryToASCIIConverter(f).toJavaFormatString();
+    }
+
+    /**
+     * Appends a double precision floating point value to an <code>Appendable</code>.
+     * @param d The double precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(double d, Appendable buf) {
+        getBinaryToASCIIConverter(d).appendTo(buf);
+    }
+
+    /**
+     * Appends a single precision floating point value to an <code>Appendable</code>.
+     * @param f The single precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(float f, Appendable buf) {
+        getBinaryToASCIIConverter(f).appendTo(buf);
+    }
+
+    /**
+     * Converts a <code>String</code> to a double precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The double precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted double precision value.
+     */
+    public static double parseDouble(String s) throws NumberFormatException {
+        return readJavaFormatString(s).doubleValue();
+    }
+
+    /**
+     * Converts a <code>String</code> to a single precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The single precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted single precision value.
+     */
+    public static float parseFloat(String s) throws NumberFormatException {
+        return readJavaFormatString(s).floatValue();
+    }
+
+    /**
+     * A converter which can process single or double precision floating point
+     * values into an ASCII <code>String</code> representation.
+     */
+    public interface BinaryToASCIIConverter {
+        /**
+         * Converts a floating point value into an ASCII <code>String</code>.
+         * @return The value converted to a <code>String</code>.
+         */
+        public String toJavaFormatString();
+
+        /**
+         * Appends a floating point value to an <code>Appendable</code>.
+         * @param buf The <code>Appendable</code> to receive the value.
+         */
+        public void appendTo(Appendable buf);
+
+        /**
+         * Retrieves the decimal exponent most closely corresponding to this value.
+         * @return The decimal exponent.
+         */
+        public int getDecimalExponent();
+
+        /**
+         * Retrieves the value as an array of digits.
+         * @param digits The digit array.
+         * @return The number of valid digits copied into the array.
+         */
+        public int getDigits(char[] digits);
+
+        /**
+         * Indicates the sign of the value.
+         * @return <code>value < 0.0</code>.
+         */
+        public boolean isNegative();
+
+        /**
+         * Indicates whether the value is either infinite or not a number.
+         *
+         * @return <code>true</code> if and only if the value is <code>NaN</code>
+         * or infinite.
+         */
+        public boolean isExceptional();
+
+        /**
+         * Indicates whether the value was rounded up during the binary to ASCII
+         * conversion.
+         *
+         * @return <code>true</code> if and only if the value was rounded up.
+         */
+        public boolean digitsRoundedUp();
+
+        /**
+         * Indicates whether the binary to ASCII conversion was exact.
+         *
+         * @return <code>true</code> if any only if the conversion was exact.
+         */
+        public boolean decimalDigitsExact();
+    }
+
+    /**
+     * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+     * and infinite values.
+     */
+    private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        final private String image;
+        private boolean isNegative;
+
+        public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+            this.image = image;
+            this.isNegative = isNegative;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            return image;
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(image);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(image);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            throw new IllegalArgumentException("Exceptional value does not have an exponent");
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            throw new IllegalArgumentException("Exceptional value does not have digits");
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return true;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            throw new IllegalArgumentException("Exceptional value is not rounded");
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            throw new IllegalArgumentException("Exceptional value is not exact");
+        }
+    }
+
+    private static final String INFINITY_REP = "Infinity";
+    private static final int INFINITY_LENGTH = INFINITY_REP.length();
+    private static final String NAN_REP = "NaN";
+    private static final int NAN_LENGTH = NAN_REP.length();
+
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+    private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true,  new char[]{'0'});
+
+    /**
+     * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+     */
+    static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        private boolean isNegative;
+        private int decExponent;
+        private int firstDigitIndex;
+        private int nDigits;
+        private final char[] digits;
+        private final char[] buffer = new char[26];
+
+        //
+        // The fields below provide additional information about the result of
+        // the binary to decimal digits conversion done in dtoa() and roundup()
+        // methods. They are changed if needed by those two methods.
+        //
+
+        // True if the dtoa() binary to decimal conversion was exact.
+        private boolean exactDecimalConversion = false;
+
+        // True if the result of the binary to decimal conversion was rounded-up
+        // at the end of the conversion process, i.e. roundUp() method was called.
+        private boolean decimalDigitsRoundedUp = false;
+
+        /**
+         * Default constructor; used for non-zero values,
+         * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+         */
+        BinaryToASCIIBuffer(){
+            this.digits = new char[20];
+        }
+
+        /**
+         * Creates a specialized value (positive and negative zeros).
+         */
+        BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+            this.isNegative = isNegative;
+            this.decExponent  = 0;
+            this.digits = digits;
+            this.firstDigitIndex = 0;
+            this.nDigits = digits.length;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            int len = getChars(buffer);
+            return new String(buffer, 0, len);
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            int len = getChars(buffer);
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(buffer, 0, len);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(buffer, 0, len);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            return decExponent;
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+            return this.nDigits;
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return false;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            return decimalDigitsRoundedUp;
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            return exactDecimalConversion;
+        }
+
+        private void setSign(boolean isNegative) {
+            this.isNegative = isNegative;
+        }
+
+        /**
+         * This is the easy subcase --
+         * all the significant bits, after scaling, are held in lvalue.
+         * negSign and decExponent tell us what processing and scaling
+         * has already been done. Exceptional cases have already been
+         * stripped out.
+         * In particular:
+         * lvalue is a finite number (not Inf, nor NaN)
+         * lvalue > 0L (not zero, nor negative).
+         *
+         * The only reason that we develop the digits here, rather than
+         * calling on Long.toString() is that we can do it a little faster,
+         * and besides want to treat trailing 0s specially. If Long.toString
+         * changes, we should re-evaluate this strategy!
+         */
+        private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
+            if ( insignificantDigits != 0 ){
+                // Discard non-significant low-order bits, while rounding,
+                // up to insignificant value.
+                long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+                long residue = lvalue % pow10;
+                lvalue /= pow10;
+                decExponent += insignificantDigits;
+                if ( residue >= (pow10>>1) ){
+                    // round up based on the low-order bits we're discarding
+                    lvalue++;
+                }
+            }
+            int  digitno = digits.length -1;
+            int  c;
+            if ( lvalue <= Integer.MAX_VALUE ){
+                assert lvalue > 0L : lvalue; // lvalue <= 0
+                // even easier subcase!
+                // can do int arithmetic rather than long!
+                int  ivalue = (int)lvalue;
+                c = ivalue%10;
+                ivalue /= 10;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                while ( ivalue != 0){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            } else {
+                // same algorithm as above (same bugs, too )
+                // but using long arithmetic.
+                c = (int)(lvalue%10L);
+                lvalue /= 10L;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10L;
+                }
+                while ( lvalue != 0L ){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            }
+            this.decExponent = decExponent+1;
+            this.firstDigitIndex = digitno;
+            this.nDigits = this.digits.length - digitno;
+        }
+
+        private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+        {
+            assert fractBits > 0 ; // fractBits here can't be zero or negative
+            assert (fractBits & FRACT_HOB)!=0  ; // Hi-order bit should be set
+            // Examine number. Determine if it is an easy case,
+            // which we can do pretty trivially using float/long conversion,
+            // or whether we must do real work.
+            final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+            // number of significant bits of fractBits;
+            final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+            // reset flags to default values as dtoa() does not always set these
+            // flags and a prior call to dtoa() might have set them to incorrect
+            // values with respect to the current state.
+            decimalDigitsRoundedUp = false;
+            exactDecimalConversion = false;
+
+            // number of significant bits to the right of the point.
+            int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+            if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+                // Look more closely at the number to decide if,
+                // with scaling by 10^nTinyBits, the result will fit in
+                // a long.
+                if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+                    //
+                    // We can do this:
+                    // take the fraction bits, which are normalized.
+                    // (a) nTinyBits == 0: Shift left or right appropriately
+                    //     to align the binary point at the extreme right, i.e.
+                    //     where a long int point is expected to be. The integer
+                    //     result is easily converted to a string.
+                    // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+                    //     which effectively converts to long and scales by
+                    //     2^nTinyBits. Then multiply by 5^nTinyBits to
+                    //     complete the scaling. We know this won't overflow
+                    //     because we just counted the number of bits necessary
+                    //     in the result. The integer you get from this can
+                    //     then be converted to a string pretty easily.
+                    //
+                    if ( nTinyBits == 0 ) {
+                        int insignificant;
+                        if ( binExp > nSignificantBits ){
+                            insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+                        } else {
+                            insignificant = 0;
+                        }
+                        if ( binExp >= EXP_SHIFT ){
+                            fractBits <<= (binExp-EXP_SHIFT);
+                        } else {
+                            fractBits >>>= (EXP_SHIFT-binExp) ;
+                        }
+                        developLongDigits( 0, fractBits, insignificant );
+                        return;
+                    }
+                    //
+                    // The following causes excess digits to be printed
+                    // out in the single-float case. Our manipulation of
+                    // halfULP here is apparently not correct. If we
+                    // better understand how this works, perhaps we can
+                    // use this special case again. But for the time being,
+                    // we do not.
+                    // else {
+                    //     fractBits >>>= EXP_SHIFT+1-nFractBits;
+                    //     fractBits//= long5pow[ nTinyBits ];
+                    //     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+                    //     developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+                    //     return;
+                    // }
+                    //
+                }
+            }
+            //
+            // This is the hard case. We are going to compute large positive
+            // integers B and S and integer decExp, s.t.
+            //      d = ( B / S )// 10^decExp
+            //      1 <= B / S < 10
+            // Obvious choices are:
+            //      decExp = floor( log10(d) )
+            //      B      = d// 2^nTinyBits// 10^max( 0, -decExp )
+            //      S      = 10^max( 0, decExp)// 2^nTinyBits
+            // (noting that nTinyBits has already been forced to non-negative)
+            // I am also going to compute a large positive integer
+            //      M      = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+            // i.e. M is (1/2) of the ULP of d, scaled like B.
+            // When we iterate through dividing B/S and picking off the
+            // quotient bits, we will know when to stop when the remainder
+            // is <= M.
+            //
+            // We keep track of powers of 2 and powers of 5.
+            //
+            int decExp = estimateDecExp(fractBits,binExp);
+            int B2, B5; // powers of 2 and powers of 5, respectively, in B
+            int S2, S5; // powers of 2 and powers of 5, respectively, in S
+            int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+            B5 = Math.max( 0, -decExp );
+            B2 = B5 + nTinyBits + binExp;
+
+            S5 = Math.max( 0, decExp );
+            S2 = S5 + nTinyBits;
+
+            M5 = B5;
+            M2 = B2 - nSignificantBits;
+
+            //
+            // the long integer fractBits contains the (nFractBits) interesting
+            // bits from the mantissa of d ( hidden 1 added if necessary) followed
+            // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+            // I will shift out those zeros before turning fractBits into a
+            // FDBigInteger. The resulting whole number will be
+            //      d * 2^(nFractBits-1-binExp).
+            //
+            fractBits >>>= tailZeros;
+            B2 -= nFractBits-1;
+            int common2factor = Math.min( B2, S2 );
+            B2 -= common2factor;
+            S2 -= common2factor;
+            M2 -= common2factor;
+
+            //
+            // HACK!! For exact powers of two, the next smallest number
+            // is only half as far away as we think (because the meaning of
+            // ULP changes at power-of-two bounds) for this reason, we
+            // hack M2. Hope this works.
+            //
+            if ( nFractBits == 1 ) {
+                M2 -= 1;
+            }
+
+            if ( M2 < 0 ){
+                // oops.
+                // since we cannot scale M down far enough,
+                // we must scale the other values up.
+                B2 -= M2;
+                S2 -= M2;
+                M2 =  0;
+            }
+            //
+            // Construct, Scale, iterate.
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            int ndigit = 0;
+            boolean low, high;
+            long lowDigitDifference;
+            int  q;
+
+            //
+            // Detect the special cases where all the numbers we are about
+            // to compute will fit in int or long integers.
+            // In these cases, we will avoid doing FDBigInteger arithmetic.
+            // We use the same algorithms, except that we "normalize"
+            // our FDBigIntegers before iterating. This is to make division easier,
+            // as it makes our fist guess (quotient of high-order words)
+            // more accurate!
+            //
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            // binary digits needed to represent B, approx.
+            int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+            // binary digits needed to represent 10*S, approx.
+            int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+            if ( Bbits < 64 && tenSbits < 64){
+                if ( Bbits < 32 && tenSbits < 32){
+                    // wa-hoo! They're all ints!
+                    int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+                    int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+                    int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+                    int tens = s * 10;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = b / s;
+                    b = 10 * ( b % s );
+                    m *= 10;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = b / s;
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q; // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                } else {
+                    // still good! they're all longs!
+                    long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+                    long s = FDBigInteger.LONG_5_POW[S5] << S2;
+                    long m = FDBigInteger.LONG_5_POW[M5] << M2;
+                    long tens = s * 10L;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = (int) ( b / s );
+                    b = 10L * ( b % s );
+                    m *= 10L;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = (int) ( b / s );
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q;  // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                }
+            } else {
+                //
+                // We really must do FDBigInteger arithmetic.
+                // Fist, construct our FDBigInteger initial values.
+                //
+                FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+                int shiftBias = Sval.getNormalizationBias();
+                Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+                FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+                FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+                FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+                //
+                // Unroll the first iteration. If our decExp estimate
+                // was too high, our first quotient will be zero. In this
+                // case, we discard it and decrement decExp.
+                //
+                ndigit = 0;
+                q = Bval.quoRemIteration( Sval );
+                low  = (Bval.cmp( Mval ) < 0);
+                high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+                assert q < 10 : q; // excessively large digit
+                if ( (q == 0) && ! high ){
+                    // oops. Usually ignore leading zero.
+                    decExp--;
+                } else {
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                //
+                // HACK! Java spec sez that we always have at least
+                // one digit after the . in either F- or E-form output.
+                // Thus we will need more than one digit if we're using
+                // E-form
+                //
+                if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                    high = low = false;
+                }
+                while( ! low && ! high ){
+                    q = Bval.quoRemIteration( Sval );
+                    assert q < 10 : q;  // excessively large digit
+                    Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+                    low  = (Bval.cmp( Mval ) < 0);
+                    high = tenSval.addAndCmp(Bval,Mval)<=0;
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                if ( high && low ){
+                    Bval = Bval.leftShift(1);
+                    lowDigitDifference = Bval.cmp(tenSval);
+                } else {
+                    lowDigitDifference = 0L; // this here only for flow analysis!
+                }
+                exactDecimalConversion  = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+            }
+            this.decExponent = decExp+1;
+            this.firstDigitIndex = 0;
+            this.nDigits = ndigit;
+            //
+            // Last digit gets rounded based on stopping condition.
+            //
+            if ( high ){
+                if ( low ){
+                    if ( lowDigitDifference == 0L ){
+                        // it's a tie!
+                        // choose based on which digits we like.
+                        if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+                            roundup();
+                        }
+                    } else if ( lowDigitDifference > 0 ){
+                        roundup();
+                    }
+                } else {
+                    roundup();
+                }
+            }
+        }
+
+        // add one to the least significant digit.
+        // in the unlikely event there is a carry out, deal with it.
+        // assert that this will only happen where there
+        // is only one digit, e.g. (float)1e-44 seems to do it.
+        //
+        private void roundup() {
+            int i = (firstDigitIndex + nDigits - 1);
+            int q = digits[i];
+            if (q == '9') {
+                while (q == '9' && i > firstDigitIndex) {
+                    digits[i] = '0';
+                    q = digits[--i];
+                }
+                if (q == '9') {
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    decExponent += 1;
+                    digits[firstDigitIndex] = '1';
+                    return;
+                }
+                // else fall through.
+            }
+            digits[i] = (char) (q + 1);
+            decimalDigitsRoundedUp = true;
+        }
+
+        /**
+         * Estimate decimal exponent. (If it is small-ish,
+         * we could double-check.)
+         *
+         * First, scale the mantissa bits such that 1 <= d2 < 2.
+         * We are then going to estimate
+         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
+         * and so we can estimate
+         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
+         * take the floor and call it decExp.
+         */
+        static int estimateDecExp(long fractBits, int binExp) {
+            double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+            double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+            long dBits = Double.doubleToRawLongBits(d);  //can't be NaN here so use raw
+            int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+            boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+            if(exponent>=0 && exponent<52) { // hot path
+                long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+                int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+                return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+            } else if (exponent < 0) {
+                return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+                        ( (isNegative) ? -1 : 0) );
+            } else { //if (exponent >= 52)
+                return (int)d;
+            }
+        }
+
+        private static int insignificantDigits(int insignificant) {
+            int i;
+            for ( i = 0; insignificant >= 10L; i++ ) {
+                insignificant /= 10L;
+            }
+            return i;
+        }
+
+        /**
+         * Calculates
+         * <pre>
+         * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+         * </pre>
+         */
+        private static int insignificantDigitsForPow2(int p2) {
+            if(p2>1 && p2 < insignificantDigitsNumber.length) {
+                return insignificantDigitsNumber[p2];
+            }
+            return 0;
+        }
+
+        /**
+         *  If insignificant==(1L << ixd)
+         *  i = insignificantDigitsNumber[idx] is the same as:
+         *  int i;
+         *  for ( i = 0; insignificant >= 10L; i++ )
+         *         insignificant /= 10L;
+         */
+        private static int[] insignificantDigitsNumber = {
+            0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+            4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+            8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+            12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+            15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+            18, 18, 18, 19
+        };
+
+        // approximately ceil( log2( long5pow[i] ) )
+        private static final int[] N_5_BITS = {
+                0,
+                3,
+                5,
+                7,
+                10,
+                12,
+                14,
+                17,
+                19,
+                21,
+                24,
+                26,
+                28,
+                31,
+                33,
+                35,
+                38,
+                40,
+                42,
+                45,
+                47,
+                49,
+                52,
+                54,
+                56,
+                59,
+                61,
+        };
+
+        private int getChars(char[] result) {
+            assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+            int i = 0;
+            if (isNegative) {
+                result[0] = '-';
+                i = 1;
+            }
+            if (decExponent > 0 && decExponent < 8) {
+                // print digits.digits.
+                int charLength = Math.min(nDigits, decExponent);
+                System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+                i += charLength;
+                if (charLength < decExponent) {
+                    charLength = decExponent - charLength;
+                    Arrays.fill(result,i,i+charLength,'0');
+                    i += charLength;
+                    result[i++] = '.';
+                    result[i++] = '0';
+                } else {
+                    result[i++] = '.';
+                    if (charLength < nDigits) {
+                        int t = nDigits - charLength;
+                        System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+                        i += t;
+                    } else {
+                        result[i++] = '0';
+                    }
+                }
+            } else if (decExponent <= 0 && decExponent > -3) {
+                result[i++] = '0';
+                result[i++] = '.';
+                if (decExponent != 0) {
+                    Arrays.fill(result, i, i-decExponent, '0');
+                    i -= decExponent;
+                }
+                System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+                i += nDigits;
+            } else {
+                result[i++] = digits[firstDigitIndex];
+                result[i++] = '.';
+                if (nDigits > 1) {
+                    System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+                    i += nDigits - 1;
+                } else {
+                    result[i++] = '0';
+                }
+                result[i++] = 'E';
+                int e;
+                if (decExponent <= 0) {
+                    result[i++] = '-';
+                    e = -decExponent + 1;
+                } else {
+                    e = decExponent - 1;
+                }
+                // decExponent has 1, 2, or 3, digits
+                if (e <= 9) {
+                    result[i++] = (char) (e + '0');
+                } else if (e <= 99) {
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                } else {
+                    result[i++] = (char) (e / 100 + '0');
+                    e %= 100;
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                }
+            }
+            return i;
+        }
+
+    }
+
+    private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+            new ThreadLocal<BinaryToASCIIBuffer>() {
+                @Override
+                protected BinaryToASCIIBuffer initialValue() {
+                    return new BinaryToASCIIBuffer();
+                }
+            };
+
+    private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+        return threadLocalBinaryToASCIIBuffer.get();
+    }
+
+    /**
+     * A converter which can process an ASCII <code>String</code> representation
+     * of a single or double precision floating point value into a
+     * <code>float</code> or a <code>double</code>.
+     */
+    interface ASCIIToBinaryConverter {
+
+        double doubleValue();
+
+        float floatValue();
+
+    }
+
+    /**
+     * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+     */
+    static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        final private double doubleVal;
+        final private float floatVal;
+
+        public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+            this.doubleVal = doubleVal;
+            this.floatVal = floatVal;
+        }
+
+        @Override
+        public double doubleValue() {
+            return doubleVal;
+        }
+
+        @Override
+        public float floatValue() {
+            return floatVal;
+        }
+    }
+
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER  = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+    /**
+     * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+     */
+    static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        boolean     isNegative;
+        int         decExponent;
+        char        digits[];
+        int         nDigits;
+
+        ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+        {
+            this.isNegative = negSign;
+            this.decExponent = decExponent;
+            this.digits = digits;
+            this.nDigits = n;
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a double.
+         *
+         * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+         * ROUNDING DIRECTION in case the result is really destined
+         * for a single-precision float.
+         */
+        @Override
+        public double doubleValue() {
+            int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to a long integer.
+            //
+            // (special performance hack: start to do it using int)
+            int iValue = (int) digits[0] - (int) '0';
+            int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+            for (int i = 1; i < iDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            long lValue = (long) iValue;
+            for (int i = iDigits; i < kDigits; i++) {
+                lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+            }
+            double dValue = (double) lValue;
+            int exp = decExponent - kDigits;
+            //
+            // lValue now contains a long integer with the value of
+            // the first kDigits digits of the number.
+            // dValue contains the (double) of the same.
+            //
+
+            if (nDigits <= MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here
+                //
+                if (exp == 0 || dValue == 0.0) {
+                    return (isNegative) ? -dValue : dValue; // small floating integer
+                }
+                else if (exp >= 0) {
+                    if (exp <= MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        double rValue = dValue * SMALL_10_POW[exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    int slop = MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply dValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        dValue *= SMALL_10_POW[slop];
+                        double rValue = dValue * SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        double rValue = dValue / SMALL_10_POW[-exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            }
+
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            //
+            if (exp > 0) {
+                if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could overflow.
+                    //
+                    double t = dValue * BIG_10_POW[j];
+                    if (Double.isInfinite(t)) {
+                        //
+                        // It did overflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too large,
+                        // then use the maximum finite as our estimate
+                        // value. Else call the result infinity
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two larger than
+                        // Double.MAX_VALUE ).
+                        //
+                        t = dValue / 2.0;
+                        t *= BIG_10_POW[j];
+                        if (Double.isInfinite(t)) {
+                            return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                        }
+                        t = Double.MAX_VALUE;
+                    }
+                    dValue = t;
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0 : 0.0;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could underflow.
+                    //
+                    double t = dValue * TINY_10_POW[j];
+                    if (t == 0.0) {
+                        //
+                        // It did underflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too small,
+                        // then use the minimum finite as our estimate
+                        // value. Else call the result 0.0
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two less than
+                        // Double.MIN_VALUE ).
+                        //
+                        t = dValue * 2.0;
+                        t *= TINY_10_POW[j];
+                        if (t == 0.0) {
+                            return (isNegative) ? -0.0 : 0.0;
+                        }
+                        t = Double.MIN_VALUE;
+                    }
+                    dValue = t;
+                }
+            }
+
+            //
+            // dValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > MAX_NDIGITS) {
+                nDigits = MAX_NDIGITS + 1;
+                digits[MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+                long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+                    int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (63 - EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= DoubleConsts.EXP_BIAS;
+                int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -DoubleConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+            }
+            return Double.longBitsToDouble(ieeeBits);
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a float.
+         * This is distinct from doubleValue() to avoid the extremely
+         * unlikely case of a double rounding error, wherein the conversion
+         * to double has one rounding error, and the conversion of that double
+         * to a float has another rounding error, IN THE WRONG DIRECTION,
+         * ( because of the preference to a zero low-order bit ).
+         */
+        @Override
+        public float floatValue() {
+            int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to an integer.
+            //
+            int iValue = (int) digits[0] - (int) '0';
+            for (int i = 1; i < kDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            float fValue = (float) iValue;
+            int exp = decExponent - kDigits;
+            //
+            // iValue now contains an integer with the value of
+            // the first kDigits digits of the number.
+            // fValue contains the (float) of the same.
+            //
+
+            if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here.
+                //
+                if (exp == 0 || fValue == 0.0f) {
+                    return (isNegative) ? -fValue : fValue; // small floating integer
+                } else if (exp >= 0) {
+                    if (exp <= SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply fValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[slop];
+                        fValue *= SINGLE_SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        fValue /= SINGLE_SMALL_10_POW[-exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+                //
+                // In double-precision, this is an exact floating integer.
+                // So we can compute to double, then shorten to float
+                // with one round, and get the right answer.
+                //
+                // First, finish accumulating digits.
+                // Then convert that integer to a double, multiply
+                // by the appropriate power of ten, and convert to float.
+                //
+                long lValue = (long) iValue;
+                for (int i = kDigits; i < nDigits; i++) {
+                    lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+                }
+                double dValue = (double) lValue;
+                exp = decExponent - nDigits;
+                dValue *= SMALL_10_POW[exp];
+                fValue = (float) dValue;
+                return (isNegative) ? -fValue : fValue;
+
+            }
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            // Scaling uses doubles to avoid overflow/underflow.
+            //
+            double dValue = fValue;
+            if (exp > 0) {
+                if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0f : 0.0f;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                }
+            }
+            fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+            //
+            // fValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > SINGLE_MAX_NDIGITS) {
+                nDigits = SINGLE_MAX_NDIGITS + 1;
+                digits[SINGLE_MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+                int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= SINGLE_FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+                    int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= FloatConsts.EXP_BIAS;
+                int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -FloatConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+            }
+            return Float.intBitsToFloat(ieeeBits);
+        }
+
+
+        /**
+         * All the positive powers of 10 that can be
+         * represented exactly in double/float.
+         */
+        private static final double[] SMALL_10_POW = {
+            1.0e0,
+            1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+            1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+            1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+            1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+            1.0e21, 1.0e22
+        };
+
+        private static final float[] SINGLE_SMALL_10_POW = {
+            1.0e0f,
+            1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+            1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+        };
+
+        private static final double[] BIG_10_POW = {
+            1e16, 1e32, 1e64, 1e128, 1e256 };
+        private static final double[] TINY_10_POW = {
+            1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+        private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+        private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @return The converter.
+     */
+    public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+        return getBinaryToASCIIConverter(d, true);
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @param isCompatibleFormat
+     * @return The converter.
+     */
+    static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+        long dBits = Double.doubleToRawLongBits(d);
+        boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+        long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+        int  binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0L ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(63-EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  64-leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= FRACT_HOB;
+            nSignificantBits = EXP_SHIFT+1;
+        }
+        binExp -= DoubleConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+        return buf;
+    }
+
+    private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+        int fBits = Float.floatToRawIntBits( f );
+        boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+        int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+        int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0 ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  32 - leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= SINGLE_FRACT_HOB;
+            nSignificantBits = SINGLE_EXP_SHIFT+1;
+        }
+        binExp -= FloatConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+        return buf;
+    }
+
+    @SuppressWarnings("fallthrough")
+    static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+        boolean isNegative = false;
+        boolean signSeen   = false;
+        int     decExp;
+        char    c;
+
+    parseNumber:
+        try{
+            in = in.trim(); // don't fool around with white space.
+                            // throws NullPointerException if null
+            int len = in.length();
+            if ( len == 0 ) {
+                throw new NumberFormatException("empty String");
+            }
+            int i = 0;
+            switch (in.charAt(i)){
+            case '-':
+                isNegative = true;
+                //FALLTHROUGH
+            case '+':
+                i++;
+                signSeen = true;
+            }
+            c = in.charAt(i);
+            if(c == 'N') { // Check for NaN
+                if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+                    return A2BC_NOT_A_NUMBER;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if(c == 'I') { // Check for Infinity strings
+                if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+                    return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if (c == '0')  { // check for hexadecimal floating-point number
+                if (len > i+1 ) {
+                    char ch = in.charAt(i+1);
+                    if (ch == 'x' || ch == 'X' ) { // possible hex string
+                        return parseHexString(in);
+                    }
+                }
+            }  // look for and process decimal floating-point string
+
+            char[] digits = new char[ len ];
+            int    nDigits= 0;
+            boolean decSeen = false;
+            int decPt = 0;
+            int nLeadZero = 0;
+            int nTrailZero= 0;
+
+        skipLeadingZerosLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c == '0') {
+                    nLeadZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break skipLeadingZerosLoop;
+                }
+                i++;
+            }
+        digitLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c >= '1' && c <= '9') {
+                    digits[nDigits++] = c;
+                    nTrailZero = 0;
+                } else if (c == '0') {
+                    digits[nDigits++] = c;
+                    nTrailZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break digitLoop;
+                }
+                i++;
+            }
+            nDigits -=nTrailZero;
+            //
+            // At this point, we've scanned all the digits and decimal
+            // point we're going to see. Trim off leading and trailing
+            // zeros, which will just confuse us later, and adjust
+            // our initial decimal exponent accordingly.
+            // To review:
+            // we have seen i total characters.
+            // nLeadZero of them were zeros before any other digits.
+            // nTrailZero of them were zeros after any other digits.
+            // if ( decSeen ), then a . was seen after decPt characters
+            // ( including leading zeros which have been discarded )
+            // nDigits characters were neither lead nor trailing
+            // zeros, nor point
+            //
+            //
+            // special hack: if we saw no non-zero digits, then the
+            // answer is zero!
+            // Unfortunately, we feel honor-bound to keep parsing!
+            //
+            boolean isZero = (nDigits == 0);
+            if ( isZero &&  nLeadZero == 0 ){
+                // we saw NO DIGITS AT ALL,
+                // not even a crummy 0!
+                // this is not allowed.
+                break parseNumber; // go throw exception
+            }
+            //
+            // Our initial exponent is decPt, adjusted by the number of
+            // discarded zeros. Or, if there was no decPt,
+            // then its just nDigits adjusted by discarded trailing zeros.
+            //
+            if ( decSeen ){
+                decExp = decPt - nLeadZero;
+            } else {
+                decExp = nDigits + nTrailZero;
+            }
+
+            //
+            // Look for 'e' or 'E' and an optionally signed integer.
+            //
+            if ( (i < len) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+                int expSign = 1;
+                int expVal  = 0;
+                int reallyBig = Integer.MAX_VALUE / 10;
+                boolean expOverflow = false;
+                switch( in.charAt(++i) ){
+                case '-':
+                    expSign = -1;
+                    //FALLTHROUGH
+                case '+':
+                    i++;
+                }
+                int expAt = i;
+            expLoop:
+                while ( i < len  ){
+                    if ( expVal >= reallyBig ){
+                        // the next character will cause integer
+                        // overflow.
+                        expOverflow = true;
+                    }
+                    c = in.charAt(i++);
+                    if(c>='0' && c<='9') {
+                        expVal = expVal*10 + ( (int)c - (int)'0' );
+                    } else {
+                        i--;           // back up.
+                        break expLoop; // stop parsing exponent.
+                    }
+                }
+                int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
+                if ( expOverflow || ( expVal > expLimit ) ){
+                    //
+                    // The intent here is to end up with
+                    // infinity or zero, as appropriate.
+                    // The reason for yielding such a small decExponent,
+                    // rather than something intuitive such as
+                    // expSign*Integer.MAX_VALUE, is that this value
+                    // is subject to further manipulation in
+                    // doubleValue() and floatValue(), and I don't want
+                    // it to be able to cause overflow there!
+                    // (The only way we can get into trouble here is for
+                    // really outrageous nDigits+nTrailZero, such as 2 billion. )
+                    //
+                    decExp = expSign*expLimit;
+                } else {
+                    // this should not overflow, since we tested
+                    // for expVal > (MAX+N), where N >= abs(decExp)
+                    decExp = decExp + expSign*expVal;
+                }
+
+                // if we saw something not a digit ( or end of string )
+                // after the [Ee][+-], without seeing any digits at all
+                // this is certainly an error. If we saw some digits,
+                // but then some trailing garbage, that might be ok.
+                // so we just fall through in that case.
+                // HUMBUG
+                if ( i == expAt ) {
+                    break parseNumber; // certainly bad
+                }
+            }
+            //
+            // We parsed everything we could.
+            // If there are leftovers, then this is not good input!
+            //
+            if ( i < len &&
+                ((i != len - 1) ||
+                (in.charAt(i) != 'f' &&
+                 in.charAt(i) != 'F' &&
+                 in.charAt(i) != 'd' &&
+                 in.charAt(i) != 'D'))) {
+                break parseNumber; // go throw exception
+            }
+            if(isZero) {
+                return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+            }
+            return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+        } catch ( StringIndexOutOfBoundsException e ){ }
+        throw new NumberFormatException("For input string: \"" + in + "\"");
+    }
+
+    private static class HexFloatPattern {
+        /**
+         * Grammar is compatible with hexadecimal floating-point constants
+         * described in section 6.4.4.2 of the C99 specification.
+         */
+        private static final Pattern VALUE = Pattern.compile(
+                   //1           234                   56                7                   8      9
+                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+                    );
+    }
+
+    /**
+     * Converts string s to a suitable floating decimal; uses the
+     * double constructor and sets the roundDir variable appropriately
+     * in case the value is later converted to a float.
+     *
+     * @param s The <code>String</code> to parse.
+     */
+   static ASCIIToBinaryConverter parseHexString(String s) {
+            // Verify string is a member of the hexadecimal floating-point
+            // string language.
+            Matcher m = HexFloatPattern.VALUE.matcher(s);
+            boolean validInput = m.matches();
+            if (!validInput) {
+                // Input does not match pattern
+                throw new NumberFormatException("For input string: \"" + s + "\"");
+            } else { // validInput
+                //
+                // We must isolate the sign, significand, and exponent
+                // fields.  The sign value is straightforward.  Since
+                // floating-point numbers are stored with a normalized
+                // representation, the significand and exponent are
+                // interrelated.
+                //
+                // After extracting the sign, we normalized the
+                // significand as a hexadecimal value, calculating an
+                // exponent adjust for any shifts made during
+                // normalization.  If the significand is zero, the
+                // exponent doesn't need to be examined since the output
+                // will be zero.
+                //
+                // Next the exponent in the input string is extracted.
+                // Afterwards, the significand is normalized as a *binary*
+                // value and the input value's normalized exponent can be
+                // computed.  The significand bits are copied into a
+                // double significand; if the string has more logical bits
+                // than can fit in a double, the extra bits affect the
+                // round and sticky bits which are used to round the final
+                // value.
+                //
+                //  Extract significand sign
+                String group1 = m.group(1);
+                boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+                //  Extract Significand magnitude
+                //
+                // Based on the form of the significand, calculate how the
+                // binary exponent needs to be adjusted to create a
+                // normalized//hexadecimal* floating-point number; that
+                // is, a number where there is one nonzero hex digit to
+                // the left of the (hexa)decimal point.  Since we are
+                // adjusting a binary, not hexadecimal exponent, the
+                // exponent is adjusted by a multiple of 4.
+                //
+                // There are a number of significand scenarios to consider;
+                // letters are used in indicate nonzero digits:
+                //
+                // 1. 000xxxx       =>      x.xxx   normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 3. .000yyy  =>   y.yy    normalized
+                //    decrease exponent by (number of zeros + 1)*4
+                //
+                // 4. 000.00000yyy => y.yy normalized
+                //    decrease exponent by (number of zeros to right of point + 1)*4
+                //
+                // If the significand is exactly zero, return a properly
+                // signed zero.
+                //
+
+                String significandString = null;
+                int signifLength = 0;
+                int exponentAdjust = 0;
+                {
+                    int leftDigits = 0; // number of meaningful digits to
+                    // left of "decimal" point
+                    // (leading zeros stripped)
+                    int rightDigits = 0; // number of digits to right of
+                    // "decimal" point; leading zeros
+                    // must always be accounted for
+                    //
+                    // The significand is made up of either
+                    //
+                    // 1. group 4 entirely (integer portion only)
+                    //
+                    // OR
+                    //
+                    // 2. the fractional portion from group 7 plus any
+                    // (optional) integer portions from group 6.
+                    //
+                    String group4;
+                    if ((group4 = m.group(4)) != null) {  // Integer-only significand
+                        // Leading zeros never matter on the integer portion
+                        significandString = stripLeadingZeros(group4);
+                        leftDigits = significandString.length();
+                    } else {
+                        // Group 6 is the optional integer; leading zeros
+                        // never matter on the integer portion
+                        String group6 = stripLeadingZeros(m.group(6));
+                        leftDigits = group6.length();
+
+                        // fraction
+                        String group7 = m.group(7);
+                        rightDigits = group7.length();
+
+                        // Turn "integer.fraction" into "integer"+"fraction"
+                        significandString =
+                                ((group6 == null) ? "" : group6) + // is the null
+                                        // check necessary?
+                                        group7;
+                    }
+
+                    significandString = stripLeadingZeros(significandString);
+                    signifLength = significandString.length();
+
+                    //
+                    // Adjust exponent as described above
+                    //
+                    if (leftDigits >= 1) {  // Cases 1 and 2
+                        exponentAdjust = 4 * (leftDigits - 1);
+                    } else {                // Cases 3 and 4
+                        exponentAdjust = -4 * (rightDigits - signifLength + 1);
+                    }
+
+                    // If the significand is zero, the exponent doesn't
+                    // matter; return a properly signed zero.
+
+                    if (signifLength == 0) { // Only zeros in input
+                        return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                    }
+                }
+
+                //  Extract Exponent
+                //
+                // Use an int to read in the exponent value; this should
+                // provide more than sufficient range for non-contrived
+                // inputs.  If reading the exponent in as an int does
+                // overflow, examine the sign of the exponent and
+                // significand to determine what to do.
+                //
+                String group8 = m.group(8);
+                boolean positiveExponent = (group8 == null) || group8.equals("+");
+                long unsignedRawExponent;
+                try {
+                    unsignedRawExponent = Integer.parseInt(m.group(9));
+                }
+                catch (NumberFormatException e) {
+                    // At this point, we know the exponent is
+                    // syntactically well-formed as a sequence of
+                    // digits.  Therefore, if an NumberFormatException
+                    // is thrown, it must be due to overflowing int's
+                    // range.  Also, at this point, we have already
+                    // checked for a zero significand.  Thus the signs
+                    // of the exponent and significand determine the
+                    // final result:
+                    //
+                    //                      significand
+                    //                      +               -
+                    // exponent     +       +infinity       -infinity
+                    //              -       +0.0            -0.0
+                    return isNegative ?
+                              (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+                            : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+                }
+
+                long rawExponent =
+                        (positiveExponent ? 1L : -1L) * // exponent sign
+                                unsignedRawExponent;            // exponent magnitude
+
+                // Calculate partially adjusted exponent
+                long exponent = rawExponent + exponentAdjust;
+
+                // Starting copying non-zero bits into proper position in
+                // a long; copy explicit bit too; this will be masked
+                // later for normal values.
+
+                boolean round = false;
+                boolean sticky = false;
+                int nextShift = 0;
+                long significand = 0L;
+                // First iteration is different, since we only copy
+                // from the leading significand bit; one more exponent
+                // adjust will be needed...
+
+                // IMPORTANT: make leadingDigit a long to avoid
+                // surprising shift semantics!
+                long leadingDigit = getHexDigit(significandString, 0);
+
+                //
+                // Left shift the leading digit (53 - (bit position of
+                // leading 1 in digit)); this sets the top bit of the
+                // significand to 1.  The nextShift value is adjusted
+                // to take into account the number of bit positions of
+                // the leadingDigit actually used.  Finally, the
+                // exponent is adjusted to normalize the significand
+                // as a binary value, not just a hex value.
+                //
+                if (leadingDigit == 1) {
+                    significand |= leadingDigit << 52;
+                    nextShift = 52 - 4;
+                    // exponent += 0
+                } else if (leadingDigit <= 3) { // [2, 3]
+                    significand |= leadingDigit << 51;
+                    nextShift = 52 - 5;
+                    exponent += 1;
+                } else if (leadingDigit <= 7) { // [4, 7]
+                    significand |= leadingDigit << 50;
+                    nextShift = 52 - 6;
+                    exponent += 2;
+                } else if (leadingDigit <= 15) { // [8, f]
+                    significand |= leadingDigit << 49;
+                    nextShift = 52 - 7;
+                    exponent += 3;
+                } else {
+                    throw new AssertionError("Result from digit conversion too large!");
+                }
+                // The preceding if-else could be replaced by a single
+                // code block based on the high-order bit set in
+                // leadingDigit.  Given leadingOnePosition,
+
+                // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+                // nextShift = 52 - (3 + leadingOnePosition);
+                // exponent += (leadingOnePosition-1);
+
+                //
+                // Now the exponent variable is equal to the normalized
+                // binary exponent.  Code below will make representation
+                // adjustments if the exponent is incremented after
+                // rounding (includes overflows to infinity) or if the
+                // result is subnormal.
+                //
+
+                // Copy digit into significand until the significand can't
+                // hold another full hex digit or there are no more input
+                // hex digits.
+                int i = 0;
+                for (i = 1;
+                     i < signifLength && nextShift >= 0;
+                     i++) {
+                    long currentDigit = getHexDigit(significandString, i);
+                    significand |= (currentDigit << nextShift);
+                    nextShift -= 4;
+                }
+
+                // After the above loop, the bulk of the string is copied.
+                // Now, we must copy any partial hex digits into the
+                // significand AND compute the round bit and start computing
+                // sticky bit.
+
+                if (i < signifLength) { // at least one hex input digit exists
+                    long currentDigit = getHexDigit(significandString, i);
+
+                    // from nextShift, figure out how many bits need
+                    // to be copied, if any
+                    switch (nextShift) { // must be negative
+                        case -1:
+                            // three bits need to be copied in; can
+                            // set round bit
+                            significand |= ((currentDigit & 0xEL) >> 1);
+                            round = (currentDigit & 0x1L) != 0L;
+                            break;
+
+                        case -2:
+                            // two bits need to be copied in; can
+                            // set round and start sticky
+                            significand |= ((currentDigit & 0xCL) >> 2);
+                            round = (currentDigit & 0x2L) != 0L;
+                            sticky = (currentDigit & 0x1L) != 0;
+                            break;
+
+                        case -3:
+                            // one bit needs to be copied in
+                            significand |= ((currentDigit & 0x8L) >> 3);
+                            // Now set round and start sticky, if possible
+                            round = (currentDigit & 0x4L) != 0L;
+                            sticky = (currentDigit & 0x3L) != 0;
+                            break;
+
+                        case -4:
+                            // all bits copied into significand; set
+                            // round and start sticky
+                            round = ((currentDigit & 0x8L) != 0);  // is top bit set?
+                            // nonzeros in three low order bits?
+                            sticky = (currentDigit & 0x7L) != 0;
+                            break;
+
+                        default:
+                            throw new AssertionError("Unexpected shift distance remainder.");
+                            // break;
+                    }
+
+                    // Round is set; sticky might be set.
+
+                    // For the sticky bit, it suffices to check the
+                    // current digit and test for any nonzero digits in
+                    // the remaining unprocessed input.
+                    i++;
+                    while (i < signifLength && !sticky) {
+                        currentDigit = getHexDigit(significandString, i);
+                        sticky = sticky || (currentDigit != 0);
+                        i++;
+                    }
+
+                }
+                // else all of string was seen, round and sticky are
+                // correct as false.
+
+                // Float calculations
+                int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+                if (exponent >= FloatConsts.MIN_EXPONENT) {
+                    if (exponent > FloatConsts.MAX_EXPONENT) {
+                        // Float.POSITIVE_INFINITY
+                        floatBits |= FloatConsts.EXP_BIT_MASK;
+                    } else {
+                        int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+                    }
+                } else {
+                    if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+                        // 0
+                    } else {
+                        // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+                        int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+                        assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+                        assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= iValue >> 1;
+                    }
+                }
+                float fValue = Float.intBitsToFloat(floatBits);
+
+                // Check for overflow and update exponent accordingly.
+                if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
+                    // overflow to properly signed infinity
+                    return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                } else {  // Finite return value
+                    if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+                            exponent >= DoubleConsts.MIN_EXPONENT) {
+
+                        // The result returned in this block cannot be a
+                        // zero or subnormal; however after the
+                        // significand is adjusted from rounding, we could
+                        // still overflow in infinity.
+
+                        // AND exponent bits into significand; if the
+                        // significand is incremented and overflows from
+                        // rounding, this combination will update the
+                        // exponent correctly, even in the case of
+                        // Double.MAX_VALUE overflowing to infinity.
+
+                        significand = ((( exponent +
+                                (long) DoubleConsts.EXP_BIAS) <<
+                                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                & DoubleConsts.EXP_BIT_MASK) |
+                                (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+                    } else {  // Subnormal or zero
+                        // (exponent < DoubleConsts.MIN_EXPONENT)
+
+                        if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+                            // No way to round back to nonzero value
+                            // regardless of significand if the exponent is
+                            // less than -1075.
+                            return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                        } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+                            //
+                            // Find bit position to round to; recompute
+                            // round and sticky bits, and shift
+                            // significand right appropriately.
+                            //
+
+                            sticky = sticky || round;
+                            round = false;
+
+                            // Number of bits of significand to preserve is
+                            // exponent - abs_min_exp +1
+                            // check:
+                            // -1075 +1074 + 1 = 0
+                            // -1023 +1074 + 1 = 52
+
+                            int bitsDiscarded = 53 -
+                                    ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+                            assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+                            // What to do here:
+                            // First, isolate the new round bit
+                            round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+                            if (bitsDiscarded > 1) {
+                                // create mask to update sticky bits; low
+                                // order bitsDiscarded bits should be 1
+                                long mask = ~((~0L) << (bitsDiscarded - 1));
+                                sticky = sticky || ((significand & mask) != 0L);
+                            }
+
+                            // Now, discard the bits
+                            significand = significand >> bitsDiscarded;
+
+                            significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+                                    (long) DoubleConsts.EXP_BIAS) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                    & DoubleConsts.EXP_BIT_MASK) |
+                                    (DoubleConsts.SIGNIF_BIT_MASK & significand);
+                        }
+                    }
+
+                    // The significand variable now contains the currently
+                    // appropriate exponent bits too.
+
+                    //
+                    // Determine if significand should be incremented;
+                    // making this determination depends on the least
+                    // significant bit and the round and sticky bits.
+                    //
+                    // Round to nearest even rounding table, adapted from
+                    // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+                    // The digit to the left of the "decimal" point is the
+                    // least significant bit, the digits to the right of
+                    // the point are the round and sticky bits
+                    //
+                    // Number       Round(x)
+                    // x0.00        x0.
+                    // x0.01        x0.
+                    // x0.10        x0.
+                    // x0.11        x1. = x0. +1
+                    // x1.00        x1.
+                    // x1.01        x1.
+                    // x1.10        x1. + 1
+                    // x1.11        x1. + 1
+                    //
+                    boolean leastZero = ((significand & 1L) == 0L);
+                    if ((leastZero && round && sticky) ||
+                            ((!leastZero) && round)) {
+                        significand++;
+                    }
+
+                    double value = isNegative ?
+                            Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+                            Double.longBitsToDouble(significand );
+
+                    return new PreparedASCIIToBinaryBuffer(value, fValue);
+                }
+            }
+    }
+
+    /**
+     * Returns <code>s</code> with any leading zeros removed.
+     */
+    static String stripLeadingZeros(String s) {
+//        return  s.replaceFirst("^0+", "");
+        if(!s.isEmpty() && s.charAt(0)=='0') {
+            for(int i=1; i<s.length(); i++) {
+                if(s.charAt(i)!='0') {
+                    return s.substring(i);
+                }
+            }
+            return "";
+        }
+        return s;
+    }
+
+    /**
+     * Extracts a hexadecimal digit from position <code>position</code>
+     * of string <code>s</code>.
+     */
+    static int getHexDigit(String s, int position) {
+        int value = Character.digit(s.charAt(position), 16);
+        if (value <= -1 || value >= 16) {
+            throw new AssertionError("Unexpected failure of digit conversion of " +
+                                     s.charAt(position));
+        }
+        return value;
+    }
+}
diff --git a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java b/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
old mode 100755
new mode 100644
index 0b6dd85..fc53920
--- a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
+++ b/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -25,961 +25,80 @@
 
 package sun.misc;
 
-import sun.misc.FpUtils;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import java.util.regex.*;
+import java.util.Arrays;
 
 public class FormattedFloatingDecimal{
-    boolean     isExceptional;
-    boolean     isNegative;
-    int         decExponent;  // value set at construction, then immutable
-    int         decExponentRounded;
-    char        digits[];
-    int         nDigits;
-    int         bigIntExp;
-    int         bigIntNBits;
-    boolean     mustSetRoundDir = false;
-    boolean     fromHex = false;
-    int         roundDir = 0; // set by doubleValue
-    int         precision;    // number of digits to the right of decimal
 
     public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
 
-    private Form form;
 
-    private     FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form )
-    {
-        isNegative = negSign;
-        isExceptional = e;
-        this.decExponent = decExponent;
-        this.digits = digits;
-        this.nDigits = n;
-        this.precision = precision;
-        this.form = form;
+    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+        FloatingDecimal.BinaryToASCIIConverter fdConverter =
+                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+        return new FormattedFloatingDecimal(precision,form, fdConverter);
     }
 
-    /*
-     * Constants of the implementation
-     * Most are IEEE-754 related.
-     * (There are more really boring constants at the end.)
-     */
-    static final long   signMask = 0x8000000000000000L;
-    static final long   expMask  = 0x7ff0000000000000L;
-    static final long   fractMask= ~(signMask|expMask);
-    static final int    expShift = 52;
-    static final int    expBias  = 1023;
-    static final long   fractHOB = ( 1L<<expShift ); // assumed High-Order bit
-    static final long   expOne   = ((long)expBias)<<expShift; // exponent of 1.0
-    static final int    maxSmallBinExp = 62;
-    static final int    minSmallBinExp = -( 63 / 3 );
-    static final int    maxDecimalDigits = 15;
-    static final int    maxDecimalExponent = 308;
-    static final int    minDecimalExponent = -324;
-    static final int    bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
+    private int decExponentRounded;
+    private char[] mantissa;
+    private char[] exponent;
 
-    static final long   highbyte = 0xff00000000000000L;
-    static final long   highbit  = 0x8000000000000000L;
-    static final long   lowbytes = ~highbyte;
-
-    static final int    singleSignMask =    0x80000000;
-    static final int    singleExpMask  =    0x7f800000;
-    static final int    singleFractMask =   ~(singleSignMask|singleExpMask);
-    static final int    singleExpShift  =   23;
-    static final int    singleFractHOB  =   1<<singleExpShift;
-    static final int    singleExpBias   =   127;
-    static final int    singleMaxDecimalDigits = 7;
-    static final int    singleMaxDecimalExponent = 38;
-    static final int    singleMinDecimalExponent = -45;
-
-    static final int    intDecimalDigits = 9;
-
-
-    /*
-     * count number of bits from high-order 1 bit to low-order 1 bit,
-     * inclusive.
-     */
-    private static int
-    countBits( long v ){
-        //
-        // the strategy is to shift until we get a non-zero sign bit
-        // then shift until we have no bits left, counting the difference.
-        // we do byte shifting as a hack. Hope it helps.
-        //
-        if ( v == 0L ) return 0;
-
-        while ( ( v & highbyte ) == 0L ){
-            v <<= 8;
-        }
-        while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
-            v <<= 1;
-        }
-
-        int n = 0;
-        while (( v & lowbytes ) != 0L ){
-            v <<= 8;
-            n += 8;
-        }
-        while ( v != 0L ){
-            v <<= 1;
-            n += 1;
-        }
-        return n;
-    }
-
-    /*
-     * Keep big powers of 5 handy for future reference.
-     */
-    private static FDBigInt b5p[];
-
-    private static synchronized FDBigInt
-    big5pow( int p ){
-        assert p >= 0 : p; // negative power of 5
-        if ( b5p == null ){
-            b5p = new FDBigInt[ p+1 ];
-        }else if (b5p.length <= p ){
-            FDBigInt t[] = new FDBigInt[ p+1 ];
-            System.arraycopy( b5p, 0, t, 0, b5p.length );
-            b5p = t;
-        }
-        if ( b5p[p] != null )
-            return b5p[p];
-        else if ( p < small5pow.length )
-            return b5p[p] = new FDBigInt( small5pow[p] );
-        else if ( p < long5pow.length )
-            return b5p[p] = new FDBigInt( long5pow[p] );
-        else {
-            // construct the value.
-            // recursively.
-            int q, r;
-            // in order to compute 5^p,
-            // compute its square root, 5^(p/2) and square.
-            // or, let q = p / 2, r = p -q, then
-            // 5^p = 5^(q+r) = 5^q * 5^r
-            q = p >> 1;
-            r = p - q;
-            FDBigInt bigq =  b5p[q];
-            if ( bigq == null )
-                bigq = big5pow ( q );
-            if ( r < small5pow.length ){
-                return (b5p[p] = bigq.mult( small5pow[r] ) );
-            }else{
-                FDBigInt bigr = b5p[ r ];
-                if ( bigr == null )
-                    bigr = big5pow( r );
-                return (b5p[p] = bigq.mult( bigr ) );
-            }
-        }
-    }
-
-    //
-    // a common operation
-    //
-    private static FDBigInt
-    multPow52( FDBigInt v, int p5, int p2 ){
-        if ( p5 != 0 ){
-            if ( p5 < small5pow.length ){
-                v = v.mult( small5pow[p5] );
-            } else {
-                v = v.mult( big5pow( p5 ) );
-            }
-        }
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
-        }
-        return v;
-    }
-
-    //
-    // another common operation
-    //
-    private static FDBigInt
-    constructPow52( int p5, int p2 ){
-        FDBigInt v = new FDBigInt( big5pow( p5 ) );
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
-        }
-        return v;
-    }
-
-    /*
-     * Make a floating double into a FDBigInt.
-     * This could also be structured as a FDBigInt
-     * constructor, but we'd have to build a lot of knowledge
-     * about floating-point representation into it, and we don't want to.
-     *
-     * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-     * bigIntExp and bigIntNBits
-     *
-     */
-    private FDBigInt
-    doubleToBigInt( double dval ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        lbits &= fractMask;
-        if ( binexp > 0 ){
-            lbits |= fractHOB;
-        } else {
-            assert lbits != 0L : lbits; // doubleToBigInt(0.0)
-            binexp +=1;
-            while ( (lbits & fractHOB ) == 0L){
-                lbits <<= 1;
-                binexp -= 1;
-            }
-        }
-        binexp -= expBias;
-        int nbits = countBits( lbits );
-        /*
-         * We now know where the high-order 1 bit is,
-         * and we know how many there are.
-         */
-        int lowOrderZeros = expShift+1-nbits;
-        lbits >>>= lowOrderZeros;
-
-        bigIntExp = binexp+1-nbits;
-        bigIntNBits = nbits;
-        return new FDBigInt( lbits );
-    }
-
-    /*
-     * Compute a number that is the ULP of the given value,
-     * for purposes of addition/subtraction. Generally easy.
-     * More difficult if subtracting and the argument
-     * is a normalized a power of 2, as the ULP changes at these points.
-     */
-    private static double ulp( double dval, boolean subtracting ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        double ulpval;
-        if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
-            // for subtraction from normalized, powers of 2,
-            // use next-smaller exponent
-            binexp -= 1;
-        }
-        if ( binexp > expShift ){
-            ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
-        } else if ( binexp == 0 ){
-            ulpval = Double.MIN_VALUE;
-        } else {
-            ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
-        }
-        if ( subtracting ) ulpval = - ulpval;
-
-        return ulpval;
-    }
-
-    /*
-     * Round a double to a float.
-     * In addition to the fraction bits of the double,
-     * look at the class instance variable roundDir,
-     * which should help us avoid double-rounding error.
-     * roundDir was set in hardValueOf if the estimate was
-     * close enough, but not exact. It tells us which direction
-     * of rounding is preferred.
-     */
-    float
-    stickyRound( double dval ){
-        long lbits = Double.doubleToLongBits( dval );
-        long binexp = lbits & expMask;
-        if ( binexp == 0L || binexp == expMask ){
-            // what we have here is special.
-            // don't worry, the right thing will happen.
-            return (float) dval;
-        }
-        lbits += (long)roundDir; // hack-o-matic.
-        return (float)Double.longBitsToDouble( lbits );
-    }
-
-
-    /*
-     * This is the easy subcase --
-     * all the significant bits, after scaling, are held in lvalue.
-     * negSign and decExponent tell us what processing and scaling
-     * has already been done. Exceptional cases have already been
-     * stripped out.
-     * In particular:
-     * lvalue is a finite number (not Inf, nor NaN)
-     * lvalue > 0L (not zero, nor negative).
-     *
-     * The only reason that we develop the digits here, rather than
-     * calling on Long.toString() is that we can do it a little faster,
-     * and besides want to treat trailing 0s specially. If Long.toString
-     * changes, we should re-evaluate this strategy!
-     */
-    private void
-    developLongDigits( int decExponent, long lvalue, long insignificant ){
-        char digits[];
-        int  ndigits;
-        int  digitno;
-        int  c;
-        //
-        // Discard non-significant low-order bits, while rounding,
-        // up to insignificant value.
-        int i;
-        for ( i = 0; insignificant >= 10L; i++ )
-            insignificant /= 10L;
-        if ( i != 0 ){
-            long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
-            long residue = lvalue % pow10;
-            lvalue /= pow10;
-            decExponent += i;
-            if ( residue >= (pow10>>1) ){
-                // round up based on the low-order bits we're discarding
-                lvalue++;
-            }
-        }
-        if ( lvalue <= Integer.MAX_VALUE ){
-            assert lvalue > 0L : lvalue; // lvalue <= 0
-            // even easier subcase!
-            // can do int arithmetic rather than long!
-            int  ivalue = (int)lvalue;
-            ndigits = 10;
-            digits = (char[])(perThreadBuffer.get());
-            digitno = ndigits-1;
-            c = ivalue%10;
-            ivalue /= 10;
-            while ( c == 0 ){
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            while ( ivalue != 0){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        } else {
-            // same algorithm as above (same bugs, too )
-            // but using long arithmetic.
-            ndigits = 20;
-            digits = (char[])(perThreadBuffer.get());
-            digitno = ndigits-1;
-            c = (int)(lvalue%10L);
-            lvalue /= 10L;
-            while ( c == 0 ){
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10L;
-            }
-            while ( lvalue != 0L ){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        }
-        char result [];
-        ndigits -= digitno;
-        result = new char[ ndigits ];
-        System.arraycopy( digits, digitno, result, 0, ndigits );
-        this.digits = result;
-        this.decExponent = decExponent+1;
-        this.nDigits = ndigits;
-    }
-
-    //
-    // add one to the least significant digit.
-    // in the unlikely event there is a carry out,
-    // deal with it.
-    // assert that this will only happen where there
-    // is only one digit, e.g. (float)1e-44 seems to do it.
-    //
-    private void
-    roundup(){
-        int i;
-        int q = digits[ i = (nDigits-1)];
-        if ( q == '9' ){
-            while ( q == '9' && i > 0 ){
-                digits[i] = '0';
-                q = digits[--i];
-            }
-            if ( q == '9' ){
-                // carryout! High-order 1, rest 0s, larger exp.
-                decExponent += 1;
-                digits[0] = '1';
-                return;
-            }
-            // else fall through.
-        }
-        digits[i] = (char)(q+1);
-    }
-
-    // Given the desired number of digits predict the result's exponent.
-    private int checkExponent(int length) {
-        if (length >= nDigits || length < 0)
-            return decExponent;
-
-        for (int i = 0; i < length; i++)
-            if (digits[i] != '9')
-                // a '9' anywhere in digits will absorb the round
-                return decExponent;
-        return decExponent + (digits[length] >= '5' ? 1 : 0);
-    }
-
-    // Unlike roundup(), this method does not modify digits.  It also
-    // rounds at a particular precision.
-    private char [] applyPrecision(int length) {
-        char [] result = new char[nDigits];
-        for (int i = 0; i < result.length; i++) result[i] = '0';
-
-        if (length >= nDigits || length < 0) {
-            // no rounding necessary
-            System.arraycopy(digits, 0, result, 0, nDigits);
-            return result;
-        }
-        if (length == 0) {
-            // only one digit (0 or 1) is returned because the precision
-            // excludes all significant digits
-            if (digits[0] >= '5') {
-                result[0] = '1';
-            }
-            return result;
-        }
-
-        int i = length;
-        int q = digits[i];
-        if (q >= '5' && i > 0) {
-            q = digits[--i];
-            if ( q == '9' ) {
-                while ( q == '9' && i > 0 ){
-                    q = digits[--i];
+    private static final ThreadLocal<Object> threadLocalCharBuffer =
+            new ThreadLocal<Object>() {
+                @Override
+                protected Object initialValue() {
+                    return new char[20];
                 }
-                if ( q == '9' ){
-                    // carryout! High-order 1, rest 0s, larger exp.
-                    result[0] = '1';
-                    return result;
-                }
-            }
-            result[i] = (char)(q + 1);
-        }
-        while (--i >= 0) {
-            result[i] = digits[i];
-        }
-        return result;
+            };
+
+    private static char[] getBuffer(){
+        return (char[]) threadLocalCharBuffer.get();
     }
 
-    /*
-     * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
-     */
-    public FormattedFloatingDecimal( double d )
-    {
-        this(d, Integer.MAX_VALUE, Form.COMPATIBLE);
-    }
-
-    public FormattedFloatingDecimal( double d, int precision, Form form )
-    {
-        long    dBits = Double.doubleToLongBits( d );
-        long    fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        this.precision = precision;
-        this.form      = form;
-
-        // discover and delete sign
-        if ( (dBits&signMask) != 0 ){
-            isNegative = true;
-            dBits ^= signMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (int)( (dBits&expMask) >> expShift );
-        fractBits = dBits&fractMask;
-        if ( binExp == (int)(expMask>>expShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
+    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+        if (fdConverter.isExceptional()) {
+            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+            this.exponent = null;
             return;
         }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0L ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return;
-            }
-            while ( (fractBits&fractHOB) == 0L ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = expShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
-        } else {
-            fractBits |= fractHOB;
-            nSignificantBits = expShift+1;
-        }
-        binExp -= expBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, fractBits, nSignificantBits );
-    }
-
-    /*
-     * SECOND IMPORTANT CONSTRUCTOR: SINGLE
-     */
-    public FormattedFloatingDecimal( float f )
-    {
-        this(f, Integer.MAX_VALUE, Form.COMPATIBLE);
-    }
-    public FormattedFloatingDecimal( float f, int precision, Form form )
-    {
-        int     fBits = Float.floatToIntBits( f );
-        int     fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        this.precision = precision;
-        this.form      = form;
-
-        // discover and delete sign
-        if ( (fBits&singleSignMask) != 0 ){
-            isNegative = true;
-            fBits ^= singleSignMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (int)( (fBits&singleExpMask) >> singleExpShift );
-        fractBits = fBits&singleFractMask;
-        if ( binExp == (int)(singleExpMask>>singleExpShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
-            return;
-        }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0 ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return;
-            }
-            while ( (fractBits&singleFractHOB) == 0 ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = singleExpShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
-        } else {
-            fractBits |= singleFractHOB;
-            nSignificantBits = singleExpShift+1;
-        }
-        binExp -= singleExpBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
-    }
-
-    private void
-    dtoa( int binExp, long fractBits, int nSignificantBits )
-    {
-        int     nFractBits; // number of significant bits of fractBits;
-        int     nTinyBits;  // number of these to the right of the point.
-        int     decExp;
-
-        // Examine number. Determine if it is an easy case,
-        // which we can do pretty trivially using float/long conversion,
-        // or whether we must do real work.
-        nFractBits = countBits( fractBits );
-        nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
-        if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
-            // Look more closely at the number to decide if,
-            // with scaling by 10^nTinyBits, the result will fit in
-            // a long.
-            if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
-                /*
-                 * We can do this:
-                 * take the fraction bits, which are normalized.
-                 * (a) nTinyBits == 0: Shift left or right appropriately
-                 *     to align the binary point at the extreme right, i.e.
-                 *     where a long int point is expected to be. The integer
-                 *     result is easily converted to a string.
-                 * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
-                 *     which effectively converts to long and scales by
-                 *     2^nTinyBits. Then multiply by 5^nTinyBits to
-                 *     complete the scaling. We know this won't overflow
-                 *     because we just counted the number of bits necessary
-                 *     in the result. The integer you get from this can
-                 *     then be converted to a string pretty easily.
-                 */
-                long halfULP;
-                if ( nTinyBits == 0 ) {
-                    if ( binExp > nSignificantBits ){
-                        halfULP = 1L << ( binExp-nSignificantBits-1);
-                    } else {
-                        halfULP = 0L;
-                    }
-                    if ( binExp >= expShift ){
-                        fractBits <<= (binExp-expShift);
-                    } else {
-                        fractBits >>>= (expShift-binExp) ;
-                    }
-                    developLongDigits( 0, fractBits, halfULP );
-                    return;
-                }
-                /*
-                 * The following causes excess digits to be printed
-                 * out in the single-float case. Our manipulation of
-                 * halfULP here is apparently not correct. If we
-                 * better understand how this works, perhaps we can
-                 * use this special case again. But for the time being,
-                 * we do not.
-                 * else {
-                 *     fractBits >>>= expShift+1-nFractBits;
-                 *     fractBits *= long5pow[ nTinyBits ];
-                 *     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
-                 *     developLongDigits( -nTinyBits, fractBits, halfULP );
-                 *     return;
-                 * }
-                 */
-            }
-        }
-        /*
-         * This is the hard case. We are going to compute large positive
-         * integers B and S and integer decExp, s.t.
-         *      d = ( B / S ) * 10^decExp
-         *      1 <= B / S < 10
-         * Obvious choices are:
-         *      decExp = floor( log10(d) )
-         *      B      = d * 2^nTinyBits * 10^max( 0, -decExp )
-         *      S      = 10^max( 0, decExp) * 2^nTinyBits
-         * (noting that nTinyBits has already been forced to non-negative)
-         * I am also going to compute a large positive integer
-         *      M      = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
-         * i.e. M is (1/2) of the ULP of d, scaled like B.
-         * When we iterate through dividing B/S and picking off the
-         * quotient bits, we will know when to stop when the remainder
-         * is <= M.
-         *
-         * We keep track of powers of 2 and powers of 5.
-         */
-
-        /*
-         * Estimate decimal exponent. (If it is small-ish,
-         * we could double-check.)
-         *
-         * First, scale the mantissa bits such that 1 <= d2 < 2.
-         * We are then going to estimate
-         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
-         * and so we can estimate
-         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
-         * take the floor and call it decExp.
-         * FIXME -- use more precise constants here. It costs no more.
-         */
-        double d2 = Double.longBitsToDouble(
-            expOne | ( fractBits &~ fractHOB ) );
-        decExp = (int)Math.floor(
-            (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
-        int B2, B5; // powers of 2 and powers of 5, respectively, in B
-        int S2, S5; // powers of 2 and powers of 5, respectively, in S
-        int M2, M5; // powers of 2 and powers of 5, respectively, in M
-        int Bbits; // binary digits needed to represent B, approx.
-        int tenSbits; // binary digits needed to represent 10*S, approx.
-        FDBigInt Sval, Bval, Mval;
-
-        B5 = Math.max( 0, -decExp );
-        B2 = B5 + nTinyBits + binExp;
-
-        S5 = Math.max( 0, decExp );
-        S2 = S5 + nTinyBits;
-
-        M5 = B5;
-        M2 = B2 - nSignificantBits;
-
-        /*
-         * the long integer fractBits contains the (nFractBits) interesting
-         * bits from the mantissa of d ( hidden 1 added if necessary) followed
-         * by (expShift+1-nFractBits) zeros. In the interest of compactness,
-         * I will shift out those zeros before turning fractBits into a
-         * FDBigInt. The resulting whole number will be
-         *      d * 2^(nFractBits-1-binExp).
-         */
-        fractBits >>>= (expShift+1-nFractBits);
-        B2 -= nFractBits-1;
-        int common2factor = Math.min( B2, S2 );
-        B2 -= common2factor;
-        S2 -= common2factor;
-        M2 -= common2factor;
-
-        /*
-         * HACK!! For exact powers of two, the next smallest number
-         * is only half as far away as we think (because the meaning of
-         * ULP changes at power-of-two bounds) for this reason, we
-         * hack M2. Hope this works.
-         */
-        if ( nFractBits == 1 )
-            M2 -= 1;
-
-        if ( M2 < 0 ){
-            // oops.
-            // since we cannot scale M down far enough,
-            // we must scale the other values up.
-            B2 -= M2;
-            S2 -= M2;
-            M2 =  0;
-        }
-        /*
-         * Construct, Scale, iterate.
-         * Some day, we'll write a stopping test that takes
-         * account of the assymetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        char digits[] = this.digits = new char[18];
-        int  ndigit = 0;
-        boolean low, high;
-        long lowDigitDifference;
-        int  q;
-
-        /*
-         * Detect the special cases where all the numbers we are about
-         * to compute will fit in int or long integers.
-         * In these cases, we will avoid doing FDBigInt arithmetic.
-         * We use the same algorithms, except that we "normalize"
-         * our FDBigInts before iterating. This is to make division easier,
-         * as it makes our fist guess (quotient of high-order words)
-         * more accurate!
-         *
-         * Some day, we'll write a stopping test that takes
-         * account of the assymetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
-        tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
-        if ( Bbits < 64 && tenSbits < 64){
-            if ( Bbits < 32 && tenSbits < 32){
-                // wa-hoo! They're all ints!
-                int b = ((int)fractBits * small5pow[B5] ) << B2;
-                int s = small5pow[S5] << S2;
-                int m = small5pow[M5] << M2;
-                int tens = s * 10;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = b / s;
-                b = 10 * ( b % s );
-                m *= 10;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
+        char[] digits = getBuffer();
+        int nDigits = fdConverter.getDigits(digits);
+        int decExp = fdConverter.getDecimalExponent();
+        int exp;
+        boolean isNegative = fdConverter.isNegative();
+        switch (form) {
+            case COMPATIBLE:
+                exp = decExp;
+                this.decExponentRounded = exp;
+                fillCompatible(precision, digits, nDigits, exp, isNegative);
+                break;
+            case DECIMAL_FLOAT:
+                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+                fillDecimal(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case SCIENTIFIC:
+                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+                fillScientific(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case GENERAL:
+                exp = applyPrecision(decExp, digits, nDigits, precision);
+                // adjust precision to be the number of digits to right of decimal
+                // the real exponent to be output is actually exp - 1, not exp
+                if (exp - 1 < -4 || exp - 1 >= precision) {
+                    // form = Form.SCIENTIFIC;
+                    precision--;
+                    fillScientific(precision, digits, nDigits, exp, isNegative);
                 } else {
-                    digits[ndigit++] = (char)('0' + q);
+                    // form = Form.DECIMAL_FLOAT;
+                    precision = precision - exp;
+                    fillDecimal(precision, digits, nDigits, exp, isNegative);
                 }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = b / s;
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q; // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                lowDigitDifference = (b<<1) - tens;
-            } else {
-                // still good! they're all longs!
-                long b = (fractBits * long5pow[B5] ) << B2;
-                long s = long5pow[S5] << S2;
-                long m = long5pow[M5] << M2;
-                long tens = s * 10L;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = (int) ( b / s );
-                b = 10L * ( b % s );
-                m *= 10L;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = (int) ( b / s );
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q;  // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                lowDigitDifference = (b<<1) - tens;
-            }
-        } else {
-            FDBigInt tenSval;
-            int  shiftBias;
-
-            /*
-             * We really must do FDBigInt arithmetic.
-             * Fist, construct our FDBigInt initial values.
-             */
-            Bval = multPow52( new FDBigInt( fractBits  ), B5, B2 );
-            Sval = constructPow52( S5, S2 );
-            Mval = constructPow52( M5, M2 );
-
-
-            // normalize so that division works better
-            Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
-            Mval.lshiftMe( shiftBias );
-            tenSval = Sval.mult( 10 );
-            /*
-             * Unroll the first iteration. If our decExp estimate
-             * was too high, our first quotient will be zero. In this
-             * case, we discard it and decrement decExp.
-             */
-            ndigit = 0;
-            q = Bval.quoRemIteration( Sval );
-            Mval = Mval.mult( 10 );
-            low  = (Bval.cmp( Mval ) < 0);
-            high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-            assert q < 10 : q; // excessively large digit
-            if ( (q == 0) && ! high ){
-                // oops. Usually ignore leading zero.
-                decExp--;
-            } else {
-                digits[ndigit++] = (char)('0' + q);
-            }
-            /*
-             * HACK! Java spec sez that we always have at least
-             * one digit after the . in either F- or E-form output.
-             * Thus we will need more than one digit if we're using
-             * E-form
-             */
-            if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                high = low = false;
-            }
-            while( ! low && ! high ){
-                q = Bval.quoRemIteration( Sval );
-                Mval = Mval.mult( 10 );
-                assert q < 10 : q;  // excessively large digit
-                low  = (Bval.cmp( Mval ) < 0);
-                high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-                digits[ndigit++] = (char)('0' + q);
-            }
-            if ( high && low ){
-                Bval.lshiftMe(1);
-                lowDigitDifference = Bval.cmp(tenSval);
-            } else
-                lowDigitDifference = 0L; // this here only for flow analysis!
+                this.decExponentRounded = exp;
+                break;
+            default:
+                assert false;
         }
-        this.decExponent = decExp+1;
-        this.digits = digits;
-        this.nDigits = ndigit;
-        /*
-         * Last digit gets rounded based on stopping condition.
-         */
-        if ( high ){
-            if ( low ){
-                if ( lowDigitDifference == 0L ){
-                    // it's a tie!
-                    // choose based on which digits we like.
-                    if ( (digits[nDigits-1]&1) != 0 ) roundup();
-                } else if ( lowDigitDifference > 0 ){
-                    roundup();
-                }
-            } else {
-                roundup();
-            }
-        }
-    }
-
-    public String
-    toString(){
-        // most brain-dead version
-        StringBuffer result = new StringBuffer( nDigits+8 );
-        if ( isNegative ){ result.append( '-' ); }
-        if ( isExceptional ){
-            result.append( digits, 0, nDigits );
-        } else {
-            result.append( "0.");
-            result.append( digits, 0, nDigits );
-            result.append('e');
-            result.append( decExponent );
-        }
-        return new String(result);
-    }
-
-    // returns the exponent before rounding
-    public int getExponent() {
-        return decExponent - 1;
     }
 
     // returns the exponent after rounding has been done by applyPrecision
@@ -987,781 +106,244 @@
         return decExponentRounded - 1;
     }
 
-    public int getChars(char[] result) {
-        assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
-        int i = 0;
-        if (isNegative) { result[0] = '-'; i = 1; }
-        if (isExceptional) {
-            System.arraycopy(digits, 0, result, i, nDigits);
-            i += nDigits;
-        } else {
-            char digits [] = this.digits;
-            int exp = decExponent;
-            switch (form) {
-            case COMPATIBLE:
-                break;
-            case DECIMAL_FLOAT:
-                exp = checkExponent(decExponent + precision);
-                digits = applyPrecision(decExponent + precision);
-                break;
-            case SCIENTIFIC:
-                exp = checkExponent(precision + 1);
-                digits = applyPrecision(precision + 1);
-                break;
-            case GENERAL:
-                exp = checkExponent(precision);
-                digits = applyPrecision(precision);
-                // adjust precision to be the number of digits to right of decimal
-                // the real exponent to be output is actually exp - 1, not exp
-                if (exp - 1 < -4 || exp - 1 >= precision) {
-                    form = Form.SCIENTIFIC;
-                    precision--;
-                } else {
-                    form = Form.DECIMAL_FLOAT;
-                    precision = precision - exp;
-                }
-                break;
-            default:
-                assert false;
-            }
-            decExponentRounded = exp;
+    public char[] getMantissa(){
+        return mantissa;
+    }
 
-            if (exp > 0
-                && ((form == Form.COMPATIBLE && (exp < 8))
-                    || (form == Form.DECIMAL_FLOAT)))
-            {
-                // print digits.digits.
-                int charLength = Math.min(nDigits, exp);
-                System.arraycopy(digits, 0, result, i, charLength);
-                i += charLength;
-                if (charLength < exp) {
-                    charLength = exp-charLength;
-                    for (int nz = 0; nz < charLength; nz++)
-                        result[i++] = '0';
-                    // Do not append ".0" for formatted floats since the user
-                    // may request that it be omitted. It is added as necessary
-                    // by the Formatter.
-                    if (form == Form.COMPATIBLE) {
-                        result[i++] = '.';
-                        result[i++] = '0';
-                    }
-                } else {
-                    // Do not append ".0" for formatted floats since the user
-                    // may request that it be omitted. It is added as necessary
-                    // by the Formatter.
-                    if (form == Form.COMPATIBLE) {
-                        result[i++] = '.';
-                        if (charLength < nDigits) {
-                            int t = Math.min(nDigits - charLength, precision);
-                            System.arraycopy(digits, charLength, result, i, t);
-                            i += t;
-                        } else {
-                            result[i++] = '0';
-                        }
-                    } else {
-                        int t = Math.min(nDigits - charLength, precision);
-                        if (t > 0) {
-                            result[i++] = '.';
-                            System.arraycopy(digits, charLength, result, i, t);
-                            i += t;
-                        }
-                    }
-                }
-            } else if (exp <= 0
-                       && ((form == Form.COMPATIBLE && exp > -3)
-                       || (form == Form.DECIMAL_FLOAT)))
-            {
-                // print 0.0* digits
-                result[i++] = '0';
-                if (exp != 0) {
-                    // write '0' s before the significant digits
-                    int t = Math.min(-exp, precision);
-                    if (t > 0) {
-                        result[i++] = '.';
-                        for (int nz = 0; nz < t; nz++)
-                            result[i++] = '0';
-                    }
-                }
-                int t = Math.min(digits.length, precision + exp);
-                if (t > 0) {
-                    if (i == 1)
-                        result[i++] = '.';
-                    // copy only when significant digits are within the precision
-                    System.arraycopy(digits, 0, result, i, t);
-                    i += t;
-                }
+    public char[] getExponent(){
+        return exponent;
+    }
+
+    /**
+     * Returns new decExp in case of overflow.
+     */
+    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+        if (prec >= nDigits || prec < 0) {
+            // no rounding necessary
+            return decExp;
+        }
+        if (prec == 0) {
+            // only one digit (0 or 1) is returned because the precision
+            // excludes all significant digits
+            if (digits[0] >= '5') {
+                digits[0] = '1';
+                Arrays.fill(digits, 1, nDigits, '0');
+                return decExp + 1;
             } else {
-                result[i++] = digits[0];
-                if (form == Form.COMPATIBLE) {
-                    result[i++] = '.';
-                    if (nDigits > 1) {
-                        System.arraycopy(digits, 1, result, i, nDigits-1);
-                        i += nDigits-1;
-                    } else {
-                        result[i++] = '0';
-                    }
-                    result[i++] = 'E';
-                } else {
-                    if (nDigits > 1) {
-                        int t = Math.min(nDigits -1, precision);
-                        if (t > 0) {
-                            result[i++] = '.';
-                            System.arraycopy(digits, 1, result, i, t);
-                            i += t;
-                        }
-                    }
-                    result[i++] = 'e';
-                }
-                int e;
-                if (exp <= 0) {
-                    result[i++] = '-';
-                    e = -exp+1;
-                } else {
-                    if (form != Form.COMPATIBLE)
-                        result[i++] = '+';
-                    e = exp-1;
-                }
-                // decExponent has 1, 2, or 3, digits
-                if (e <= 9) {
-                    if (form != Form.COMPATIBLE)
-                        result[i++] = '0';
-                    result[i++] = (char)(e+'0');
-                } else if (e <= 99) {
-                    result[i++] = (char)(e/10 +'0');
-                    result[i++] = (char)(e%10 + '0');
-                } else {
-                    result[i++] = (char)(e/100+'0');
-                    e %= 100;
-                    result[i++] = (char)(e/10+'0');
-                    result[i++] = (char)(e%10 + '0');
-                }
+                Arrays.fill(digits, 0, nDigits, '0');
+                return decExp;
             }
         }
-        return i;
+        int q = digits[prec];
+        if (q >= '5') {
+            int i = prec;
+            q = digits[--i];
+            if ( q == '9' ) {
+                while ( q == '9' && i > 0 ){
+                    q = digits[--i];
+                }
+                if ( q == '9' ){
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    digits[0] = '1';
+                    Arrays.fill(digits, 1, nDigits, '0');
+                    return decExp+1;
+                }
+            }
+            digits[i] = (char)(q + 1);
+            Arrays.fill(digits, i+1, nDigits, '0');
+        } else {
+            Arrays.fill(digits, prec, nDigits, '0');
+        }
+        return decExp;
     }
 
-    // Per-thread buffer for string/stringbuffer conversion
-    private static ThreadLocal perThreadBuffer = new ThreadLocal() {
-            protected synchronized Object initialValue() {
-                return new char[26];
-            }
-        };
-
-    /*
-     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a double.
-     *
-     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
-     * ROUNDING DIRECTION in case the result is really destined
-     * for a single-precision float.
+    /**
+     * Fills mantissa and exponent char arrays for compatible format.
      */
-
-    public strictfp double doubleValue(){
-        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );
-        long    lValue;
-        double  dValue;
-        double  rValue, tValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Double.NaN;
-            else
-                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
+    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0 && exp < 8) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                int extraZeros = exp - nDigits;
+                mantissa = create(isNegative, nDigits + extraZeros + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+                mantissa[startIndex + nDigits + extraZeros] = '.';
+                mantissa[startIndex + nDigits + extraZeros+1] = '0';
+            } else if (exp < nDigits) {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + 1 + t);
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                mantissa[startIndex + exp ] = '.';
+                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+            } else { // exp == digits.length
+                mantissa = create(isNegative, nDigits + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                mantissa[startIndex + nDigits ] = '.';
+                mantissa[startIndex + nDigits +1] = '0';
+            }
+        } else if (exp <= 0 && exp > -3) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+                }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
+            }
+        } else {
+            if (nDigits > 1) {
+                mantissa = create(isNegative, nDigits + 1);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
+            } else {
+                mantissa = create(isNegative, 3);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                mantissa[startIndex + 2] = '0';
+            }
+            int e, expStartIntex;
+            boolean isNegExp = (exp <= 0);
+            if (isNegExp) {
+                e = -exp + 1;
+                expStartIntex = 1;
+            } else {
+                e = exp - 1;
+                expStartIntex = 0;
+            }
+            // decExponent has 1, 2, or 3, digits
+            if (e <= 9) {
+                exponent = create(isNegExp,1);
+                exponent[expStartIntex] = (char) (e + '0');
+            } else if (e <= 99) {
+                exponent = create(isNegExp,2);
+                exponent[expStartIntex] = (char) (e / 10 + '0');
+                exponent[expStartIntex+1] = (char) (e % 10 + '0');
+            } else {
+                exponent = create(isNegExp,3);
+                exponent[expStartIntex] = (char) (e / 100 + '0');
+                e %= 100;
+                exponent[expStartIntex+1] = (char) (e / 10 + '0');
+                exponent[expStartIntex+2] = (char) (e % 10 + '0');
+            }
         }
-        else {
-            if (mustSetRoundDir) {
-                roundDir = 0;
-            }
-            /*
-             * convert the lead kDigits to a long integer.
-             */
-            // (special performance hack: start to do it using int)
-            int iValue = (int)digits[0]-(int)'0';
-            int iDigits = Math.min( kDigits, intDecimalDigits );
-            for ( int i=1; i < iDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            lValue = (long)iValue;
-            for ( int i=iDigits; i < kDigits; i++ ){
-                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-            }
-            dValue = (double)lValue;
-            int exp = decExponent-kDigits;
-            /*
-             * lValue now contains a long integer with the value of
-             * the first kDigits digits of the number.
-             * dValue contains the (double) of the same.
-             */
+    }
 
-            if ( nDigits <= maxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here
-                 */
-                if (exp == 0 || dValue == 0.0)
-                    return (isNegative)? -dValue : dValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= maxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        rValue = dValue * small10pow[exp];
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    int slop = maxDecimalDigits - kDigits;
-                    if ( exp <= maxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        dValue *= small10pow[slop];
-                        rValue = dValue * small10pow[exp-slop];
-
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp-slop];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -maxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        rValue = dValue / small10pow[-exp];
-                        tValue = rValue * small10pow[-exp];
-                        if ( mustSetRoundDir ){
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            }
-
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by approximating the right answer by,
-             * naively, scaling by powers of 10.
-             */
-            if ( exp > 0 ){
-                if ( decExponent > maxDecimalExponent+1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * Infinity. Cut to the chase.
-                     */
-                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue *= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= big10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could overflow.
-                     */
-                    double t = dValue * big10pow[j];
-                    if ( Double.isInfinite( t ) ){
-                        /*
-                         * It did overflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too large,
-                         * then use the maximum finite as our estimate
-                         * value. Else call the result infinity
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two larger than
-                         * Double.MAX_VALUE ).
-                         */
-                        t = dValue / 2.0;
-                        t *= big10pow[j];
-                        if ( Double.isInfinite( t ) ){
-                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                        }
-                        t = Double.MAX_VALUE;
-                    }
-                    dValue = t;
-                }
-            } else if ( exp < 0 ){
-                exp = -exp;
-                if ( decExponent < minDecimalExponent-1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * zero. Cut to the chase.
-                     */
-                    return (isNegative)? -0.0 : 0.0;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue /= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= tiny10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could underflow.
-                     */
-                    double t = dValue * tiny10pow[j];
-                    if ( t == 0.0 ){
-                        /*
-                         * It did underflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too small,
-                         * then use the minimum finite as our estimate
-                         * value. Else call the result 0.0
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two less than
-                         * Double.MIN_VALUE ).
-                         */
-                        t = dValue * 2.0;
-                        t *= tiny10pow[j];
-                        if ( t == 0.0 ){
-                            return (isNegative)? -0.0 : 0.0;
-                        }
-                        t = Double.MIN_VALUE;
-                    }
-                    dValue = t;
-                }
-            }
-
-            /*
-             * dValue is now approximately the result.
-             * The hard part is adjusting it, by comparison
-             * with FDBigInt arithmetic.
-             * Formulate the EXACT big-number result as
-             * bigD0 * 10^exp
-             */
-            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
-            exp   = decExponent - nDigits;
-
-            correctionLoop:
-            while(true){
-                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-                 * bigIntExp and bigIntNBits
-                 */
-                FDBigInt bigB = doubleToBigInt( dValue );
-
-                /*
-                 * Scale bigD, bigB appropriately for
-                 * big-integer operations.
-                 * Naively, we multipy by powers of ten
-                 * and powers of two. What we actually do
-                 * is keep track of the powers of 5 and
-                 * powers of 2 we would use, then factor out
-                 * common divisors before doing the work.
-                 */
-                int B2, B5; // powers of 2, 5 in bigB
-                int     D2, D5; // powers of 2, 5 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if ( exp >= 0 ){
-                    B2 = B5 = 0;
-                    D2 = D5 = exp;
-                } else {
-                    B2 = B5 = -exp;
-                    D2 = D5 = 0;
-                }
-                if ( bigIntExp >= 0 ){
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if ( bigIntExp+bigIntNBits <= -expBias+1 ){
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(expBias+expShift+1)
-                    hulpbias = bigIntExp+ expBias + expShift;
-                } else {
-                    hulpbias = expShift + 2 - bigIntNBits;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                bigB = multPow52( bigB, B5, B2 );
-                FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
-                //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
-                //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
-                //
-                FDBigInt diff;
-                int cmpResult;
-                boolean overvalue;
-                if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
-                        // candidate is a normalized exact power of 2 and
-                        // is too big. We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if ( Ulp2 < 0 ){
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff.lshiftMe( 1 );
-                        }
-                    }
-                } else if ( cmpResult < 0 ){
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.sub( bigB );
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising fequency
-                    break correctionLoop;
-                }
-                FDBigInt halfUlp = constructPow52( B5, Ulp2 );
-                if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
-                    // difference is small.
-                    // this is close enough
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else if ( cmpResult == 0 ){
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    dValue += 0.5*ulp( dValue, overvalue );
-                    // should check for bigIntNBits == 1 here??
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    dValue += ulp( dValue, overvalue );
-                    if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
-                        break correctionLoop; // oops. Fell off end of range.
-                    continue; // try again.
-                }
-
-            }
-            return (isNegative)? -dValue : dValue;
+    private static char[] create(boolean isNegative, int size) {
+        if(isNegative) {
+            char[] r = new char[size +1];
+            r[0] = '-';
+            return r;
+        } else {
+            return new char[size];
         }
     }
 
     /*
-     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a float.
-     * This is distinct from doubleValue() to avoid the extremely
-     * unlikely case of a double rounding error, wherein the converstion
-     * to double has one rounding error, and the conversion of that double
-     * to a float has another rounding error, IN THE WRONG DIRECTION,
-     * ( because of the preference to a zero low-order bit ).
+     * Fills mantissa char arrays for DECIMAL_FLOAT format.
+     * Exponent should be equal to null.
      */
-
-    public strictfp float floatValue(){
-        int     kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
-        int     iValue;
-        float   fValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Float.NaN;
-            else
-                return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
-        }
-        else {
-            /*
-             * convert the lead kDigits to an integer.
-             */
-            iValue = (int)digits[0]-(int)'0';
-            for ( int i=1; i < kDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            fValue = (float)iValue;
-            int exp = decExponent-kDigits;
-            /*
-             * iValue now contains an integer with the value of
-             * the first kDigits digits of the number.
-             * fValue contains the (float) of the same.
-             */
-
-            if ( nDigits <= singleMaxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here.
-                 */
-                if (exp == 0 || fValue == 0.0f)
-                    return (isNegative)? -fValue : fValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= singleMaxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        fValue *= singleSmall10pow[exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    int slop = singleMaxDecimalDigits - kDigits;
-                    if ( exp <= singleMaxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        fValue *= singleSmall10pow[slop];
-                        fValue *= singleSmall10pow[exp-slop];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -singleMaxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        fValue /= singleSmall10pow[-exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
+    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                mantissa = create(isNegative,exp);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+            } else {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+                if (t > 0) {
+                    mantissa[startIndex + exp] = '.';
+                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
                 }
-            } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
-                /*
-                 * In double-precision, this is an exact floating integer.
-                 * So we can compute to double, then shorten to float
-                 * with one round, and get the right answer.
-                 *
-                 * First, finish accumulating digits.
-                 * Then convert that integer to a double, multiply
-                 * by the appropriate power of ten, and convert to float.
-                 */
-                long lValue = (long)iValue;
-                for ( int i=kDigits; i < nDigits; i++ ){
-                    lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+            }
+        } else if (exp <= 0) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
                 }
-                double dValue = (double)lValue;
-                exp = decExponent-nDigits;
-                dValue *= small10pow[exp];
-                fValue = (float)dValue;
-                return (isNegative)? -fValue : fValue;
-
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
             }
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by weeding out obviously out-of-range
-             * results, then convert to double and go to
-             * common hard-case code.
-             */
-            if ( decExponent > singleMaxDecimalExponent+1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * Infinity. Cut to the chase.
-                 */
-                return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-            } else if ( decExponent < singleMinDecimalExponent-1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * zero. Cut to the chase.
-                 */
-                return (isNegative)? -0.0f : 0.0f;
-            }
-
-            /*
-             * Here, we do 'way too much work, but throwing away
-             * our partial results, and going and doing the whole
-             * thing as double, then throwing away half the bits that computes
-             * when we convert back to float.
-             *
-             * The alternative is to reproduce the whole multiple-precision
-             * algorythm for float precision, or to try to parameterize it
-             * for common usage. The former will take about 400 lines of code,
-             * and the latter I tried without success. Thus the semi-hack
-             * answer here.
-             */
-            mustSetRoundDir = !fromHex;
-            double dValue = doubleValue();
-            return stickyRound( dValue );
         }
     }
 
-
-    /*
-     * All the positive powers of 10 that can be
-     * represented exactly in double/float.
+    /**
+     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
      */
-    private static final double small10pow[] = {
-        1.0e0,
-        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
-        1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
-        1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
-        1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
-        1.0e21, 1.0e22
-    };
-
-    private static final float singleSmall10pow[] = {
-        1.0e0f,
-        1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
-        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
-    };
-
-    private static final double big10pow[] = {
-        1e16, 1e32, 1e64, 1e128, 1e256 };
-    private static final double tiny10pow[] = {
-        1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
-    private static final int maxSmallTen = small10pow.length-1;
-    private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
-    private static final int small5pow[] = {
-        1,
-        5,
-        5*5,
-        5*5*5,
-        5*5*5*5,
-        5*5*5*5*5,
-        5*5*5*5*5*5,
-        5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5*5
-    };
-
-
-    private static final long long5pow[] = {
-        1L,
-        5L,
-        5L*5,
-        5L*5*5,
-        5L*5*5*5,
-        5L*5*5*5*5,
-        5L*5*5*5*5*5,
-        5L*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-    };
-
-    // approximately ceil( log2( long5pow[i] ) )
-    private static final int n5bits[] = {
-        0,
-        3,
-        5,
-        7,
-        10,
-        12,
-        14,
-        17,
-        19,
-        21,
-        24,
-        26,
-        28,
-        31,
-        33,
-        35,
-        38,
-        40,
-        42,
-        45,
-        47,
-        49,
-        52,
-        54,
-        56,
-        59,
-        61,
-    };
-
-    private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
-    private static final char notANumber[] = { 'N', 'a', 'N' };
-    private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
+    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        int t = Math.max(0, Math.min(nDigits - 1, precision));
+        if (t > 0) {
+            mantissa = create(isNegative, t + 2);
+            mantissa[startIndex] = digits[0];
+            mantissa[startIndex + 1] = '.';
+            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+        } else {
+            mantissa = create(isNegative, 1);
+            mantissa[startIndex] = digits[0];
+        }
+        char expSign;
+        int e;
+        if (exp <= 0) {
+            expSign = '-';
+            e = -exp + 1;
+        } else {
+            expSign = '+' ;
+            e = exp - 1;
+        }
+        // decExponent has 1, 2, or 3, digits
+        if (e <= 9) {
+            exponent = new char[] { expSign,
+                    '0', (char) (e + '0') };
+        } else if (e <= 99) {
+            exponent = new char[] { expSign,
+                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        } else {
+            char hiExpChar = (char) (e / 100 + '0');
+            e %= 100;
+            exponent = new char[] { expSign,
+                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        }
+    }
 }
diff --git a/ojluni/src/main/java/sun/net/www/MimeEntry.java b/ojluni/src/main/java/sun/net/www/MimeEntry.java
deleted file mode 100755
index 005d960..0000000
--- a/ojluni/src/main/java/sun/net/www/MimeEntry.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (c) 1994, 2002, 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.net.www;
-import java.net.URL;
-import java.io.*;
-import java.util.StringTokenizer;
-
-public class MimeEntry implements Cloneable {
-    private String typeName;    // of the form: "type/subtype"
-    private String tempFileNameTemplate;
-
-    private int action;
-    private String command;
-    private String description;
-    private String imageFileName;
-    private String fileExtensions[];
-
-    boolean starred;
-
-    // Actions
-    public static final int             UNKNOWN                 = 0;
-    public static final int             LOAD_INTO_BROWSER       = 1;
-    public static final int             SAVE_TO_FILE            = 2;
-    public static final int             LAUNCH_APPLICATION      = 3;
-
-    static final String[] actionKeywords = {
-        "unknown",
-        "browser",
-        "save",
-        "application",
-    };
-
-    /**
-     * Construct an empty entry of the given type and subtype.
-     */
-    public MimeEntry(String type) {
-        // Default action is UNKNOWN so clients can decide what the default
-        // should be, typically save to file or ask user.
-        this(type, UNKNOWN, null, null, null);
-    }
-
-    //
-    // The next two constructors are used only by the deprecated
-    // PlatformMimeTable classes or, in last case, is called by the public
-    // constructor.  They are kept here anticipating putting support for
-    // mailcap formatted config files back in (so BOTH the properties format
-    // and the mailcap formats are supported).
-    //
-    MimeEntry(String type, String imageFileName, String extensionString) {
-        typeName = type.toLowerCase();
-        action = UNKNOWN;
-        command = null;
-        this.imageFileName = imageFileName;
-        setExtensions(extensionString);
-        starred = isStarred(typeName);
-    }
-
-    // For use with MimeTable::parseMailCap
-    MimeEntry(String typeName, int action, String command,
-              String tempFileNameTemplate) {
-        this.typeName = typeName.toLowerCase();
-        this.action = action;
-        this.command = command;
-        this.imageFileName = null;
-        this.fileExtensions = null;
-
-        this.tempFileNameTemplate = tempFileNameTemplate;
-    }
-
-    // This is the one called by the public constructor.
-    MimeEntry(String typeName, int action, String command,
-              String imageFileName, String fileExtensions[]) {
-
-        this.typeName = typeName.toLowerCase();
-        this.action = action;
-        this.command = command;
-        this.imageFileName = imageFileName;
-        this.fileExtensions = fileExtensions;
-
-        starred = isStarred(typeName);
-
-    }
-
-    public synchronized String getType() {
-        return typeName;
-    }
-
-    public synchronized void setType(String type) {
-        typeName = type.toLowerCase();
-    }
-
-    public synchronized int getAction() {
-        return action;
-    }
-
-    public synchronized void setAction(int action, String command) {
-        this.action = action;
-        this.command = command;
-    }
-
-    public synchronized void setAction(int action) {
-        this.action = action;
-    }
-
-    public synchronized String getLaunchString() {
-        return command;
-    }
-
-    public synchronized void setCommand(String command) {
-        this.command = command;
-    }
-
-    public synchronized String getDescription() {
-        return (description != null ? description : typeName);
-    }
-
-    public synchronized void setDescription(String description) {
-        this.description = description;
-    }
-
-    // ??? what to return for the image -- the file name or should this return
-    // something more advanced like an image source or something?
-    // returning the name has the least policy associated with it.
-    // pro tempore, we'll use the name
-    public String getImageFileName() {
-        return imageFileName;
-    }
-
-    public synchronized void setImageFileName(String filename) {
-        File file = new File(filename);
-        if (file.getParent() == null) {
-            imageFileName = System.getProperty(
-                                     "java.net.ftp.imagepath."+filename);
-        }
-        else {
-            imageFileName = filename;
-        }
-
-        if (filename.lastIndexOf('.') < 0) {
-            imageFileName = imageFileName + ".gif";
-        }
-    }
-
-    public String getTempFileTemplate() {
-        return tempFileNameTemplate;
-    }
-
-    public synchronized String[] getExtensions() {
-        return fileExtensions;
-    }
-
-    public synchronized String getExtensionsAsList() {
-        String extensionsAsString = "";
-        if (fileExtensions != null) {
-            for (int i = 0; i < fileExtensions.length; i++) {
-                extensionsAsString += fileExtensions[i];
-                if (i < (fileExtensions.length - 1)) {
-                    extensionsAsString += ",";
-                }
-            }
-        }
-
-        return extensionsAsString;
-    }
-
-    public synchronized void setExtensions(String extensionString) {
-        StringTokenizer extTokens = new StringTokenizer(extensionString, ",");
-        int numExts = extTokens.countTokens();
-        String extensionStrings[] = new String[numExts];
-
-        for (int i = 0; i < numExts; i++) {
-            String ext = (String)extTokens.nextElement();
-            extensionStrings[i] = ext.trim();
-        }
-
-        fileExtensions = extensionStrings;
-    }
-
-    private boolean isStarred(String typeName) {
-        return (typeName != null)
-            && (typeName.length() > 0)
-            && (typeName.endsWith("/*"));
-    }
-
-    /**
-     * Invoke the MIME type specific behavior for this MIME type.
-     * Returned value can be one of several types:
-     * <ol>
-     * <li>A thread -- the caller can choose when to launch this thread.
-     * <li>A string -- the string is loaded into the browser directly.
-     * <li>An input stream -- the caller can read from this byte stream and
-     *     will typically store the results in a file.
-     * <li>A document (?) --
-     * </ol>
-     */
-    public Object launch(java.net.URLConnection urlc, InputStream is, MimeTable mt) throws ApplicationLaunchException {
-        switch (action) {
-        case SAVE_TO_FILE:
-            // REMIND: is this really the right thing to do?
-            try {
-                return is;
-            } catch(Exception e) {
-                // I18N
-                return "Load to file failed:\n" + e;
-            }
-
-        case LOAD_INTO_BROWSER:
-            // REMIND: invoke the content handler?
-            // may be the right thing to do, may not be -- short term
-            // where docs are not loaded asynch, loading and returning
-            // the content is the right thing to do.
-            try {
-                return urlc.getContent();
-            } catch (Exception e) {
-                return null;
-            }
-
-        case LAUNCH_APPLICATION:
-            {
-                String threadName = command;
-                int fst = threadName.indexOf(' ');
-                if (fst > 0) {
-                    threadName = threadName.substring(0, fst);
-                }
-
-                return new MimeLauncher(this, urlc, is,
-                                        mt.getTempFileTemplate(), threadName);
-            }
-
-        case UNKNOWN:
-            // REMIND: What do do here?
-            return null;
-        }
-
-        return null;
-    }
-
-    public boolean matches(String type) {
-        if (starred) {
-          // REMIND: is this the right thing or not?
-          return type.startsWith(typeName);
-        } else {
-            return type.equals(typeName);
-        }
-    }
-
-    public Object clone() {
-        // return a shallow copy of this.
-        MimeEntry theClone = new MimeEntry(typeName);
-        theClone.action = action;
-        theClone.command = command;
-        theClone.description = description;
-        theClone.imageFileName = imageFileName;
-        theClone.tempFileNameTemplate = tempFileNameTemplate;
-        theClone.fileExtensions = fileExtensions;
-
-        return theClone;
-    }
-
-    public synchronized String toProperty() {
-        StringBuffer buf = new StringBuffer();
-
-        String separator = "; ";
-        boolean needSeparator = false;
-
-        int action = getAction();
-        if (action != MimeEntry.UNKNOWN) {
-            buf.append("action=" + actionKeywords[action]);
-            needSeparator = true;
-        }
-
-        String command = getLaunchString();
-        if (command != null && command.length() > 0) {
-            if (needSeparator) {
-                buf.append(separator);
-            }
-            buf.append("application=" + command);
-            needSeparator = true;
-        }
-
-        if (getImageFileName() != null) {
-            if (needSeparator) {
-                buf.append(separator);
-            }
-            buf.append("icon=" + getImageFileName());
-            needSeparator = true;
-        }
-
-        String extensions = getExtensionsAsList();
-        if (extensions.length() > 0) {
-            if (needSeparator) {
-                buf.append(separator);
-            }
-            buf.append("file_extensions=" + extensions);
-            needSeparator = true;
-        }
-
-        String description = getDescription();
-        if (description != null && !description.equals(getType())) {
-            if (needSeparator) {
-                buf.append(separator);
-            }
-            buf.append("description=" + description);
-        }
-
-        return buf.toString();
-    }
-
-    public String toString() {
-        return "MimeEntry[contentType=" + typeName
-            + ", image=" + imageFileName
-            + ", action=" + action
-            + ", command=" + command
-            + ", extensions=" + getExtensionsAsList()
-            + "]";
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/MimeLauncher.java b/ojluni/src/main/java/sun/net/www/MimeLauncher.java
deleted file mode 100755
index ee4fb40..0000000
--- a/ojluni/src/main/java/sun/net/www/MimeLauncher.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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.net.www;
-import java.net.URL;
-import java.io.*;
-import java.util.StringTokenizer;
-
-class MimeLauncher extends Thread {
-    java.net.URLConnection uc;
-    MimeEntry m;
-    String genericTempFileTemplate;
-    InputStream is;
-    String execPath;
-
-    MimeLauncher (MimeEntry M, java.net.URLConnection uc,
-                  InputStream is, String tempFileTemplate, String threadName) throws ApplicationLaunchException {
-        super(threadName);
-        m = M;
-        this.uc = uc;
-        this.is = is;
-        genericTempFileTemplate = tempFileTemplate;
-
-        /* get the application to launch */
-        String launchString = m.getLaunchString();
-
-        /* get a valid path to launch application - sets
-           the execPath instance variable with the correct path.
-         */
-        if (!findExecutablePath(launchString)) {
-            /* strip off parameters i.e %s */
-            String appName;
-            int index = launchString.indexOf(' ');
-            if (index != -1) {
-                appName = launchString.substring(0, index);
-            }
-            else {
-                appName = launchString;
-            }
-            throw new ApplicationLaunchException(appName);
-        }
-    }
-
-    protected String getTempFileName(URL url, String template) {
-        String tempFilename = template;
-
-        // Replace all but last occurrance of "%s" with timestamp to insure
-        // uniqueness.  There's a subtle behavior here: if there is anything
-        // _after_ the last "%s" we need to append it so that unusual launch
-        // strings that have the datafile in the middle can still be used.
-        int wildcard = tempFilename.lastIndexOf("%s");
-        String prefix = tempFilename.substring(0, wildcard);
-
-        String suffix = "";
-        if (wildcard < tempFilename.length() - 2) {
-            suffix = tempFilename.substring(wildcard + 2);
-        }
-
-        long timestamp = System.currentTimeMillis()/1000;
-        int argIndex = 0;
-        while ((argIndex = prefix.indexOf("%s")) >= 0) {
-            prefix = prefix.substring(0, argIndex)
-                + timestamp
-                + prefix.substring(argIndex + 2);
-        }
-
-        // Add a file name and file-extension if known
-        String filename = url.getFile();
-
-        String extension = "";
-        int dot = filename.lastIndexOf('.');
-
-        // BugId 4084826:  Temp MIME file names not always valid.
-        // Fix:  don't allow slashes in the file name or extension.
-        if (dot >= 0 && dot > filename.lastIndexOf('/')) {
-            extension = filename.substring(dot);
-        }
-
-        filename = "HJ" + url.hashCode();
-
-        tempFilename = prefix + filename + timestamp + extension + suffix;
-
-        return tempFilename;
-    }
-
-    public void run() {
-        try {
-            String ofn = m.getTempFileTemplate();
-            if (ofn == null) {
-                ofn = genericTempFileTemplate;
-            }
-
-            ofn = getTempFileName(uc.getURL(), ofn);
-            try {
-                OutputStream os = new FileOutputStream(ofn);
-                byte buf[] = new byte[2048];
-                int i = 0;
-                try {
-                    while ((i = is.read(buf)) >= 0) {
-                        os.write(buf, 0, i);
-                    }
-                } catch(IOException e) {
-                  //System.err.println("Exception in write loop " + i);
-                  //e.printStackTrace();
-                } finally {
-                    os.close();
-                    is.close();
-                }
-            } catch(IOException e) {
-              //System.err.println("Exception in input or output stream");
-              //e.printStackTrace();
-            }
-
-            int inx = 0;
-            String c = execPath;
-            while ((inx = c.indexOf("%t")) >= 0) {
-                c = c.substring(0, inx) + uc.getContentType()
-                    + c.substring(inx + 2);
-            }
-
-            boolean substituted = false;
-            while ((inx = c.indexOf("%s")) >= 0) {
-                c = c.substring(0, inx) + ofn + c.substring(inx + 2);
-                substituted = true;
-            }
-            if (!substituted)
-                c = c + " <" + ofn;
-
-            // System.out.println("Execing " +c);
-
-            Runtime.getRuntime().exec(c);
-        } catch(IOException e) {
-        }
-    }
-
-    /* This method determines the path for the launcher application
-       and sets the execPath instance variable.  It uses the exec.path
-       property to obtain a list of paths that is in turn used to
-       location the application.  If a valid path is not found, it
-       returns false else true.  */
-    private boolean findExecutablePath(String str) {
-        if (str == null || str.length() == 0) {
-            return false;
-        }
-
-        String command;
-        int index = str.indexOf(' ');
-        if (index != -1) {
-            command = str.substring(0, index);
-        }
-        else {
-            command = str;
-        }
-
-        File f = new File(command);
-        if (f.isFile()) {
-            // Already executable as it is
-            execPath = str;
-            return true;
-        }
-
-        String execPathList;
-        execPathList = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("exec.path"));
-        if (execPathList == null) {
-            // exec.path property not set
-            return false;
-        }
-
-        StringTokenizer iter = new StringTokenizer(execPathList, "|");
-        while (iter.hasMoreElements()) {
-            String prefix = (String)iter.nextElement();
-            String fullCmd = prefix + File.separator + command;
-            f = new File(fullCmd);
-            if (f.isFile()) {
-                execPath = prefix + File.separator + str;
-                return true;
-            }
-        }
-
-        return false; // application not found in exec.path
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/MimeTable.java b/ojluni/src/main/java/sun/net/www/MimeTable.java
deleted file mode 100755
index b8b70fd..0000000
--- a/ojluni/src/main/java/sun/net/www/MimeTable.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (c) 1994, 2010, 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.net.www;
-import java.io.*;
-import java.util.Calendar;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-import java.net.URL;
-import java.net.FileNameMap;
-import java.util.Hashtable;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-public class MimeTable implements FileNameMap {
-    /** Keyed by content type, returns MimeEntries */
-    private Hashtable<String, MimeEntry> entries
-        = new Hashtable<String, MimeEntry>();
-
-    /** Keyed by file extension (with the .), returns MimeEntries */
-    private Hashtable<String, MimeEntry> extensionMap
-        = new Hashtable<String, MimeEntry>();
-
-    // Will be reset if in the platform-specific data file
-    private static String tempFileTemplate;
-
-    static {
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                tempFileTemplate =
-                    System.getProperty("content.types.temp.file.template",
-                                       "/tmp/%s");
-
-                mailcapLocations = new String[] {
-                    System.getProperty("user.mailcap"),
-                    System.getProperty("user.home") + "/.mailcap",
-                    "/etc/mailcap",
-                    "/usr/etc/mailcap",
-                    "/usr/local/etc/mailcap",
-                    System.getProperty("hotjava.home",
-                                           "/usr/local/hotjava")
-                        + "/lib/mailcap",
-                };
-                return null;
-            }
-        });
-    }
-
-
-    private static final String filePreamble = "sun.net.www MIME content-types table";
-    private static final String fileMagic = "#" + filePreamble;
-
-    MimeTable() {
-        load();
-    }
-
-    private static class DefaultInstanceHolder {
-        static final MimeTable defaultInstance = getDefaultInstance();
-
-        static MimeTable getDefaultInstance() {
-            return java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<MimeTable>() {
-                public MimeTable run() {
-                    MimeTable instance = new MimeTable();
-                    URLConnection.setFileNameMap(instance);
-                    return instance;
-                }
-            });
-        }
-    }
-
-    /**
-     * Get the single instance of this class.  First use will load the
-     * table from a data file.
-     */
-    public static MimeTable getDefaultTable() {
-        return DefaultInstanceHolder.defaultInstance;
-    }
-
-    /**
-     *
-     */
-    public static FileNameMap loadTable() {
-        MimeTable mt = getDefaultTable();
-        return (FileNameMap)mt;
-    }
-
-    public synchronized int getSize() {
-        return entries.size();
-    }
-
-    public synchronized String getContentTypeFor(String fileName) {
-        MimeEntry entry = findByFileName(fileName);
-        if (entry != null) {
-            return entry.getType();
-        } else {
-            return null;
-        }
-    }
-
-    public synchronized void add(MimeEntry m) {
-        entries.put(m.getType(), m);
-
-        String exts[] = m.getExtensions();
-        if (exts == null) {
-            return;
-        }
-
-        for (int i = 0; i < exts.length; i++) {
-            extensionMap.put(exts[i], m);
-        }
-    }
-
-    public synchronized MimeEntry remove(String type) {
-        MimeEntry entry = entries.get(type);
-        return remove(entry);
-    }
-
-    public synchronized MimeEntry remove(MimeEntry entry) {
-        String[] extensionKeys = entry.getExtensions();
-        if (extensionKeys != null) {
-            for (int i = 0; i < extensionKeys.length; i++) {
-                extensionMap.remove(extensionKeys[i]);
-            }
-        }
-
-        return entries.remove(entry.getType());
-    }
-
-    public synchronized MimeEntry find(String type) {
-        MimeEntry entry = entries.get(type);
-        if (entry == null) {
-            // try a wildcard lookup
-            Enumeration<MimeEntry> e = entries.elements();
-            while (e.hasMoreElements()) {
-                MimeEntry wild = e.nextElement();
-                if (wild.matches(type)) {
-                    return wild;
-                }
-            }
-        }
-
-        return entry;
-    }
-
-    /**
-     * Locate a MimeEntry by the file extension that has been associated
-     * with it. Parses general file names, and URLs.
-     */
-    public MimeEntry findByFileName(String fname) {
-        String ext = "";
-
-        int i = fname.lastIndexOf('#');
-
-        if (i > 0) {
-            fname = fname.substring(0, i - 1);
-        }
-
-        i = fname.lastIndexOf('.');
-        // REMIND: OS specific delimters appear here
-        i = Math.max(i, fname.lastIndexOf('/'));
-        i = Math.max(i, fname.lastIndexOf('?'));
-
-        if (i != -1 && fname.charAt(i) == '.') {
-            ext = fname.substring(i).toLowerCase();
-        }
-
-        return findByExt(ext);
-    }
-
-    /**
-     * Locate a MimeEntry by the file extension that has been associated
-     * with it.
-     */
-    public synchronized MimeEntry findByExt(String fileExtension) {
-        return extensionMap.get(fileExtension);
-    }
-
-    public synchronized MimeEntry findByDescription(String description) {
-        Enumeration<MimeEntry> e = elements();
-        while (e.hasMoreElements()) {
-            MimeEntry entry = e.nextElement();
-            if (description.equals(entry.getDescription())) {
-                return entry;
-            }
-        }
-
-        // We failed, now try treating description as type
-        return find(description);
-    }
-
-    String getTempFileTemplate() {
-        return tempFileTemplate;
-    }
-
-    public synchronized Enumeration<MimeEntry> elements() {
-        return entries.elements();
-    }
-
-    // For backward compatibility -- mailcap format files
-    // This is not currently used, but may in the future when we add ability
-    // to read BOTH the properties format and the mailcap format.
-    protected static String[] mailcapLocations;
-
-    public synchronized void load() {
-        Properties entries = new Properties();
-        File file = null;
-        try {
-            InputStream is;
-            // First try to load the user-specific table, if it exists
-            String userTablePath =
-                System.getProperty("content.types.user.table");
-            if (userTablePath != null) {
-                file = new File(userTablePath);
-                if (!file.exists()) {
-                    // No user-table, try to load the default built-in table.
-                    file = new File(System.getProperty("java.home") +
-                                    File.separator +
-                                    "lib" +
-                                    File.separator +
-                                    "content-types.properties");
-                }
-            }
-            else {
-                // No user table, try to load the default built-in table.
-                file = new File(System.getProperty("java.home") +
-                                File.separator +
-                                "lib" +
-                                File.separator +
-                                "content-types.properties");
-            }
-
-            is = new BufferedInputStream(new FileInputStream(file));
-            entries.load(is);
-            is.close();
-        }
-        catch (IOException e) {
-            System.err.println("Warning: default mime table not found: " +
-                               file.getPath());
-            return;
-        }
-        parse(entries);
-    }
-
-    void parse(Properties entries) {
-        // first, strip out the platform-specific temp file template
-        String tempFileTemplate = (String)entries.get("temp.file.template");
-        if (tempFileTemplate != null) {
-            entries.remove("temp.file.template");
-            this.tempFileTemplate = tempFileTemplate;
-        }
-
-        // now, parse the mime-type spec's
-        Enumeration<?> types = entries.propertyNames();
-        while (types.hasMoreElements()) {
-            String type = (String)types.nextElement();
-            String attrs = entries.getProperty(type);
-            parse(type, attrs);
-        }
-    }
-
-    //
-    // Table format:
-    //
-    // <entry> ::= <table_tag> | <type_entry>
-    //
-    // <table_tag> ::= <table_format_version> | <temp_file_template>
-    //
-    // <type_entry> ::= <type_subtype_pair> '=' <type_attrs_list>
-    //
-    // <type_subtype_pair> ::= <type> '/' <subtype>
-    //
-    // <type_attrs_list> ::= <attr_value_pair> [ ';' <attr_value_pair> ]*
-    //                       | [ <attr_value_pair> ]+
-    //
-    // <attr_value_pair> ::= <attr_name> '=' <attr_value>
-    //
-    // <attr_name> ::= 'description' | 'action' | 'application'
-    //                 | 'file_extensions' | 'icon'
-    //
-    // <attr_value> ::= <legal_char>*
-    //
-    // Embedded ';' in an <attr_value> are quoted with leading '\' .
-    //
-    // Interpretation of <attr_value> depends on the <attr_name> it is
-    // associated with.
-    //
-
-    void parse(String type, String attrs) {
-        MimeEntry newEntry = new MimeEntry(type);
-
-        // REMIND handle embedded ';' and '|' and literal '"'
-        StringTokenizer tokenizer = new StringTokenizer(attrs, ";");
-        while (tokenizer.hasMoreTokens()) {
-            String pair = tokenizer.nextToken();
-            parse(pair, newEntry);
-        }
-
-        add(newEntry);
-    }
-
-    void parse(String pair, MimeEntry entry) {
-        // REMIND add exception handling...
-        String name = null;
-        String value = null;
-
-        boolean gotName = false;
-        StringTokenizer tokenizer = new StringTokenizer(pair, "=");
-        while (tokenizer.hasMoreTokens()) {
-            if (gotName) {
-                value = tokenizer.nextToken().trim();
-            }
-            else {
-                name = tokenizer.nextToken().trim();
-                gotName = true;
-            }
-        }
-
-        fill(entry, name, value);
-    }
-
-    void fill(MimeEntry entry, String name, String value) {
-        if ("description".equalsIgnoreCase(name)) {
-            entry.setDescription(value);
-        }
-        else if ("action".equalsIgnoreCase(name)) {
-            entry.setAction(getActionCode(value));
-        }
-        else if ("application".equalsIgnoreCase(name)) {
-            entry.setCommand(value);
-        }
-        else if ("icon".equalsIgnoreCase(name)) {
-            entry.setImageFileName(value);
-        }
-        else if ("file_extensions".equalsIgnoreCase(name)) {
-            entry.setExtensions(value);
-        }
-
-        // else illegal name exception
-    }
-
-    String[] getExtensions(String list) {
-        StringTokenizer tokenizer = new StringTokenizer(list, ",");
-        int n = tokenizer.countTokens();
-        String[] extensions = new String[n];
-        for (int i = 0; i < n; i++) {
-            extensions[i] = tokenizer.nextToken();
-        }
-
-        return extensions;
-    }
-
-    int getActionCode(String action) {
-        for (int i = 0; i < MimeEntry.actionKeywords.length; i++) {
-            if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) {
-                return i;
-            }
-        }
-
-        return MimeEntry.UNKNOWN;
-    }
-
-    public synchronized boolean save(String filename) {
-        if (filename == null) {
-            filename = System.getProperty("user.home" +
-                                          File.separator +
-                                          "lib" +
-                                          File.separator +
-                                          "content-types.properties");
-        }
-
-        return saveAsProperties(new File(filename));
-    }
-
-    public Properties getAsProperties() {
-        Properties properties = new Properties();
-        Enumeration<MimeEntry> e = elements();
-        while (e.hasMoreElements()) {
-            MimeEntry entry = e.nextElement();
-            properties.put(entry.getType(), entry.toProperty());
-        }
-
-        return properties;
-    }
-
-    protected boolean saveAsProperties(File file) {
-        FileOutputStream os = null;
-        try {
-            os = new FileOutputStream(file);
-            Properties properties = getAsProperties();
-            properties.put("temp.file.template", tempFileTemplate);
-            String tag;
-            String user = System.getProperty("user.name");
-            if (user != null) {
-                tag = "; customized for " + user;
-                properties.save(os, filePreamble + tag);
-            }
-            else {
-                properties.save(os, filePreamble);
-            }
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-            return false;
-        }
-        finally {
-            if (os != null) {
-                try { os.close(); } catch (IOException e) {}
-            }
-        }
-
-        return true;
-    }
-    /*
-     * Debugging utilities
-     *
-    public void list(PrintStream out) {
-        Enumeration keys = entries.keys();
-        while (keys.hasMoreElements()) {
-            String key = (String)keys.nextElement();
-            MimeEntry entry = (MimeEntry)entries.get(key);
-            out.println(key + ": " + entry);
-        }
-    }
-
-    public static void main(String[] args) {
-        MimeTable testTable = MimeTable.getDefaultTable();
-
-        Enumeration e = testTable.elements();
-        while (e.hasMoreElements()) {
-            MimeEntry entry = (MimeEntry)e.nextElement();
-            System.out.println(entry);
-        }
-
-        testTable.save(File.separator + "tmp" +
-                       File.separator + "mime_table.save");
-    }
-    */
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/gopher/GopherClient.java b/ojluni/src/main/java/sun/net/www/protocol/gopher/GopherClient.java
deleted file mode 100755
index dd19d40..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/gopher/GopherClient.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 1996, 2004, 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.net.www.protocol.gopher;
-
-import java.io.*;
-import java.util.*;
-import java.net.*;
-import sun.net.www.*;
-import sun.net.NetworkClient;
-import java.net.URL;
-import java.net.URLStreamHandler;
-
-import sun.security.action.GetBooleanAction;
-
-/** Class to maintain the state of a gopher fetch and handle the protocol */
-public class GopherClient extends NetworkClient implements Runnable {
-
-    /* The following three data members are left in for binary
-     * backwards-compatibility.  Unfortunately, HotJava sets them directly
-     * when it wants to change the settings.  The new design has us not
-     * cache these, so this is unnecessary, but eliminating the data members
-     * would break HJB 1.1 under JDK 1.2.
-     *
-     * These data members are not used, and their values are meaningless.
-     * REMIND:  Take them out for JDK 2.0!
-     */
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public static boolean       useGopherProxy;
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public static String        gopherProxyHost;
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public static int           gopherProxyPort;
-
-
-    static {
-        useGopherProxy = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetBooleanAction("gopherProxySet"))
-            .booleanValue();
-
-        gopherProxyHost = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction("gopherProxyHost"));
-
-        gopherProxyPort = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetIntegerAction("gopherProxyPort", 80))
-            .intValue();
-    }
-
-    PipedOutputStream os;
-    URL u;
-    int gtype;
-    String gkey;
-    sun.net.www.URLConnection connection;
-
-    GopherClient(sun.net.www.URLConnection connection) {
-        this.connection = connection;
-    }
-
-    /**
-     * @return true if gopher connections should go through a proxy, according
-     *          to system properties.
-     */
-    public static boolean getUseGopherProxy() {
-        return java.security.AccessController.doPrivileged(
-            new GetBooleanAction("gopherProxySet")).booleanValue();
-    }
-
-    /**
-     * @return the proxy host to use, or null if nothing is set.
-     */
-    public static String getGopherProxyHost() {
-        String host = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("gopherProxyHost"));
-        if ("".equals(host)) {
-            host = null;
-        }
-        return host;
-    }
-
-    /**
-     * @return the proxy port to use.  Will default reasonably.
-     */
-    public static int getGopherProxyPort() {
-        return java.security.AccessController.doPrivileged(
-            new sun.security.action.GetIntegerAction("gopherProxyPort", 80))
-            .intValue();
-    }
-
-    /** Given a url, setup to fetch the gopher document it refers to */
-    InputStream openStream(URL u) throws IOException {
-        this.u = u;
-        this.os = os;
-        int i = 0;
-        String s = u.getFile();
-        int limit = s.length();
-        int c = '1';
-        while (i < limit && (c = s.charAt(i)) == '/')
-            i++;
-        gtype = c == '/' ? '1' : c;
-        if (i < limit)
-            i++;
-        gkey = s.substring(i);
-
-        openServer(u.getHost(), u.getPort() <= 0 ? 70 : u.getPort());
-
-        MessageHeader msgh = new MessageHeader();
-
-        switch (gtype) {
-          case '0':
-          case '7':
-            msgh.add("content-type", "text/plain");
-            break;
-          case '1':
-            msgh.add("content-type", "text/html");
-            break;
-          case 'g':
-          case 'I':
-            msgh.add("content-type", "image/gif");
-            break;
-          default:
-            msgh.add("content-type", "content/unknown");
-            break;
-        }
-        if (gtype != '7') {
-            serverOutput.print(decodePercent(gkey) + "\r\n");
-            serverOutput.flush();
-        } else if ((i = gkey.indexOf('?')) >= 0) {
-            serverOutput.print(decodePercent(gkey.substring(0, i) + "\t" +
-                                           gkey.substring(i + 1) + "\r\n"));
-            serverOutput.flush();
-            msgh.add("content-type", "text/html");
-        } else {
-            msgh.add("content-type", "text/html");
-        }
-        connection.setProperties(msgh);
-        if (msgh.findValue("content-type") == "text/html") {
-            os = new PipedOutputStream();
-            PipedInputStream ret = new PipedInputStream();
-            ret.connect(os);
-            new Thread(this).start();
-            return ret;
-        }
-        return new GopherInputStream(this, serverInput);
-    }
-
-    /** Translate all the instances of %NN into the character they represent */
-    private String decodePercent(String s) {
-        if (s == null || s.indexOf('%') < 0)
-            return s;
-        int limit = s.length();
-        char d[] = new char[limit];
-        int dp = 0;
-        for (int sp = 0; sp < limit; sp++) {
-            int c = s.charAt(sp);
-            if (c == '%' && sp + 2 < limit) {
-                int s1 = s.charAt(sp + 1);
-                int s2 = s.charAt(sp + 2);
-                if ('0' <= s1 && s1 <= '9')
-                    s1 = s1 - '0';
-                else if ('a' <= s1 && s1 <= 'f')
-                    s1 = s1 - 'a' + 10;
-                else if ('A' <= s1 && s1 <= 'F')
-                    s1 = s1 - 'A' + 10;
-                else
-                    s1 = -1;
-                if ('0' <= s2 && s2 <= '9')
-                    s2 = s2 - '0';
-                else if ('a' <= s2 && s2 <= 'f')
-                    s2 = s2 - 'a' + 10;
-                else if ('A' <= s2 && s2 <= 'F')
-                    s2 = s2 - 'A' + 10;
-                else
-                    s2 = -1;
-                if (s1 >= 0 && s2 >= 0) {
-                    c = (s1 << 4) | s2;
-                    sp += 2;
-                }
-            }
-            d[dp++] = (char) c;
-        }
-        return new String(d, 0, dp);
-    }
-
-    /** Turn special characters into the %NN form */
-    private String encodePercent(String s) {
-        if (s == null)
-            return s;
-        int limit = s.length();
-        char d[] = null;
-        int dp = 0;
-        for (int sp = 0; sp < limit; sp++) {
-            int c = s.charAt(sp);
-            if (c <= ' ' || c == '"' || c == '%') {
-                if (d == null)
-                    d = s.toCharArray();
-                if (dp + 3 >= d.length) {
-                    char nd[] = new char[dp + 10];
-                    System.arraycopy(d, 0, nd, 0, dp);
-                    d = nd;
-                }
-                d[dp] = '%';
-                int dig = (c >> 4) & 0xF;
-                d[dp + 1] = (char) (dig < 10 ? '0' + dig : 'A' - 10 + dig);
-                dig = c & 0xF;
-                d[dp + 2] = (char) (dig < 10 ? '0' + dig : 'A' - 10 + dig);
-                dp += 3;
-            } else {
-                if (d != null) {
-                    if (dp >= d.length) {
-                        char nd[] = new char[dp + 10];
-                        System.arraycopy(d, 0, nd, 0, dp);
-                        d = nd;
-                    }
-                    d[dp] = (char) c;
-                }
-                dp++;
-            }
-        }
-        return d == null ? s : new String(d, 0, dp);
-    }
-
-    /** This method is run as a seperate thread when an incoming gopher
-        document requires translation to html */
-    public void run() {
-        int qpos = -1;
-        try {
-            if (gtype == '7' && (qpos = gkey.indexOf('?')) < 0) {
-                PrintStream ps = new PrintStream(os, false, encoding);
-                ps.print("<html><head><title>Searchable Gopher Index</title></head>\n<body><h1>Searchable Gopher Index</h1><isindex>\n</body></html>\n");
-            } else if (gtype != '1' && gtype != '7') {
-                byte buf[] = new byte[2048];
-                try {
-                    int n;
-                    while ((n = serverInput.read(buf)) >= 0)
-                            os.write(buf, 0, n);
-                } catch(Exception e) {
-                }
-            } else {
-                PrintStream ps = new PrintStream(os, false, encoding);
-                String title = null;
-                if (gtype == '7')
-                    title = "Results of searching for \"" + gkey.substring(qpos + 1)
-                        + "\" on " + u.getHost();
-                else
-                    title = "Gopher directory " + gkey + " from " + u.getHost();
-                ps.print("<html><head><title>");
-                ps.print(title);
-                ps.print("</title></head>\n<body>\n<H1>");
-                ps.print(title);
-                ps.print("</h1><dl compact>\n");
-                DataInputStream ds = new DataInputStream(serverInput);
-                String s;
-                while ((s = ds.readLine()) != null) {
-                    int len = s.length();
-                    while (len > 0 && s.charAt(len - 1) <= ' ')
-                        len--;
-                    if (len <= 0)
-                        continue;
-                    int key = s.charAt(0);
-                    int t1 = s.indexOf('\t');
-                    int t2 = t1 > 0 ? s.indexOf('\t', t1 + 1) : -1;
-                    int t3 = t2 > 0 ? s.indexOf('\t', t2 + 1) : -1;
-                    if (t3 < 0) {
-                        // ps.print("<br><i>"+s+"</i>\n");
-                        continue;
-                    }
-                    String port = t3 + 1 < len ? ":" + s.substring(t3 + 1, len) : "";
-                    String host = t2 + 1 < t3 ? s.substring(t2 + 1, t3) : u.getHost();
-                    ps.print("<dt><a href=\"gopher://" + host + port + "/"
-                             + s.substring(0, 1) + encodePercent(s.substring(t1 + 1, t2)) + "\">\n");
-                    ps.print("<img align=middle border=0 width=25 height=32 src=");
-                    switch (key) {
-                      default:
-                        ps.print(System.getProperty("java.net.ftp.imagepath.file"));
-                        break;
-                      case '0':
-                        ps.print(System.getProperty("java.net.ftp.imagepath.text"));
-                        break;
-                      case '1':
-                        ps.print(System.getProperty("java.net.ftp.imagepath.directory"));
-                        break;
-                      case 'g':
-                        ps.print(System.getProperty("java.net.ftp.imagepath.gif"));
-                        break;
-                    }
-                    ps.print(".gif align=middle><dd>\n");
-                    ps.print(s.substring(1, t1) + "</a>\n");
-                }
-                ps.print("</dl></body>\n");
-                ps.close();
-           }
-
-       } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding+ " encoding not found");
-       } catch (IOException e) {
-       } finally {
-           try {
-               closeServer();
-               os.close();
-           } catch (IOException e2) {
-           }
-        }
-    }
-}
-
-/** An input stream that does nothing more than hold on to the NetworkClient
-    that created it.  This is used when only the input stream is needed, and
-    the network client needs to be closed when the input stream is closed. */
-class GopherInputStream extends FilterInputStream {
-    NetworkClient parent;
-
-    GopherInputStream(NetworkClient o, InputStream fd) {
-        super(fd);
-        parent = o;
-    }
-
-    public void close() {
-        try {
-            parent.closeServer();
-            super.close();
-        } catch (IOException e) {
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/gopher/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/gopher/Handler.java
deleted file mode 100755
index 8009859..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/gopher/Handler.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 1995, 2003, 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.net.www.protocol.gopher;
-
-import java.io.*;
-import java.util.*;
-import sun.net.NetworkClient;
-import java.net.URL;
-import java.net.URLStreamHandler;
-import java.net.Proxy;
-import java.net.InetSocketAddress;
-import java.net.SocketPermission;
-import java.security.Permission;
-import sun.net.www.protocol.http.HttpURLConnection;
-
-/**
- * A class to handle the gopher protocol.
- */
-
-public class Handler extends java.net.URLStreamHandler {
-
-    protected int getDefaultPort() {
-        return 70;
-    }
-
-    public java.net.URLConnection openConnection(URL u)
-    throws IOException {
-        return openConnection(u, null);
-    }
-
-    public java.net.URLConnection openConnection(URL u, Proxy p)
-    throws IOException {
-
-
-        /* if set for proxy usage then go through the http code to get */
-        /* the url connection. */
-        if (p == null && GopherClient.getUseGopherProxy()) {
-            String host = GopherClient.getGopherProxyHost();
-            if (host != null) {
-                InetSocketAddress saddr = InetSocketAddress.createUnresolved(host, GopherClient.getGopherProxyPort());
-
-                p = new Proxy(Proxy.Type.HTTP, saddr);
-            }
-        }
-        if (p != null) {
-            return new HttpURLConnection(u, p);
-        }
-
-        return new GopherURLConnection(u);
-    }
-}
-
-class GopherURLConnection extends sun.net.www.URLConnection {
-
-    Permission permission;
-
-    GopherURLConnection(URL u) {
-        super(u);
-    }
-
-    public void connect() throws IOException {
-    }
-
-    public InputStream getInputStream() throws IOException {
-        return new GopherClient(this).openStream(url);
-    }
-
-    public Permission getPermission() {
-        if (permission == null) {
-            int port = url.getPort();
-            port = port < 0 ? 70 : port;
-            String host = url.getHost() + ":" + url.getPort();
-            permission = new SocketPermission(host, "connect");
-        }
-        return permission;
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
deleted file mode 100755
index 05a6174..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2001, 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 sun.net.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.net.SecureCacheResponse;
-import java.security.Principal;
-import java.io.IOException;
-import java.util.List;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import sun.net.www.http.*;
-import sun.net.www.protocol.http.HttpURLConnection;
-
-/**
- * HTTPS URL connection support.
- * We need this delegate because HttpsURLConnection is a subclass of
- * java.net.HttpURLConnection. We will avoid copying over the code from
- * sun.net.www.protocol.http.HttpURLConnection by having this class
- *
- */
-public abstract class AbstractDelegateHttpsURLConnection extends
-        HttpURLConnection {
-
-    protected AbstractDelegateHttpsURLConnection(URL url,
-            sun.net.www.protocol.http.Handler handler) throws IOException {
-        this(url, null, handler);
-    }
-
-    protected AbstractDelegateHttpsURLConnection(URL url, Proxy p,
-            sun.net.www.protocol.http.Handler handler) throws IOException {
-        super(url, p, handler);
-    }
-
-    protected abstract javax.net.ssl.SSLSocketFactory getSSLSocketFactory();
-
-    protected abstract javax.net.ssl.HostnameVerifier getHostnameVerifier();
-
-    /**
-     * No user application is able to call these routines, as no one
-     * should ever get access to an instance of
-     * DelegateHttpsURLConnection (sun.* or com.*)
-     */
-
-    /**
-     * Create a new HttpClient object, bypassing the cache of
-     * HTTP client objects/connections.
-     *
-     * Note: this method is changed from protected to public because
-     * the com.sun.ssl.internal.www.protocol.https handler reuses this
-     * class for its actual implemantation
-     *
-     * @param url the URL being accessed
-     */
-    public void setNewClient (URL url)
-        throws IOException {
-        setNewClient (url, false);
-    }
-
-    /**
-     * Obtain a HttpClient object. Use the cached copy if specified.
-     *
-     * Note: this method is changed from protected to public because
-     * the com.sun.ssl.internal.www.protocol.https handler reuses this
-     * class for its actual implemantation
-     *
-     * @param url       the URL being accessed
-     * @param useCache  whether the cached connection should be used
-     *        if present
-     */
-    public void setNewClient (URL url, boolean useCache)
-        throws IOException {
-        http = HttpsClient.New (getSSLSocketFactory(),
-                                url,
-                                getHostnameVerifier(),
-                                useCache, this);
-        ((HttpsClient)http).afterConnect();
-    }
-
-    /**
-     * Create a new HttpClient object, set up so that it uses
-     * per-instance proxying to the given HTTP proxy.  This
-     * bypasses the cache of HTTP client objects/connections.
-     *
-     * Note: this method is changed from protected to public because
-     * the com.sun.ssl.internal.www.protocol.https handler reuses this
-     * class for its actual implemantation
-     *
-     * @param url       the URL being accessed
-     * @param proxyHost the proxy host to use
-     * @param proxyPort the proxy port to use
-     */
-    public void setProxiedClient (URL url, String proxyHost, int proxyPort)
-            throws IOException {
-        setProxiedClient(url, proxyHost, proxyPort, false);
-    }
-
-    /**
-     * Obtain a HttpClient object, set up so that it uses per-instance
-     * proxying to the given HTTP proxy. Use the cached copy of HTTP
-     * client objects/connections if specified.
-     *
-     * Note: this method is changed from protected to public because
-     * the com.sun.ssl.internal.www.protocol.https handler reuses this
-     * class for its actual implemantation
-     *
-     * @param url       the URL being accessed
-     * @param proxyHost the proxy host to use
-     * @param proxyPort the proxy port to use
-     * @param useCache  whether the cached connection should be used
-     *        if present
-     */
-    public void setProxiedClient (URL url, String proxyHost, int proxyPort,
-            boolean useCache) throws IOException {
-        proxiedConnect(url, proxyHost, proxyPort, useCache);
-        if (!http.isCachedConnection()) {
-            doTunneling();
-        }
-        ((HttpsClient)http).afterConnect();
-    }
-
-    protected void proxiedConnect(URL url, String proxyHost, int proxyPort,
-            boolean useCache) throws IOException {
-        if (connected)
-            return;
-        http = HttpsClient.New (getSSLSocketFactory(),
-                                url,
-                                getHostnameVerifier(),
-                                proxyHost, proxyPort, useCache, this);
-        connected = true;
-    }
-
-    /**
-     * Used by subclass to access "connected" variable.
-     */
-    public boolean isConnected() {
-        return connected;
-    }
-
-    /**
-     * Used by subclass to access "connected" variable.
-     */
-    public void setConnected(boolean conn) {
-        connected = conn;
-    }
-
-    /**
-     * Implements the HTTP protocol handler's "connect" method,
-     * establishing an SSL connection to the server as necessary.
-     */
-    public void connect() throws IOException {
-        if (connected)
-            return;
-        plainConnect();
-        if (cachedResponse != null) {
-            // using cached response
-            return;
-        }
-        if (!http.isCachedConnection() && http.needsTunneling()) {
-            doTunneling();
-        }
-        ((HttpsClient)http).afterConnect();
-    }
-
-    // will try to use cached HttpsClient
-    protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout)
-        throws IOException {
-        return HttpsClient.New(getSSLSocketFactory(), url,
-                               getHostnameVerifier(), p, true, connectTimeout,
-                               this);
-    }
-
-    // will open new connection
-    protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout,
-                                          boolean useCache)
-        throws IOException {
-        return HttpsClient.New(getSSLSocketFactory(), url,
-                               getHostnameVerifier(), p,
-                               useCache, connectTimeout, this);
-    }
-
-    /**
-     * Returns the cipher suite in use on this connection.
-     */
-    public String getCipherSuite () {
-        if (cachedResponse != null) {
-            return ((SecureCacheResponse)cachedResponse).getCipherSuite();
-        }
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-           return ((HttpsClient)http).getCipherSuite ();
-        }
-    }
-
-    /**
-     * Returns the certificate chain the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    public java.security.cert.Certificate[] getLocalCertificates() {
-        if (cachedResponse != null) {
-            List l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain();
-            if (l == null) {
-                return null;
-            } else {
-                return (java.security.cert.Certificate[])l.toArray();
-            }
-        }
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-            return (((HttpsClient)http).getLocalCertificates ());
-        }
-    }
-
-    /**
-     * Returns the server's certificate chain, or throws
-     * SSLPeerUnverified Exception if
-     * the server did not authenticate.
-     */
-    public java.security.cert.Certificate[] getServerCertificates()
-            throws SSLPeerUnverifiedException {
-        if (cachedResponse != null) {
-            List l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain();
-            if (l == null) {
-                return null;
-            } else {
-                return (java.security.cert.Certificate[])l.toArray();
-            }
-        }
-
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-            return (((HttpsClient)http).getServerCertificates ());
-        }
-    }
-
-    /**
-     * Returns the server's X.509 certificate chain, or null if
-     * the server did not authenticate.
-     */
-    public javax.security.cert.X509Certificate[] getServerCertificateChain()
-            throws SSLPeerUnverifiedException {
-        if (cachedResponse != null) {
-            throw new UnsupportedOperationException("this method is not supported when using cache");
-        }
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-            return ((HttpsClient)http).getServerCertificateChain ();
-        }
-    }
-
-    /**
-     * Returns the server's principal, or throws SSLPeerUnverifiedException
-     * if the server did not authenticate.
-     */
-    Principal getPeerPrincipal()
-            throws SSLPeerUnverifiedException
-    {
-        if (cachedResponse != null) {
-            return ((SecureCacheResponse)cachedResponse).getPeerPrincipal();
-        }
-
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-            return (((HttpsClient)http).getPeerPrincipal());
-        }
-    }
-
-    /**
-     * Returns the principal the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    Principal getLocalPrincipal()
-    {
-        if (cachedResponse != null) {
-            return ((SecureCacheResponse)cachedResponse).getLocalPrincipal();
-        }
-
-        if (http == null) {
-            throw new IllegalStateException("connection not yet open");
-        } else {
-            return (((HttpsClient)http).getLocalPrincipal());
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java
deleted file mode 100755
index b6ff7b4..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2001, 2005, 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.net.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.io.IOException;
-
-/**
- * This class was introduced to provide an additional level of
- * abstraction between javax.net.ssl.HttpURLConnection and
- * com.sun.net.ssl.HttpURLConnection objects. <p>
- *
- * javax.net.ssl.HttpURLConnection is used in the new sun.net version
- * of protocol implementation (this one)
- * com.sun.net.ssl.HttpURLConnection is used in the com.sun version.
- *
- */
-public class DelegateHttpsURLConnection extends AbstractDelegateHttpsURLConnection {
-
-    // we need a reference to the HttpsURLConnection to get
-    // the properties set there
-    // we also need it to be public so that it can be referenced
-    // from sun.net.www.protocol.http.HttpURLConnection
-    // this is for ResponseCache.put(URI, URLConnection)
-    // second parameter needs to be cast to javax.net.ssl.HttpsURLConnection
-    // instead of AbstractDelegateHttpsURLConnection
-    public javax.net.ssl.HttpsURLConnection httpsURLConnection;
-
-    DelegateHttpsURLConnection(URL url,
-            sun.net.www.protocol.http.Handler handler,
-            javax.net.ssl.HttpsURLConnection httpsURLConnection)
-            throws IOException {
-        this(url, null, handler, httpsURLConnection);
-    }
-
-    DelegateHttpsURLConnection(URL url, Proxy p,
-            sun.net.www.protocol.http.Handler handler,
-            javax.net.ssl.HttpsURLConnection httpsURLConnection)
-            throws IOException {
-        super(url, p, handler);
-        this.httpsURLConnection = httpsURLConnection;
-    }
-
-    protected javax.net.ssl.SSLSocketFactory getSSLSocketFactory() {
-        return httpsURLConnection.getSSLSocketFactory();
-    }
-
-    protected javax.net.ssl.HostnameVerifier getHostnameVerifier() {
-        return httpsURLConnection.getHostnameVerifier();
-    }
-
-    /*
-     * Called by layered delegator's finalize() method to handle closing
-     * the underlying object.
-     */
-    protected void dispose() throws Throwable {
-        super.finalize();
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java
deleted file mode 100755
index d2be7fd..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2001, 2003, 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.
- */
-
-/*-
- *      HTTP stream opener
- */
-
-package sun.net.www.protocol.https;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.Proxy;
-
-/** open an http input stream given a URL */
-public class Handler extends sun.net.www.protocol.http.Handler {
-    protected String proxy;
-    protected int proxyPort;
-
-    protected int getDefaultPort() {
-        return 443;
-    }
-
-    public Handler () {
-        proxy = null;
-        proxyPort = -1;
-    }
-
-    public Handler (String proxy, int port) {
-        this.proxy = proxy;
-        this.proxyPort = port;
-    }
-
-    protected java.net.URLConnection openConnection(URL u)
-    throws IOException {
-        return openConnection(u, (Proxy)null);
-    }
-
-    protected java.net.URLConnection openConnection(URL u, Proxy p)
-        throws IOException {
-        return new HttpsURLConnectionImpl(u, p, this);
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java b/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java
deleted file mode 100755
index 91a5329..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2001, 2010, 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.net.www.protocol.https;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.PrintStream;
-import java.io.BufferedOutputStream;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.security.Principal;
-import java.security.cert.*;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.security.AccessController;
-
-import javax.security.auth.x500.X500Principal;
-
-import javax.net.ssl.*;
-import sun.net.www.http.HttpClient;
-import sun.net.www.protocol.http.HttpURLConnection;
-import sun.security.action.*;
-
-import sun.security.util.HostnameChecker;
-import sun.security.ssl.SSLSocketImpl;
-
-import sun.util.logging.PlatformLogger;
-import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
-
-
-/**
- * This class provides HTTPS client URL support, building on the standard
- * "sun.net.www" HTTP protocol handler.  HTTPS is the same protocol as HTTP,
- * but differs in the transport layer which it uses:  <UL>
- *
- *      <LI>There's a <em>Secure Sockets Layer</em> between TCP
- *      and the HTTP protocol code.
- *
- *      <LI>It uses a different default TCP port.
- *
- *      <LI>It doesn't use application level proxies, which can see and
- *      manipulate HTTP user level data, compromising privacy.  It uses
- *      low level tunneling instead, which hides HTTP protocol and data
- *      from all third parties.  (Traffic analysis is still possible).
- *
- *      <LI>It does basic server authentication, to protect
- *      against "URL spoofing" attacks.  This involves deciding
- *      whether the X.509 certificate chain identifying the server
- *      is trusted, and verifying that the name of the server is
- *      found in the certificate.  (The application may enable an
- *      anonymous SSL cipher suite, and such checks are not done
- *      for anonymous ciphers.)
- *
- *      <LI>It exposes key SSL session attributes, specifically the
- *      cipher suite in use and the server's X509 certificates, to
- *      application software which knows about this protocol handler.
- *
- *      </UL>
- *
- * <P> System properties used include:  <UL>
- *
- *      <LI><em>https.proxyHost</em> ... the host supporting SSL
- *      tunneling using the conventional CONNECT syntax
- *
- *      <LI><em>https.proxyPort</em> ... port to use on proxyHost
- *
- *      <LI><em>https.cipherSuites</em> ... comma separated list of
- *      SSL cipher suite names to enable.
- *
- *      <LI><em>http.nonProxyHosts</em> ...
- *
- *      </UL>
- *
- * @author David Brownell
- * @author Bill Foote
- */
-
-// final for export control reasons (access to APIs); remove with care
-final class HttpsClient extends HttpClient
-    implements HandshakeCompletedListener
-{
-    // STATIC STATE and ACCESSORS THERETO
-
-    // HTTPS uses a different default port number than HTTP.
-    private static final int    httpsPortNumber = 443;
-
-    // default HostnameVerifier class canonical name
-    private static final String defaultHVCanonicalName =
-            "javax.net.ssl.DefaultHostnameVerifier";
-
-    /** Returns the default HTTPS port (443) */
-    @Override
-    protected int getDefaultPort() { return httpsPortNumber; }
-
-    private HostnameVerifier hv;
-    private SSLSocketFactory sslSocketFactory;
-
-    // HttpClient.proxyDisabled will always be false, because we don't
-    // use an application-level HTTP proxy.  We might tunnel through
-    // our http proxy, though.
-
-
-    // INSTANCE DATA
-
-    // last negotiated SSL session
-    private SSLSession  session;
-
-    private String [] getCipherSuites() {
-        //
-        // If ciphers are assigned, sort them into an array.
-        //
-        String ciphers [];
-        String cipherString = AccessController.doPrivileged(
-                new GetPropertyAction("https.cipherSuites"));
-
-        if (cipherString == null || "".equals(cipherString)) {
-            ciphers = null;
-        } else {
-            StringTokenizer     tokenizer;
-            Vector<String>      v = new Vector<String>();
-
-            tokenizer = new StringTokenizer(cipherString, ",");
-            while (tokenizer.hasMoreTokens())
-                v.addElement(tokenizer.nextToken());
-            ciphers = new String [v.size()];
-            for (int i = 0; i < ciphers.length; i++)
-                ciphers [i] = v.elementAt(i);
-        }
-        return ciphers;
-    }
-
-    private String [] getProtocols() {
-        //
-        // If protocols are assigned, sort them into an array.
-        //
-        String protocols [];
-        String protocolString = AccessController.doPrivileged(
-                new GetPropertyAction("https.protocols"));
-
-        if (protocolString == null || "".equals(protocolString)) {
-            protocols = null;
-        } else {
-            StringTokenizer     tokenizer;
-            Vector<String>      v = new Vector<String>();
-
-            tokenizer = new StringTokenizer(protocolString, ",");
-            while (tokenizer.hasMoreTokens())
-                v.addElement(tokenizer.nextToken());
-            protocols = new String [v.size()];
-            for (int i = 0; i < protocols.length; i++) {
-                protocols [i] = v.elementAt(i);
-            }
-        }
-        return protocols;
-    }
-
-    private String getUserAgent() {
-        String userAgent = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("https.agent"));
-        if (userAgent == null || userAgent.length() == 0) {
-            userAgent = "JSSE";
-        }
-        return userAgent;
-    }
-
-    // should remove once HttpClient.newHttpProxy is putback
-    private static Proxy newHttpProxy(String proxyHost, int proxyPort) {
-        InetSocketAddress saddr = null;
-        final String phost = proxyHost;
-        final int pport = proxyPort < 0 ? httpsPortNumber : proxyPort;
-        try {
-            saddr = java.security.AccessController.doPrivileged(new
-                java.security.PrivilegedExceptionAction<InetSocketAddress>() {
-                public InetSocketAddress run() {
-                    return new InetSocketAddress(phost, pport);
-                }});
-        } catch (java.security.PrivilegedActionException pae) {
-        }
-        return new Proxy(Proxy.Type.HTTP, saddr);
-    }
-
-    // CONSTRUCTOR, FACTORY
-
-
-    /**
-     * Create an HTTPS client URL.  Traffic will be tunneled through any
-     * intermediate nodes rather than proxied, so that confidentiality
-     * of data exchanged can be preserved.  However, note that all the
-     * anonymous SSL flavors are subject to "person-in-the-middle"
-     * attacks against confidentiality.  If you enable use of those
-     * flavors, you may be giving up the protection you get through
-     * SSL tunneling.
-     *
-     * Use New to get new HttpsClient. This constructor is meant to be
-     * used only by New method. New properly checks for URL spoofing.
-     *
-     * @param URL https URL with which a connection must be established
-     */
-    private HttpsClient(SSLSocketFactory sf, URL url)
-    throws IOException
-    {
-        // HttpClient-level proxying is always disabled,
-        // because we override doConnect to do tunneling instead.
-        this(sf, url, (String)null, -1);
-    }
-
-    /**
-     *  Create an HTTPS client URL.  Traffic will be tunneled through
-     * the specified proxy server.
-     */
-    HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort)
-        throws IOException {
-        this(sf, url, proxyHost, proxyPort, -1);
-    }
-
-    /**
-     *  Create an HTTPS client URL.  Traffic will be tunneled through
-     * the specified proxy server, with a connect timeout
-     */
-    HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort,
-                int connectTimeout)
-        throws IOException {
-        this(sf, url,
-             (proxyHost == null? null:
-                HttpsClient.newHttpProxy(proxyHost, proxyPort)),
-                connectTimeout);
-    }
-
-    /**
-     *  Same as previous constructor except using a Proxy
-     */
-    HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy,
-                int connectTimeout)
-        throws IOException {
-        this.proxy = proxy;
-        setSSLSocketFactory(sf);
-        this.proxyDisabled = true;
-
-        this.host = url.getHost();
-        this.url = url;
-        port = url.getPort();
-        if (port == -1) {
-            port = getDefaultPort();
-        }
-        setConnectTimeout(connectTimeout);
-        openServer();
-    }
-
-
-    // This code largely ripped off from HttpClient.New, and
-    // it uses the same keepalive cache.
-
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                          HttpURLConnection httpuc)
-            throws IOException {
-        return HttpsClient.New(sf, url, hv, true, httpuc);
-    }
-
-    /** See HttpClient for the model for this method. */
-    static HttpClient New(SSLSocketFactory sf, URL url,
-            HostnameVerifier hv, boolean useCache,
-            HttpURLConnection httpuc) throws IOException {
-        return HttpsClient.New(sf, url, hv, (String)null, -1, useCache, httpuc);
-    }
-
-    /**
-     * Get a HTTPS client to the URL.  Traffic will be tunneled through
-     * the specified proxy server.
-     */
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                           String proxyHost, int proxyPort,
-                           HttpURLConnection httpuc) throws IOException {
-        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true, httpuc);
-    }
-
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                           String proxyHost, int proxyPort, boolean useCache,
-                           HttpURLConnection httpuc)
-        throws IOException {
-        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1,
-                               httpuc);
-    }
-
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                          String proxyHost, int proxyPort, boolean useCache,
-                          int connectTimeout, HttpURLConnection httpuc)
-        throws IOException {
-
-        return HttpsClient.New(sf, url, hv,
-                               (proxyHost == null? null :
-                                HttpsClient.newHttpProxy(proxyHost, proxyPort)),
-                               useCache, connectTimeout, httpuc);
-    }
-
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                          Proxy p, boolean useCache,
-                          int connectTimeout, HttpURLConnection httpuc)
-        throws IOException
-    {
-        if (p == null) {
-            p = Proxy.NO_PROXY;
-        }
-        HttpsClient ret = null;
-        if (useCache) {
-            /* see if one's already around */
-            ret = (HttpsClient) kac.get(url, sf);
-            if (ret != null && httpuc != null &&
-                httpuc.streaming() &&
-                httpuc.getRequestMethod() == "POST") {
-                if (!ret.available())
-                    ret = null;
-            }
-
-            if (ret != null) {
-                if ((ret.proxy != null && ret.proxy.equals(p)) ||
-                    (ret.proxy == null && p == null)) {
-                    synchronized (ret) {
-                        ret.cachedHttpClient = true;
-                        assert ret.inCache;
-                        ret.inCache = false;
-                        if (httpuc != null && ret.needsTunneling())
-                            httpuc.setTunnelState(TUNNELING);
-                        PlatformLogger logger = HttpURLConnection.getHttpLogger();
-                        if (logger.isLoggable(PlatformLogger.FINEST)) {
-                            logger.finest("KeepAlive stream retrieved from the cache, " + ret);
-                        }
-                    }
-                } else {
-                    // We cannot return this connection to the cache as it's
-                    // KeepAliveTimeout will get reset. We simply close the connection.
-                    // This should be fine as it is very rare that a connection
-                    // to the same host will not use the same proxy.
-                    synchronized(ret) {
-                        ret.inCache = false;
-                        ret.closeServer();
-                    }
-                    ret = null;
-                }
-            }
-        }
-        if (ret == null) {
-            ret = new HttpsClient(sf, url, p, connectTimeout);
-        } else {
-            SecurityManager security = System.getSecurityManager();
-            if (security != null) {
-                if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) {
-                    security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort());
-                } else {
-                    security.checkConnect(url.getHost(), url.getPort());
-                }
-            }
-            ret.url = url;
-        }
-        ret.setHostnameVerifier(hv);
-
-        return ret;
-    }
-
-    // METHODS
-    void setHostnameVerifier(HostnameVerifier hv) {
-        this.hv = hv;
-    }
-
-    void setSSLSocketFactory(SSLSocketFactory sf) {
-        sslSocketFactory = sf;
-    }
-
-    SSLSocketFactory getSSLSocketFactory() {
-        return sslSocketFactory;
-    }
-
-    /**
-     * The following method, createSocket, is defined in NetworkClient
-     * and overridden here so that the socket facroty is used to create
-     * new sockets.
-     */
-    @Override
-    protected Socket createSocket() throws IOException {
-        try {
-            return sslSocketFactory.createSocket();
-        } catch (SocketException se) {
-            //
-            // bug 6771432
-            // javax.net.SocketFactory throws a SocketException with an
-            // UnsupportedOperationException as its cause to indicate that
-            // unconnected sockets have not been implemented.
-            //
-            Throwable t = se.getCause();
-            if (t != null && t instanceof UnsupportedOperationException) {
-                return super.createSocket();
-            } else {
-                throw se;
-            }
-        }
-    }
-
-
-    @Override
-    public boolean needsTunneling() {
-        return (proxy != null && proxy.type() != Proxy.Type.DIRECT
-                && proxy.type() != Proxy.Type.SOCKS);
-    }
-
-    @Override
-    public void afterConnect() throws IOException, UnknownHostException {
-        if (!isCachedConnection()) {
-            SSLSocket s = null;
-            SSLSocketFactory factory = sslSocketFactory;
-            try {
-                if (!(serverSocket instanceof SSLSocket)) {
-                    s = (SSLSocket)factory.createSocket(serverSocket,
-                                                        host, port, true);
-                } else {
-                    s = (SSLSocket)serverSocket;
-                    if (s instanceof SSLSocketImpl) {
-                        ((SSLSocketImpl)s).setHost(host);
-                    }
-                }
-            } catch (IOException ex) {
-                // If we fail to connect through the tunnel, try it
-                // locally, as a last resort.  If this doesn't work,
-                // throw the original exception.
-                try {
-                    s = (SSLSocket)factory.createSocket(host, port);
-                } catch (IOException ignored) {
-                    throw ex;
-                }
-            }
-
-            //
-            // Force handshaking, so that we get any authentication.
-            // Register a handshake callback so our session state tracks any
-            // later session renegotiations.
-            //
-            String [] protocols = getProtocols();
-            String [] ciphers = getCipherSuites();
-            if (protocols != null) {
-                s.setEnabledProtocols(protocols);
-            }
-            if (ciphers != null) {
-                s.setEnabledCipherSuites(ciphers);
-            }
-            s.addHandshakeCompletedListener(this);
-
-            // We have two hostname verification approaches. One is in
-            // SSL/TLS socket layer, where the algorithm is configured with
-            // SSLParameters.setEndpointIdentificationAlgorithm(), and the
-            // hostname verification is done by X509ExtendedTrustManager when
-            // the algorithm is "HTTPS". The other one is in HTTPS layer,
-            // where the algorithm is customized by
-            // HttpsURLConnection.setHostnameVerifier(), and the hostname
-            // verification is done by HostnameVerifier when the default
-            // rules for hostname verification fail.
-            //
-            // The relationship between two hostname verification approaches
-            // likes the following:
-            //
-            //               |             EIA algorithm
-            //               +----------------------------------------------
-            //               |     null      |   HTTPS    |   LDAP/other   |
-            // -------------------------------------------------------------
-            //     |         |1              |2           |3               |
-            // HNV | default | Set HTTPS EIA | use EIA    | HTTPS          |
-            //     |--------------------------------------------------------
-            //     | non -   |4              |5           |6               |
-            //     | default | HTTPS/HNV     | use EIA    | HTTPS/HNV      |
-            // -------------------------------------------------------------
-            //
-            // Abbreviation:
-            //     EIA: the endpoint identification algorithm in SSL/TLS
-            //           socket layer
-            //     HNV: the hostname verification object in HTTPS layer
-            // Notes:
-            //     case 1. default HNV and EIA is null
-            //           Set EIA as HTTPS, hostname check done in SSL/TLS
-            //           layer.
-            //     case 2. default HNV and EIA is HTTPS
-            //           Use existing EIA, hostname check done in SSL/TLS
-            //           layer.
-            //     case 3. default HNV and EIA is other than HTTPS
-            //           Use existing EIA, EIA check done in SSL/TLS
-            //           layer, then do HTTPS check in HTTPS layer.
-            //     case 4. non-default HNV and EIA is null
-            //           No EIA, no EIA check done in SSL/TLS layer, then do
-            //           HTTPS check in HTTPS layer using HNV as override.
-            //     case 5. non-default HNV and EIA is HTTPS
-            //           Use existing EIA, hostname check done in SSL/TLS
-            //           layer. No HNV override possible. We will review this
-            //           decision and may update the architecture for JDK 7.
-            //     case 6. non-default HNV and EIA is other than HTTPS
-            //           Use existing EIA, EIA check done in SSL/TLS layer,
-            //           then do HTTPS check in HTTPS layer as override.
-            boolean needToCheckSpoofing = true;
-            String identification =
-                s.getSSLParameters().getEndpointIdentificationAlgorithm();
-            if (identification != null && identification.length() != 0) {
-                if (identification.equalsIgnoreCase("HTTPS")) {
-                    // Do not check server identity again out of SSLSocket,
-                    // the endpoint will be identified during TLS handshaking
-                    // in SSLSocket.
-                    needToCheckSpoofing = false;
-                }   // else, we don't understand the identification algorithm,
-                    // need to check URL spoofing here.
-            } else {
-                boolean isDefaultHostnameVerifier = false;
-
-                // We prefer to let the SSLSocket do the spoof checks, but if
-                // the application has specified a HostnameVerifier (HNV),
-                // we will always use that.
-                if (hv != null) {
-                    String canonicalName = hv.getClass().getCanonicalName();
-                    if (canonicalName != null &&
-                    canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
-                        isDefaultHostnameVerifier = true;
-                    }
-                } else {
-                    // Unlikely to happen! As the behavior is the same as the
-                    // default hostname verifier, so we prefer to let the
-                    // SSLSocket do the spoof checks.
-                    isDefaultHostnameVerifier = true;
-                }
-
-                if (isDefaultHostnameVerifier) {
-                    // If the HNV is the default from HttpsURLConnection, we
-                    // will do the spoof checks in SSLSocket.
-                    SSLParameters paramaters = s.getSSLParameters();
-                    paramaters.setEndpointIdentificationAlgorithm("HTTPS");
-                    s.setSSLParameters(paramaters);
-
-                    needToCheckSpoofing = false;
-                }
-            }
-
-            s.startHandshake();
-            session = s.getSession();
-            // change the serverSocket and serverOutput
-            serverSocket = s;
-            try {
-                serverOutput = new PrintStream(
-                    new BufferedOutputStream(serverSocket.getOutputStream()),
-                    false, encoding);
-            } catch (UnsupportedEncodingException e) {
-                throw new InternalError(encoding+" encoding not found");
-            }
-
-            // check URL spoofing if it has not been checked under handshaking
-            if (needToCheckSpoofing) {
-                checkURLSpoofing(hv);
-            }
-        } else {
-            // if we are reusing a cached https session,
-            // we don't need to do handshaking etc. But we do need to
-            // set the ssl session
-            session = ((SSLSocket)serverSocket).getSession();
-        }
-    }
-
-    // Server identity checking is done according to RFC 2818: HTTP over TLS
-    // Section 3.1 Server Identity
-    private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
-            throws IOException {
-        //
-        // Get authenticated server name, if any
-        //
-        String host = url.getHost();
-
-        // if IPv6 strip off the "[]"
-        if (host != null && host.startsWith("[") && host.endsWith("]")) {
-            host = host.substring(1, host.length()-1);
-        }
-
-        Certificate[] peerCerts = null;
-        String cipher = session.getCipherSuite();
-        try {
-            HostnameChecker checker = HostnameChecker.getInstance(
-                                                HostnameChecker.TYPE_TLS);
-
-            // Use ciphersuite to determine whether Kerberos is present.
-            if (cipher.startsWith("TLS_KRB5")) {
-                if (!HostnameChecker.match(host, getPeerPrincipal())) {
-                    throw new SSLPeerUnverifiedException("Hostname checker" +
-                                " failed for Kerberos");
-                }
-            } else { // X.509
-
-                // get the subject's certificate
-                peerCerts = session.getPeerCertificates();
-
-                X509Certificate peerCert;
-                if (peerCerts[0] instanceof
-                        java.security.cert.X509Certificate) {
-                    peerCert = (java.security.cert.X509Certificate)peerCerts[0];
-                } else {
-                    throw new SSLPeerUnverifiedException("");
-                }
-                checker.match(host, peerCert);
-            }
-
-            // if it doesn't throw an exception, we passed. Return.
-            return;
-
-        } catch (SSLPeerUnverifiedException e) {
-
-            //
-            // client explicitly changed default policy and enabled
-            // anonymous ciphers; we can't check the standard policy
-            //
-            // ignore
-        } catch (java.security.cert.CertificateException cpe) {
-            // ignore
-        }
-
-        if ((cipher != null) && (cipher.indexOf("_anon_") != -1)) {
-            return;
-        } else if ((hostnameVerifier != null) &&
-                   (hostnameVerifier.verify(host, session))) {
-            return;
-        }
-
-        serverSocket.close();
-        session.invalidate();
-
-        throw new IOException("HTTPS hostname wrong:  should be <"
-                              + url.getHost() + ">");
-    }
-
-    @Override
-    protected void putInKeepAliveCache() {
-        if (inCache) {
-            assert false : "Duplicate put to keep alive cache";
-            return;
-        }
-        inCache = true;
-        kac.put(url, sslSocketFactory, this);
-    }
-
-    /*
-     * Close an idle connection to this URL (if it exists in the cache).
-     */
-    @Override
-    public void closeIdleConnection() {
-        HttpClient http = (HttpClient) kac.get(url, sslSocketFactory);
-        if (http != null) {
-            http.closeServer();
-        }
-    }
-
-    /**
-     * Returns the cipher suite in use on this connection.
-     */
-    String getCipherSuite() {
-        return session.getCipherSuite();
-    }
-
-    /**
-     * Returns the certificate chain the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    public java.security.cert.Certificate [] getLocalCertificates() {
-        return session.getLocalCertificates();
-    }
-
-    /**
-     * Returns the certificate chain with which the server
-     * authenticated itself, or throw a SSLPeerUnverifiedException
-     * if the server did not authenticate.
-     */
-    java.security.cert.Certificate [] getServerCertificates()
-            throws SSLPeerUnverifiedException
-    {
-        return session.getPeerCertificates();
-    }
-
-    /**
-     * Returns the X.509 certificate chain with which the server
-     * authenticated itself, or null if the server did not authenticate.
-     */
-    javax.security.cert.X509Certificate [] getServerCertificateChain()
-            throws SSLPeerUnverifiedException
-    {
-        return session.getPeerCertificateChain();
-    }
-
-    /**
-     * Returns the principal with which the server authenticated
-     * itself, or throw a SSLPeerUnverifiedException if the
-     * server did not authenticate.
-     */
-    Principal getPeerPrincipal()
-            throws SSLPeerUnverifiedException
-    {
-        Principal principal;
-        try {
-            principal = session.getPeerPrincipal();
-        } catch (AbstractMethodError e) {
-            // if the provider does not support it, fallback to peer certs.
-            // return the X500Principal of the end-entity cert.
-            java.security.cert.Certificate[] certs =
-                        session.getPeerCertificates();
-            principal = (X500Principal)
-                ((X509Certificate)certs[0]).getSubjectX500Principal();
-        }
-        return principal;
-    }
-
-    /**
-     * Returns the principal the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    Principal getLocalPrincipal()
-    {
-        Principal principal;
-        try {
-            principal = session.getLocalPrincipal();
-        } catch (AbstractMethodError e) {
-            principal = null;
-            // if the provider does not support it, fallback to local certs.
-            // return the X500Principal of the end-entity cert.
-            java.security.cert.Certificate[] certs =
-                        session.getLocalCertificates();
-            if (certs != null) {
-                principal = (X500Principal)
-                    ((X509Certificate)certs[0]).getSubjectX500Principal();
-            }
-        }
-        return principal;
-    }
-
-    /**
-     * This method implements the SSL HandshakeCompleted callback,
-     * remembering the resulting session so that it may be queried
-     * for the current cipher suite and peer certificates.  Servers
-     * sometimes re-initiate handshaking, so the session in use on
-     * a given connection may change.  When sessions change, so may
-     * peer identities and cipher suites.
-     */
-    public void handshakeCompleted(HandshakeCompletedEvent event)
-    {
-        session = event.getSession();
-    }
-
-    /**
-     * @return the proxy host being used for this client, or null
-     *          if we're not going through a proxy
-     */
-    @Override
-    public String getProxyHostUsed() {
-        if (!needsTunneling()) {
-            return null;
-        } else {
-            return super.getProxyHostUsed();
-        }
-    }
-
-    /**
-     * @return the proxy port being used for this client.  Meaningless
-     *          if getProxyHostUsed() gives null.
-     */
-    @Override
-    public int getProxyPortUsed() {
-        return (proxy == null || proxy.type() == Proxy.Type.DIRECT ||
-                proxy.type() == Proxy.Type.SOCKS)? -1:
-            ((InetSocketAddress)proxy.address()).getPort();
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
deleted file mode 100755
index 832854c..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, 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.
- */
-
-/*
- * NOTE: This class lives in the package sun.net.www.protocol.https.
- * There is a copy in com.sun.net.ssl.internal.www.protocol.https for JSSE
- * 1.0.2 compatibility. It is 100% identical except the package and extends
- * lines. Any changes should be made to be class in sun.net.* and then copied
- * to com.sun.net.*.
- */
-
-// For both copies of the file, uncomment one line and comment the other
-package sun.net.www.protocol.https;
-// package com.sun.net.ssl.internal.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.net.ProtocolException;
-import java.io.*;
-import javax.net.ssl.*;
-import java.security.Permission;
-import java.security.Principal;
-import java.util.Map;
-import java.util.List;
-import sun.net.www.http.HttpClient;
-
-/**
- * A class to represent an HTTP connection to a remote object.
- *
- * Ideally, this class should subclass and inherit the http handler
- * implementation, but it can't do so because that class have the
- * wrong Java Type.  Thus it uses the delegate (aka, the
- * Adapter/Wrapper design pattern) to reuse code from the http
- * handler.
- *
- * Since it would use a delegate to access
- * sun.net.www.protocol.http.HttpURLConnection functionalities, it
- * needs to implement all public methods in it's super class and all
- * the way to Object.
- *
- */
-
-// For both copies of the file, uncomment one line and comment the
-// other. The differences between the two copies are introduced for
-// plugin, and it is marked as such.
-public class HttpsURLConnectionImpl
-        extends javax.net.ssl.HttpsURLConnection {
-// public class HttpsURLConnectionOldImpl
-//      extends com.sun.net.ssl.HttpsURLConnection {
-
-    // NOTE: made protected for plugin so that subclass can set it.
-    protected DelegateHttpsURLConnection delegate;
-
-// For both copies of the file, uncomment one line and comment the other
-    HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
-//    HttpsURLConnectionOldImpl(URL u, Handler handler) throws IOException {
-        this(u, null, handler);
-    }
-
-// For both copies of the file, uncomment one line and comment the other
-    HttpsURLConnectionImpl(URL u, Proxy p, Handler handler) throws IOException {
-//    HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
-        super(u);
-        delegate = new DelegateHttpsURLConnection(url, p, handler, this);
-    }
-
-    // NOTE: introduced for plugin
-    // subclass needs to overwrite this to set delegate to
-    // the appropriate delegatee
-    protected HttpsURLConnectionImpl(URL u) throws IOException {
-        super(u);
-    }
-
-    /**
-     * Create a new HttpClient object, bypassing the cache of
-     * HTTP client objects/connections.
-     *
-     * @param url       the URL being accessed
-     */
-    protected void setNewClient(URL url) throws IOException {
-        delegate.setNewClient(url, false);
-    }
-
-    /**
-     * Obtain a HttpClient object. Use the cached copy if specified.
-     *
-     * @param url       the URL being accessed
-     * @param useCache  whether the cached connection should be used
-     *                  if present
-     */
-    protected void setNewClient(URL url, boolean useCache)
-            throws IOException {
-        delegate.setNewClient(url, useCache);
-    }
-
-    /**
-     * Create a new HttpClient object, set up so that it uses
-     * per-instance proxying to the given HTTP proxy.  This
-     * bypasses the cache of HTTP client objects/connections.
-     *
-     * @param url       the URL being accessed
-     * @param proxyHost the proxy host to use
-     * @param proxyPort the proxy port to use
-     */
-    protected void setProxiedClient(URL url, String proxyHost, int proxyPort)
-            throws IOException {
-        delegate.setProxiedClient(url, proxyHost, proxyPort);
-    }
-
-    /**
-     * Obtain a HttpClient object, set up so that it uses per-instance
-     * proxying to the given HTTP proxy. Use the cached copy of HTTP
-     * client objects/connections if specified.
-     *
-     * @param url       the URL being accessed
-     * @param proxyHost the proxy host to use
-     * @param proxyPort the proxy port to use
-     * @param useCache  whether the cached connection should be used
-     *                  if present
-     */
-    protected void setProxiedClient(URL url, String proxyHost, int proxyPort,
-            boolean useCache) throws IOException {
-        delegate.setProxiedClient(url, proxyHost, proxyPort, useCache);
-    }
-
-    /**
-     * Implements the HTTP protocol handler's "connect" method,
-     * establishing an SSL connection to the server as necessary.
-     */
-    public void connect() throws IOException {
-        delegate.connect();
-    }
-
-    /**
-     * Used by subclass to access "connected" variable.  Since we are
-     * delegating the actual implementation to "delegate", we need to
-     * delegate the access of "connected" as well.
-     */
-    protected boolean isConnected() {
-        return delegate.isConnected();
-    }
-
-    /**
-     * Used by subclass to access "connected" variable.  Since we are
-     * delegating the actual implementation to "delegate", we need to
-     * delegate the access of "connected" as well.
-     */
-    protected void setConnected(boolean conn) {
-        delegate.setConnected(conn);
-    }
-
-    /**
-     * Returns the cipher suite in use on this connection.
-     */
-    public String getCipherSuite() {
-        return delegate.getCipherSuite();
-    }
-
-    /**
-     * Returns the certificate chain the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    public java.security.cert.Certificate []
-        getLocalCertificates() {
-        return delegate.getLocalCertificates();
-    }
-
-    /**
-     * Returns the server's certificate chain, or throws
-     * SSLPeerUnverified Exception if
-     * the server did not authenticate.
-     */
-    public java.security.cert.Certificate []
-        getServerCertificates() throws SSLPeerUnverifiedException {
-        return delegate.getServerCertificates();
-    }
-
-    /**
-     * Returns the server's X.509 certificate chain, or null if
-     * the server did not authenticate.
-     *
-     * NOTE: This method is not necessary for the version of this class
-     * implementing javax.net.ssl.HttpsURLConnection, but provided for
-     * compatibility with the com.sun.net.ssl.HttpsURLConnection version.
-     */
-    public javax.security.cert.X509Certificate[] getServerCertificateChain() {
-        try {
-            return delegate.getServerCertificateChain();
-        } catch (SSLPeerUnverifiedException e) {
-            // this method does not throw an exception as declared in
-            // com.sun.net.ssl.HttpsURLConnection.
-            // Return null for compatibility.
-            return null;
-        }
-    }
-
-    /**
-     * Returns the principal with which the server authenticated itself,
-     * or throw a SSLPeerUnverifiedException if the server did not authenticate.
-     */
-    public Principal getPeerPrincipal()
-            throws SSLPeerUnverifiedException
-    {
-        return delegate.getPeerPrincipal();
-    }
-
-    /**
-     * Returns the principal the client sent to the
-     * server, or null if the client did not authenticate.
-     */
-    public Principal getLocalPrincipal()
-    {
-        return delegate.getLocalPrincipal();
-    }
-
-    /*
-     * Allowable input/output sequences:
-     * [interpreted as POST/PUT]
-     * - get output, [write output,] get input, [read input]
-     * - get output, [write output]
-     * [interpreted as GET]
-     * - get input, [read input]
-     * Disallowed:
-     * - get input, [read input,] get output, [write output]
-     */
-
-    public synchronized OutputStream getOutputStream() throws IOException {
-        return delegate.getOutputStream();
-    }
-
-    public synchronized InputStream getInputStream() throws IOException {
-        return delegate.getInputStream();
-    }
-
-    public InputStream getErrorStream() {
-        return delegate.getErrorStream();
-    }
-
-    /**
-     * Disconnect from the server.
-     */
-    public void disconnect() {
-        delegate.disconnect();
-    }
-
-    public boolean usingProxy() {
-        return delegate.usingProxy();
-    }
-
-    /**
-     * Returns an unmodifiable Map of the header fields.
-     * The Map keys are Strings that represent the
-     * response-header field names. Each Map value is an
-     * unmodifiable List of Strings that represents
-     * the corresponding field values.
-     *
-     * @return a Map of header fields
-     * @since 1.4
-     */
-    public Map<String,List<String>> getHeaderFields() {
-        return delegate.getHeaderFields();
-    }
-
-    /**
-     * Gets a header field by name. Returns null if not known.
-     * @param name the name of the header field
-     */
-    public String getHeaderField(String name) {
-        return delegate.getHeaderField(name);
-    }
-
-    /**
-     * Gets a header field by index. Returns null if not known.
-     * @param n the index of the header field
-     */
-    public String getHeaderField(int n) {
-        return delegate.getHeaderField(n);
-    }
-
-    /**
-     * Gets a header field by index. Returns null if not known.
-     * @param n the index of the header field
-     */
-    public String getHeaderFieldKey(int n) {
-        return delegate.getHeaderFieldKey(n);
-    }
-
-    /**
-     * Sets request property. If a property with the key already
-     * exists, overwrite its value with the new value.
-     * @param value the value to be set
-     */
-    public void setRequestProperty(String key, String value) {
-        delegate.setRequestProperty(key, value);
-    }
-
-    /**
-     * Adds a general request property specified by a
-     * key-value pair.  This method will not overwrite
-     * existing values associated with the same key.
-     *
-     * @param   key     the keyword by which the request is known
-     *                  (e.g., "<code>accept</code>").
-     * @param   value  the value associated with it.
-     * @see #getRequestProperties(java.lang.String)
-     * @since 1.4
-     */
-    public void addRequestProperty(String key, String value) {
-        delegate.addRequestProperty(key, value);
-    }
-
-    /**
-     * Overwrite super class method
-     */
-    public int getResponseCode() throws IOException {
-        return delegate.getResponseCode();
-    }
-
-    public String getRequestProperty(String key) {
-        return delegate.getRequestProperty(key);
-    }
-
-    /**
-     * Returns an unmodifiable Map of general request
-     * properties for this connection. The Map keys
-     * are Strings that represent the request-header
-     * field names. Each Map value is a unmodifiable List
-     * of Strings that represents the corresponding
-     * field values.
-     *
-     * @return  a Map of the general request properties for this connection.
-     * @throws IllegalStateException if already connected
-     * @since 1.4
-     */
-    public Map<String,List<String>> getRequestProperties() {
-        return delegate.getRequestProperties();
-    }
-
-    /*
-     * We support JDK 1.2.x so we can't count on these from JDK 1.3.
-     * We override and supply our own version.
-     */
-    public void setInstanceFollowRedirects(boolean shouldFollow) {
-        delegate.setInstanceFollowRedirects(shouldFollow);
-    }
-
-    public boolean getInstanceFollowRedirects() {
-        return delegate.getInstanceFollowRedirects();
-    }
-
-    public void setRequestMethod(String method) throws ProtocolException {
-        delegate.setRequestMethod(method);
-    }
-
-    public String getRequestMethod() {
-        return delegate.getRequestMethod();
-    }
-
-    public String getResponseMessage() throws IOException {
-        return delegate.getResponseMessage();
-    }
-
-    public long getHeaderFieldDate(String name, long Default) {
-        return delegate.getHeaderFieldDate(name, Default);
-    }
-
-    public Permission getPermission() throws IOException {
-        return delegate.getPermission();
-    }
-
-    public URL getURL() {
-        return delegate.getURL();
-    }
-
-    public int getContentLength() {
-        return delegate.getContentLength();
-    }
-
-    public long getContentLengthLong() {
-        return delegate.getContentLengthLong();
-    }
-
-    public String getContentType() {
-        return delegate.getContentType();
-    }
-
-    public String getContentEncoding() {
-        return delegate.getContentEncoding();
-    }
-
-    public long getExpiration() {
-        return delegate.getExpiration();
-    }
-
-    public long getDate() {
-        return delegate.getDate();
-    }
-
-    public long getLastModified() {
-        return delegate.getLastModified();
-    }
-
-    public int getHeaderFieldInt(String name, int Default) {
-        return delegate.getHeaderFieldInt(name, Default);
-    }
-
-    public long getHeaderFieldLong(String name, long Default) {
-        return delegate.getHeaderFieldLong(name, Default);
-    }
-
-    public Object getContent() throws IOException {
-        return delegate.getContent();
-    }
-
-    public Object getContent(Class[] classes) throws IOException {
-        return delegate.getContent(classes);
-    }
-
-    public String toString() {
-        return delegate.toString();
-    }
-
-    public void setDoInput(boolean doinput) {
-        delegate.setDoInput(doinput);
-    }
-
-    public boolean getDoInput() {
-        return delegate.getDoInput();
-    }
-
-    public void setDoOutput(boolean dooutput) {
-        delegate.setDoOutput(dooutput);
-    }
-
-    public boolean getDoOutput() {
-        return delegate.getDoOutput();
-    }
-
-    public void setAllowUserInteraction(boolean allowuserinteraction) {
-        delegate.setAllowUserInteraction(allowuserinteraction);
-    }
-
-    public boolean getAllowUserInteraction() {
-        return delegate.getAllowUserInteraction();
-    }
-
-    public void setUseCaches(boolean usecaches) {
-        delegate.setUseCaches(usecaches);
-    }
-
-    public boolean getUseCaches() {
-        return delegate.getUseCaches();
-    }
-
-    public void setIfModifiedSince(long ifmodifiedsince) {
-        delegate.setIfModifiedSince(ifmodifiedsince);
-    }
-
-    public long getIfModifiedSince() {
-        return delegate.getIfModifiedSince();
-    }
-
-    public boolean getDefaultUseCaches() {
-        return delegate.getDefaultUseCaches();
-    }
-
-    public void setDefaultUseCaches(boolean defaultusecaches) {
-        delegate.setDefaultUseCaches(defaultusecaches);
-    }
-
-    /*
-     * finalize (dispose) the delegated object.  Otherwise
-     * sun.net.www.protocol.http.HttpURLConnection's finalize()
-     * would have to be made public.
-     */
-    protected void finalize() throws Throwable {
-        delegate.dispose();
-    }
-
-    public boolean equals(Object obj) {
-        return delegate.equals(obj);
-    }
-
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    public void setConnectTimeout(int timeout) {
-        delegate.setConnectTimeout(timeout);
-    }
-
-    public int getConnectTimeout() {
-        return delegate.getConnectTimeout();
-    }
-
-    public void setReadTimeout(int timeout) {
-        delegate.setReadTimeout(timeout);
-    }
-
-    public int getReadTimeout() {
-        return delegate.getReadTimeout();
-    }
-
-    public void setFixedLengthStreamingMode (int contentLength) {
-        delegate.setFixedLengthStreamingMode(contentLength);
-    }
-
-    public void setFixedLengthStreamingMode(long contentLength) {
-        delegate.setFixedLengthStreamingMode(contentLength);
-    }
-
-    public void setChunkedStreamingMode (int chunklen) {
-        delegate.setChunkedStreamingMode(chunklen);
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/mailto/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/mailto/Handler.java
deleted file mode 100755
index 10fe684..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/mailto/Handler.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 1995, 2000, 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.
- */
-
-/*-
- *      mailto stream opener
- */
-
-package sun.net.www.protocol.mailto;
-
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-import java.io.*;
-import sun.net.www.*;
-//import sun.net.www.protocol.news.ArticlePoster;
-import sun.net.smtp.SmtpClient;
-
-/** open an nntp input stream given a URL */
-public class Handler extends URLStreamHandler {
-
-/*
-//     private String decodePercent(String s) {
-//      if (s==null || s.indexOf('%') < 0)
-//          return s;
-//      int limit = s.length();
-//      char d[] = new char[limit];
-//      int dp = 0;
-//      for (int sp = 0; sp < limit; sp++) {
-//          int c = s.charAt(sp);
-//          if (c == '%' && sp + 2 < limit) {
-//              int s1 = s.charAt(sp + 1);
-//              int s2 = s.charAt(sp + 2);
-//              if ('0' <= s1 && s1 <= '9')
-//                  s1 = s1 - '0';
-//              else if ('a' <= s1 && s1 <= 'f')
-//                  s1 = s1 - 'a' + 10;
-//              else if ('A' <= s1 && s1 <= 'F')
-//                  s1 = s1 - 'A' + 10;
-//              else
-//                  s1 = -1;
-//              if ('0' <= s2 && s2 <= '9')
-//                  s2 = s2 - '0';
-//              else if ('a' <= s2 && s2 <= 'f')
-//                  s2 = s2 - 'a' + 10;
-//              else if ('A' <= s2 && s2 <= 'F')
-//                  s2 = s2 - 'A' + 10;
-//              else
-//                  s2 = -1;
-//              if (s1 >= 0 && s2 >= 0) {
-//                  c = (s1 << 4) | s2;
-//                  sp += 2;
-//              }
-//          }
-//          d[dp++] = (char) c;
-//      }
-//      return new String(d, 0, dp);
-//     }
-
-//     public InputStream openStream(URL u) {
-//          String dest = u.file;
-//          String subj = "";
-//          int lastsl = dest.lastIndexOf('/');
-//          if (lastsl >= 0) {
-//              int st = dest.charAt(0) == '/' ? 1 : 0;
-//              if (lastsl > st)
-//                  subj = dest.substring(st, lastsl);
-//              dest = dest.substring(lastsl + 1);
-//          }
-//          if (u.postData != null) {
-//              ArticlePoster.MailTo("Posted form",
-//                                   decodePercent(dest),
-//                                   u.postData);
-//          }
-//          else
-//              ArticlePoster.MailTo(decodePercent(subj), decodePercent(dest));
-//      return null;
-//     }
-    */
-
-    public synchronized URLConnection openConnection(URL u) {
-        return new MailToURLConnection(u);
-    }
-
-    /**
-     * This method is called to parse the string spec into URL u for a
-     * mailto protocol.
-     *
-     * @param   u the URL to receive the result of parsing the spec
-     * @param   spec the URL string to parse
-     * @param   start the character position to start parsing at.  This is
-     *          just past the ':'.
-     * @param   limit the character position to stop parsing at.
-     */
-    public void parseURL(URL u, String spec, int start, int limit) {
-
-        String protocol = u.getProtocol();
-        String host = "";
-        int port = u.getPort();
-        String file = "";
-
-        if (start < limit) {
-            file = spec.substring(start, limit);
-        }
-        /*
-         * Let's just make sure we DO have an Email address in the URL.
-         */
-        boolean nogood = false;
-        if (file == null || file.equals(""))
-            nogood = true;
-        else {
-            boolean allwhites = true;
-            for (int i = 0; i < file.length(); i++)
-                if (!Character.isWhitespace(file.charAt(i)))
-                    allwhites = false;
-            if (allwhites)
-                nogood = true;
-        }
-        if (nogood)
-            throw new RuntimeException("No email address");
-        setURL(u, protocol, host, port, file, null);
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/mailto/MailToURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/mailto/MailToURLConnection.java
deleted file mode 100755
index df4d330..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/mailto/MailToURLConnection.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 1996, 2008, 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.net.www.protocol.mailto;
-
-import java.net.URL;
-import java.net.InetAddress;
-import java.net.SocketPermission;
-import java.io.*;
-import java.security.Permission;
-import sun.net.www.*;
-import sun.net.smtp.SmtpClient;
-import sun.net.www.ParseUtil;
-
-
-/**
- * Handle mailto URLs. To send mail using a mailto URLConnection,
- * call <code>getOutputStream</code>, write the message to the output
- * stream, and close it.
- *
- */
-public class MailToURLConnection extends URLConnection {
-    InputStream is = null;
-    OutputStream os = null;
-
-    SmtpClient client;
-    Permission permission;
-    private int connectTimeout = -1;
-    private int readTimeout = -1;
-
-    MailToURLConnection(URL u) {
-        super(u);
-
-        MessageHeader props = new MessageHeader();
-        props.add("content-type", "text/html");
-        setProperties(props);
-    }
-
-    /**
-     * Get the user's full email address - stolen from
-     * HotJavaApplet.getMailAddress().
-     */
-    String getFromAddress() {
-        String str = System.getProperty("user.fromaddr");
-        if (str == null) {
-            str = System.getProperty("user.name");
-            if (str != null) {
-                String host = System.getProperty("mail.host");
-                if (host == null) {
-                    try {
-                        host = InetAddress.getLocalHost().getHostName();
-                    } catch (java.net.UnknownHostException e) {
-                    }
-                }
-                str += "@" + host;
-            } else {
-                str = "";
-            }
-        }
-        return str;
-    }
-
-    public void connect() throws IOException {
-        client = new SmtpClient(connectTimeout);
-        client.setReadTimeout(readTimeout);
-    }
-
-    @Override
-    public synchronized OutputStream getOutputStream() throws IOException {
-        if (os != null) {
-            return os;
-        } else if (is != null) {
-            throw new IOException("Cannot write output after reading input.");
-        }
-        connect();
-
-        String to = ParseUtil.decode(url.getPath());
-        client.from(getFromAddress());
-        client.to(to);
-
-        os = client.startMessage();
-        return os;
-    }
-
-    @Override
-    public Permission getPermission() throws IOException {
-        if (permission == null) {
-            connect();
-            String host = client.getMailHost() + ":" + 25;
-            permission = new SocketPermission(host, "connect");
-        }
-        return permission;
-    }
-
-    @Override
-    public void setConnectTimeout(int timeout) {
-        if (timeout < 0)
-            throw new IllegalArgumentException("timeouts can't be negative");
-        connectTimeout = timeout;
-    }
-
-    @Override
-    public int getConnectTimeout() {
-        return (connectTimeout < 0 ? 0 : connectTimeout);
-    }
-
-    @Override
-    public void setReadTimeout(int timeout) {
-        if (timeout < 0)
-            throw new IllegalArgumentException("timeouts can't be negative");
-        readTimeout = timeout;
-    }
-
-    @Override
-    public int getReadTimeout() {
-        return readTimeout < 0 ? 0 : readTimeout;
-    }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/netdoc/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/netdoc/Handler.java
deleted file mode 100755
index fbcddcb..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/netdoc/Handler.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 1996, 1998, 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.
- */
-
-/*-
- * netdoc urls point either into the local filesystem or externally
- * through an http url, with network documents being preferred.  Useful for
- * FAQs & other documents which are likely to be changing over time at the
- * central site, and where the user will want the most recent edition.
- *
- * @author Steven B. Byrne
- */
-
-package sun.net.www.protocol.netdoc;
-
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.MalformedURLException;
-import java.net.URLStreamHandler;
-import java.io.InputStream;
-import java.io.IOException;
-
-public class Handler extends URLStreamHandler {
-    static URL base;
-
-    /*
-     * Attempt to find a load the given url using the default (network)
-     * documentation location.  If that fails, use the local copy
-     */
-    public synchronized URLConnection openConnection(URL u)
-        throws IOException
-    {
-        URLConnection uc = null;
-        URL ru;
-
-        Boolean tmp = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetBooleanAction("newdoc.localonly"));
-        boolean localonly = tmp.booleanValue();
-
-        String docurl = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction("doc.url"));
-
-        String file = u.getFile();
-        if (!localonly) {
-            try {
-                if (base == null) {
-                    base = new URL(docurl);
-                }
-                ru = new URL(base, file);
-            } catch (MalformedURLException e) {
-                ru = null;
-            }
-            if (ru != null) {
-                uc = ru.openConnection();
-            }
-        }
-
-        if (uc == null) {
-            try {
-                ru = new URL("file", "~", file);
-
-                uc = ru.openConnection();
-                InputStream is = uc.getInputStream();   // Check for success.
-            } catch (MalformedURLException e) {
-                uc = null;
-            } catch (IOException e) {
-                uc = null;
-            }
-        }
-
-        if (uc == null) {
-            throw new IOException("Can't find file for URL: "
-                                  +u.toExternalForm());
-        }
-        return uc;
-    }
-}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index 50732eb..d1b398fa 100755
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -763,6 +763,26 @@
 
                     // set or refresh local address
                     localAddress = Net.localAddress(fd);
+
+                    // flush any packets already received.
+                    boolean blocking = false;
+                    synchronized (blockingLock()) {
+                        try {
+                            blocking = isBlocking();
+                            // remainder of each packet thrown away
+                            ByteBuffer tmpBuf = ByteBuffer.allocate(1);
+                            if (blocking) {
+                                configureBlocking(false);
+                            }
+                            do {
+                                tmpBuf.clear();
+                            } while (read(tmpBuf) > 0);
+                        } finally {
+                            if (blocking) {
+                                configureBlocking(true);
+                            }
+                        }
+                    }
                 }
             }
         }
diff --git a/ojluni/src/main/java/sun/nio/ch/DevPollArrayWrapper.java b/ojluni/src/main/java/sun/nio/ch/DevPollArrayWrapper.java
deleted file mode 100755
index 3151b22..0000000
--- a/ojluni/src/main/java/sun/nio/ch/DevPollArrayWrapper.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2001, 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.nio.ch;
-
-import java.io.IOException;
-import java.util.BitSet;
-import java.util.Map;
-import java.util.HashMap;
-
-
-/**
- * Manipulates a native array of pollfd structs on Solaris:
- *
- * typedef struct pollfd {
- *    int fd;
- *    short events;
- *    short revents;
- * } pollfd_t;
- *
- * @author Mike McCloskey
- * @since 1.4
- */
-
-class DevPollArrayWrapper {
-
-    // Event masks
-    static final short POLLIN       = 0x0001;
-    static final short POLLPRI      = 0x0002;
-    static final short POLLOUT      = 0x0004;
-    static final short POLLRDNORM   = 0x0040;
-    static final short POLLWRNORM   = POLLOUT;
-    static final short POLLRDBAND   = 0x0080;
-    static final short POLLWRBAND   = 0x0100;
-    static final short POLLNORM     = POLLRDNORM;
-    static final short POLLERR      = 0x0008;
-    static final short POLLHUP      = 0x0010;
-    static final short POLLNVAL     = 0x0020;
-    static final short POLLREMOVE   = 0x0800;
-    static final short POLLCONN     = POLLOUT;
-
-    // Miscellaneous constants
-    static final short SIZE_POLLFD   = 8;
-    static final short FD_OFFSET     = 0;
-    static final short EVENT_OFFSET  = 4;
-    static final short REVENT_OFFSET = 6;
-
-    // Special value to indicate that an update should be ignored
-    static final byte  IGNORE        = (byte)-1;
-
-    // Maximum number of open file descriptors
-    static final int   OPEN_MAX      = IOUtil.fdLimit();
-
-    // Number of pollfd structures to create.
-    // dpwrite/ioctl(DP_POLL) allows up to OPEN_MAX-1
-    static final int   NUM_POLLFDS   = Math.min(OPEN_MAX-1, 8192);
-
-    // Initial size of arrays for fd registration changes
-    private final int INITIAL_PENDING_UPDATE_SIZE = 64;
-
-    // maximum size of updatesLow
-    private final int MAX_UPDATE_ARRAY_SIZE = Math.min(OPEN_MAX, 64*1024);
-
-    // The pollfd array for results from devpoll driver
-    private final AllocatedNativeObject pollArray;
-
-    // Base address of the native pollArray
-    private final long pollArrayAddress;
-
-    // The fd of the devpoll driver
-    private int wfd;
-
-    // The fd of the interrupt line going out
-    private int outgoingInterruptFD;
-
-    // The fd of the interrupt line coming in
-    private int incomingInterruptFD;
-
-    // The index of the interrupt FD
-    private int interruptedIndex;
-
-    // Number of updated pollfd entries
-    int updated;
-
-    // object to synchronize fd registration changes
-    private final Object updateLock = new Object();
-
-    // number of file descriptors with registration changes pending
-    private int updateCount;
-
-    // file descriptors with registration changes pending
-    private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
-
-    // events for file descriptors with registration changes pending, indexed
-    // by file descriptor and stored as bytes for efficiency reasons. For
-    // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
-    // least then the update is stored in a map.
-    private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
-    private Map<Integer,Byte> eventsHigh;
-
-    // Used by release and updateRegistrations to track whether a file
-    // descriptor is registered with /dev/poll.
-    private final BitSet registered = new BitSet();
-
-    DevPollArrayWrapper() {
-        int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
-        pollArray = new AllocatedNativeObject(allocationSize, true);
-        pollArrayAddress = pollArray.address();
-        wfd = init();
-        if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE)
-            eventsHigh = new HashMap<>();
-    }
-
-    void initInterrupt(int fd0, int fd1) {
-        outgoingInterruptFD = fd1;
-        incomingInterruptFD = fd0;
-        register(wfd, fd0, POLLIN);
-    }
-
-    void putReventOps(int i, int revent) {
-        int offset = SIZE_POLLFD * i + REVENT_OFFSET;
-        pollArray.putShort(offset, (short)revent);
-    }
-
-    int getEventOps(int i) {
-        int offset = SIZE_POLLFD * i + EVENT_OFFSET;
-        return pollArray.getShort(offset);
-    }
-
-    int getReventOps(int i) {
-        int offset = SIZE_POLLFD * i + REVENT_OFFSET;
-        return pollArray.getShort(offset);
-    }
-
-    int getDescriptor(int i) {
-        int offset = SIZE_POLLFD * i + FD_OFFSET;
-        return pollArray.getInt(offset);
-    }
-
-    private void setUpdateEvents(int fd, byte events) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            eventsLow[fd] = events;
-        } else {
-            eventsHigh.put(Integer.valueOf(fd), Byte.valueOf(events));
-        }
-    }
-
-    private byte getUpdateEvents(int fd) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            return eventsLow[fd];
-        } else {
-            Byte result = eventsHigh.get(Integer.valueOf(fd));
-            // result should never be null
-            return result.byteValue();
-        }
-    }
-
-    void setInterest(int fd, int mask) {
-        synchronized (updateLock) {
-            // record the file descriptor and events, expanding the
-            // respective arrays first if necessary.
-            int oldCapacity = updateDescriptors.length;
-            if (updateCount == oldCapacity) {
-                int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
-                int[] newDescriptors = new int[newCapacity];
-                System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
-                updateDescriptors = newDescriptors;
-            }
-            updateDescriptors[updateCount++] = fd;
-
-            // events are stored as bytes for efficiency reasons
-            byte b = (byte)mask;
-            assert (b == mask) && (b != IGNORE);
-            setUpdateEvents(fd, b);
-        }
-    }
-
-    void release(int fd) {
-        synchronized (updateLock) {
-            // ignore any pending update for this file descriptor
-            setUpdateEvents(fd, IGNORE);
-
-            // remove from /dev/poll
-            if (registered.get(fd)) {
-                register(wfd, fd, POLLREMOVE);
-                registered.clear(fd);
-            }
-        }
-    }
-
-    void closeDevPollFD() throws IOException {
-        FileDispatcherImpl.closeIntFD(wfd);
-        pollArray.free();
-    }
-
-    int poll(long timeout) throws IOException {
-        updateRegistrations();
-        updated = poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
-        for (int i=0; i<updated; i++) {
-            if (getDescriptor(i) == incomingInterruptFD) {
-                interruptedIndex = i;
-                interrupted = true;
-                break;
-            }
-        }
-        return updated;
-    }
-
-    void updateRegistrations() throws IOException {
-        synchronized (updateLock) {
-            // Populate pollfd array with updated masks
-            int j = 0;
-            int index = 0;
-            while (j < updateCount) {
-                int fd = updateDescriptors[j];
-                short events = getUpdateEvents(fd);
-                boolean wasRegistered = registered.get(fd);
-
-                // events = 0 => POLLREMOVE or do-nothing
-                if (events != IGNORE) {
-                    if (events == 0) {
-                        if (wasRegistered) {
-                            events = POLLREMOVE;
-                            registered.clear(fd);
-                        } else {
-                            events = IGNORE;
-                        }
-                    } else {
-                        if (!wasRegistered) {
-                            registered.set(fd);
-                        }
-                    }
-                }
-
-                // populate pollfd array with updated event
-                if (events != IGNORE) {
-                    // insert POLLREMOVE if changing events
-                    if (wasRegistered && events != POLLREMOVE) {
-                        putPollFD(pollArray, index, fd, POLLREMOVE);
-                        index++;
-                    }
-                    putPollFD(pollArray, index, fd, events);
-                    index++;
-                    if (index >= (NUM_POLLFDS-1)) {
-                        registerMultiple(wfd, pollArray.address(), index);
-                        index = 0;
-                    }
-
-                    // events for this fd now up to date
-                    setUpdateEvents(fd, IGNORE);
-                }
-                j++;
-            }
-
-            // write any remaining updates
-            if (index > 0)
-                registerMultiple(wfd, pollArray.address(), index);
-
-            updateCount = 0;
-        }
-    }
-
-    private void putPollFD(AllocatedNativeObject array, int index, int fd,
-                           short event)
-    {
-        int structIndex = SIZE_POLLFD * index;
-        array.putInt(structIndex + FD_OFFSET, fd);
-        array.putShort(structIndex + EVENT_OFFSET, event);
-        array.putShort(structIndex + REVENT_OFFSET, (short)0);
-    }
-
-    boolean interrupted = false;
-
-    public void interrupt() {
-        interrupt(outgoingInterruptFD);
-    }
-
-    public int interruptedIndex() {
-        return interruptedIndex;
-    }
-
-    boolean interrupted() {
-        return interrupted;
-    }
-
-    void clearInterrupted() {
-        interrupted = false;
-    }
-
-    private native int init();
-    private native void register(int wfd, int fd, int mask);
-    private native void registerMultiple(int wfd, long address, int len)
-        throws IOException;
-    private native int poll0(long pollAddress, int numfds, long timeout,
-                             int wfd);
-    private static native void interrupt(int fd);
-}
diff --git a/ojluni/src/main/java/sun/nio/ch/DevPollSelectorImpl.java b/ojluni/src/main/java/sun/nio/ch/DevPollSelectorImpl.java
deleted file mode 100755
index 047d6f9..0000000
--- a/ojluni/src/main/java/sun/nio/ch/DevPollSelectorImpl.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, 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.nio.ch;
-
-import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
-import sun.misc.*;
-
-
-/**
- * An implementation of Selector for Solaris.
- */
-class DevPollSelectorImpl
-    extends SelectorImpl
-{
-
-    // File descriptors used for interrupt
-    protected int fd0;
-    protected int fd1;
-
-    // The poll object
-    DevPollArrayWrapper pollWrapper;
-
-    // Maps from file descriptors to keys
-    private Map<Integer,SelectionKeyImpl> fdToKey;
-
-    // True if this Selector has been closed
-    private boolean closed = false;
-
-    // Lock for close/cleanup
-    private Object closeLock = new Object();
-
-    // Lock for interrupt triggering and clearing
-    private Object interruptLock = new Object();
-    private boolean interruptTriggered = false;
-
-    /**
-     * Package private constructor called by factory method in
-     * the abstract superclass Selector.
-     */
-    DevPollSelectorImpl(SelectorProvider sp) {
-        super(sp);
-        long pipeFds = IOUtil.makePipe(false);
-        fd0 = (int) (pipeFds >>> 32);
-        fd1 = (int) pipeFds;
-        pollWrapper = new DevPollArrayWrapper();
-        pollWrapper.initInterrupt(fd0, fd1);
-        fdToKey = new HashMap<Integer,SelectionKeyImpl>();
-    }
-
-    protected int doSelect(long timeout)
-        throws IOException
-    {
-        if (closed)
-            throw new ClosedSelectorException();
-        processDeregisterQueue();
-        try {
-            begin();
-            pollWrapper.poll(timeout);
-        } finally {
-            end();
-        }
-        processDeregisterQueue();
-        int numKeysUpdated = updateSelectedKeys();
-        if (pollWrapper.interrupted()) {
-            // Clear the wakeup pipe
-            pollWrapper.putReventOps(pollWrapper.interruptedIndex(), 0);
-            synchronized (interruptLock) {
-                pollWrapper.clearInterrupted();
-                IOUtil.drain(fd0);
-                interruptTriggered = false;
-            }
-        }
-        return numKeysUpdated;
-    }
-
-    /**
-     * Update the keys whose fd's have been selected by the devpoll
-     * driver. Add the ready keys to the ready queue.
-     */
-    private int updateSelectedKeys() {
-        int entries = pollWrapper.updated;
-        int numKeysUpdated = 0;
-        for (int i=0; i<entries; i++) {
-            int nextFD = pollWrapper.getDescriptor(i);
-            SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
-            // ski is null in the case of an interrupt
-            if (ski != null) {
-                int rOps = pollWrapper.getReventOps(i);
-                if (selectedKeys.contains(ski)) {
-                    if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
-                        numKeysUpdated++;
-                    }
-                } else {
-                    ski.channel.translateAndSetReadyOps(rOps, ski);
-                    if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
-                        selectedKeys.add(ski);
-                        numKeysUpdated++;
-                    }
-                }
-            }
-        }
-        return numKeysUpdated;
-    }
-
-    protected void implClose() throws IOException {
-        if (closed)
-            return;
-        closed = true;
-
-        // prevent further wakeup
-        synchronized (interruptLock) {
-            interruptTriggered = true;
-        }
-
-        FileDispatcherImpl.closeIntFD(fd0);
-        FileDispatcherImpl.closeIntFD(fd1);
-
-        pollWrapper.release(fd0);
-        pollWrapper.closeDevPollFD();
-        selectedKeys = null;
-
-        // Deregister channels
-        Iterator<SelectionKey> i = keys.iterator();
-        while (i.hasNext()) {
-            SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-            deregister(ski);
-            SelectableChannel selch = ski.channel();
-            if (!selch.isOpen() && !selch.isRegistered())
-                ((SelChImpl)selch).kill();
-            i.remove();
-        }
-        fd0 = -1;
-        fd1 = -1;
-    }
-
-    protected void implRegister(SelectionKeyImpl ski) {
-        int fd = IOUtil.fdVal(ski.channel.getFD());
-        fdToKey.put(Integer.valueOf(fd), ski);
-        keys.add(ski);
-    }
-
-    protected void implDereg(SelectionKeyImpl ski) throws IOException {
-        int i = ski.getIndex();
-        assert (i >= 0);
-        int fd = ski.channel.getFDVal();
-        fdToKey.remove(Integer.valueOf(fd));
-        pollWrapper.release(fd);
-        ski.setIndex(-1);
-        keys.remove(ski);
-        selectedKeys.remove(ski);
-        deregister((AbstractSelectionKey)ski);
-        SelectableChannel selch = ski.channel();
-        if (!selch.isOpen() && !selch.isRegistered())
-            ((SelChImpl)selch).kill();
-    }
-
-    void putEventOps(SelectionKeyImpl sk, int ops) {
-        if (closed)
-            throw new ClosedSelectorException();
-        int fd = IOUtil.fdVal(sk.channel.getFD());
-        pollWrapper.setInterest(fd, ops);
-    }
-
-    public Selector wakeup() {
-        synchronized (interruptLock) {
-            if (!interruptTriggered) {
-                pollWrapper.interrupt();
-                interruptTriggered = true;
-            }
-        }
-        return this;
-    }
-}
diff --git a/ojluni/src/main/java/sun/nio/ch/DevPollSelectorProvider.java b/ojluni/src/main/java/sun/nio/ch/DevPollSelectorProvider.java
deleted file mode 100755
index dbd6170..0000000
--- a/ojluni/src/main/java/sun/nio/ch/DevPollSelectorProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2001, 2003, 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.nio.ch;
-
-import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-
-public class DevPollSelectorProvider
-    extends SelectorProviderImpl
-{
-    public AbstractSelector openSelector() throws IOException {
-        return new DevPollSelectorImpl(this);
-    }
-
-    public Channel inheritedChannel() throws IOException {
-        return InheritedChannel.getChannel();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/CollectionCertStore.java b/ojluni/src/main/java/sun/security/provider/certpath/CollectionCertStore.java
deleted file mode 100644
index f991434..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/CollectionCertStore.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.Certificate;
-import java.security.cert.CRL;
-import java.util.Collection;
-import java.util.ConcurrentModificationException;
-import java.util.HashSet;
-import java.security.cert.CertSelector;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertStoreParameters;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.CRLSelector;
-import java.security.cert.CertStoreSpi;
-
-/**
- * A <code>CertStore</code> that retrieves <code>Certificates</code> and
- * <code>CRL</code>s from a <code>Collection</code>.
- * <p>
- * Before calling the {@link #engineGetCertificates engineGetCertificates} or
- * {@link #engineGetCRLs engineGetCRLs} methods, the
- * {@link #CollectionCertStore(CertStoreParameters)
- * CollectionCertStore(CertStoreParameters)} constructor is called to
- * create the <code>CertStore</code> and establish the
- * <code>Collection</code> from which <code>Certificate</code>s and
- * <code>CRL</code>s will be retrieved. If the specified
- * <code>Collection</code> contains an object that is not a
- * <code>Certificate</code> or <code>CRL</code>, that object will be
- * ignored.
- * <p>
- * <b>Concurrent Access</b>
- * <p>
- * As described in the javadoc for <code>CertStoreSpi</code>, the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
- * must be thread-safe. That is, multiple threads may concurrently
- * invoke these methods on a single <code>CollectionCertStore</code>
- * object (or more than one) with no ill effects.
- * <p>
- * This is achieved by requiring that the <code>Collection</code> passed to
- * the {@link #CollectionCertStore(CertStoreParameters)
- * CollectionCertStore(CertStoreParameters)} constructor (via the
- * <code>CollectionCertStoreParameters</code> object) must have fail-fast
- * iterators. Simultaneous modifications to the <code>Collection</code> can thus be
- * detected and certificate or CRL retrieval can be retried. The fact that
- * <code>Certificate</code>s and <code>CRL</code>s must be thread-safe is also
- * essential.
- *
- * @see java.security.cert.CertStore
- *
- * @since       1.4
- * @author      Steve Hanna
- */
-public class CollectionCertStore extends CertStoreSpi {
-
-    private Collection<?> coll;
-
-    /**
-     * Creates a <code>CertStore</code> with the specified parameters.
-     * For this class, the parameters object must be an instance of
-     * <code>CollectionCertStoreParameters</code>. The <code>Collection</code>
-     * included in the <code>CollectionCertStoreParameters</code> object
-     * must be thread-safe.
-     *
-     * @param params the algorithm parameters
-     * @exception InvalidAlgorithmParameterException if params is not an
-     *   instance of <code>CollectionCertStoreParameters</code>
-     */
-    public CollectionCertStore(CertStoreParameters params)
-        throws InvalidAlgorithmParameterException
-    {
-        super(params);
-        if (!(params instanceof CollectionCertStoreParameters))
-            throw new InvalidAlgorithmParameterException(
-                "parameters must be CollectionCertStoreParameters");
-        coll = ((CollectionCertStoreParameters) params).getCollection();
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>Certificate</code>s that
-     * match the specified selector. If no <code>Certificate</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     *
-     * @param selector a <code>CertSelector</code> used to select which
-     *  <code>Certificate</code>s should be returned. Specify <code>null</code>
-     *  to return all <code>Certificate</code>s.
-     * @return a <code>Collection</code> of <code>Certificate</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    @Override
-    public Collection<Certificate> engineGetCertificates
-            (CertSelector selector) throws CertStoreException {
-        if (coll == null) {
-            throw new CertStoreException("Collection is null");
-        }
-        // Tolerate a few ConcurrentModificationExceptions
-        for (int c = 0; c < 10; c++) {
-            try {
-                HashSet<Certificate> result = new HashSet<>();
-                if (selector != null) {
-                    for (Object o : coll) {
-                        if ((o instanceof Certificate) &&
-                            selector.match((Certificate) o))
-                            result.add((Certificate)o);
-                    }
-                } else {
-                    for (Object o : coll) {
-                        if (o instanceof Certificate)
-                            result.add((Certificate)o);
-                    }
-                }
-                return(result);
-            } catch (ConcurrentModificationException e) { }
-        }
-        throw new ConcurrentModificationException("Too many "
-            + "ConcurrentModificationExceptions");
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>CRL</code>s that
-     * match the specified selector. If no <code>CRL</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     *
-     * @param selector a <code>CRLSelector</code> used to select which
-     *  <code>CRL</code>s should be returned. Specify <code>null</code>
-     *  to return all <code>CRL</code>s.
-     * @return a <code>Collection</code> of <code>CRL</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    @Override
-    public Collection<CRL> engineGetCRLs(CRLSelector selector)
-        throws CertStoreException
-    {
-        if (coll == null)
-            throw new CertStoreException("Collection is null");
-
-        // Tolerate a few ConcurrentModificationExceptions
-        for (int c = 0; c < 10; c++) {
-            try {
-                HashSet<CRL> result = new HashSet<>();
-                if (selector != null) {
-                    for (Object o : coll) {
-                        if ((o instanceof CRL) && selector.match((CRL) o))
-                            result.add((CRL)o);
-                    }
-                } else {
-                    for (Object o : coll) {
-                        if (o instanceof CRL)
-                            result.add((CRL)o);
-                    }
-                }
-                return result;
-            } catch (ConcurrentModificationException e) { }
-        }
-        throw new ConcurrentModificationException("Too many "
-            + "ConcurrentModificationExceptions");
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/IndexedCollectionCertStore.java b/ojluni/src/main/java/sun/security/provider/certpath/IndexedCollectionCertStore.java
deleted file mode 100644
index 64fcc56..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/IndexedCollectionCertStore.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath;
-
-import java.util.*;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.*;
-
-import javax.security.auth.x500.X500Principal;
-
-/**
- * A <code>CertStore</code> that retrieves <code>Certificates</code> and
- * <code>CRL</code>s from a <code>Collection</code>.
- * <p>
- * This implementation is functionally equivalent to CollectionCertStore
- * with two differences:
- * <ol>
- * <li>Upon construction, the elements in the specified Collection are
- * partially indexed. X509Certificates are indexed by subject, X509CRLs
- * by issuer, non-X509 Certificates and CRLs are copied without indexing,
- * other objects are ignored. This increases CertStore construction time
- * but allows significant speedups for searches which specify the indexed
- * attributes, in particular for large Collections (reduction from linear
- * time to effectively constant time). Searches for non-indexed queries
- * are as fast (or marginally faster) than for the standard
- * CollectionCertStore. Certificate subjects and CRL issuers
- * were found to be specified in most searches used internally by the
- * CertPath provider. Additional attributes could indexed if there are
- * queries that justify the effort.
- *
- * <li>Changes to the specified Collection after construction time are
- * not detected and ignored. This is because there is no way to efficiently
- * detect if a Collection has been modified, a full traversal would be
- * required. That would degrade lookup performance to linear time and
- * eliminated the benefit of indexing. We may fix this via the introduction
- * of new public APIs in the future.
- * </ol>
- * <p>
- * Before calling the {@link #engineGetCertificates engineGetCertificates} or
- * {@link #engineGetCRLs engineGetCRLs} methods, the
- * {@link #CollectionCertStore(CertStoreParameters)
- * CollectionCertStore(CertStoreParameters)} constructor is called to
- * create the <code>CertStore</code> and establish the
- * <code>Collection</code> from which <code>Certificate</code>s and
- * <code>CRL</code>s will be retrieved. If the specified
- * <code>Collection</code> contains an object that is not a
- * <code>Certificate</code> or <code>CRL</code>, that object will be
- * ignored.
- * <p>
- * <b>Concurrent Access</b>
- * <p>
- * As described in the javadoc for <code>CertStoreSpi</code>, the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
- * must be thread-safe. That is, multiple threads may concurrently
- * invoke these methods on a single <code>CollectionCertStore</code>
- * object (or more than one) with no ill effects.
- * <p>
- * This is achieved by requiring that the <code>Collection</code> passed to
- * the {@link #CollectionCertStore(CertStoreParameters)
- * CollectionCertStore(CertStoreParameters)} constructor (via the
- * <code>CollectionCertStoreParameters</code> object) must have fail-fast
- * iterators. Simultaneous modifications to the <code>Collection</code> can thus be
- * detected and certificate or CRL retrieval can be retried. The fact that
- * <code>Certificate</code>s and <code>CRL</code>s must be thread-safe is also
- * essential.
- *
- * @see java.security.cert.CertStore
- * @see CollectionCertStore
- *
- * @author Andreas Sterbenz
- */
-public class IndexedCollectionCertStore extends CertStoreSpi {
-
-    /**
-     * Map X500Principal(subject) -> X509Certificate | List of X509Certificate
-     */
-    private Map<X500Principal, Object> certSubjects;
-    /**
-     * Map X500Principal(issuer) -> X509CRL | List of X509CRL
-     */
-    private Map<X500Principal, Object> crlIssuers;
-    /**
-     * Sets of non-X509 certificates and CRLs
-     */
-    private Set<Certificate> otherCertificates;
-    private Set<CRL> otherCRLs;
-
-    /**
-     * Creates a <code>CertStore</code> with the specified parameters.
-     * For this class, the parameters object must be an instance of
-     * <code>CollectionCertStoreParameters</code>.
-     *
-     * @param params the algorithm parameters
-     * @exception InvalidAlgorithmParameterException if params is not an
-     *   instance of <code>CollectionCertStoreParameters</code>
-     */
-    public IndexedCollectionCertStore(CertStoreParameters params)
-            throws InvalidAlgorithmParameterException {
-        super(params);
-        if (!(params instanceof CollectionCertStoreParameters)) {
-            throw new InvalidAlgorithmParameterException(
-                "parameters must be CollectionCertStoreParameters");
-        }
-        Collection<?> coll = ((CollectionCertStoreParameters)params).getCollection();
-        if (coll == null) {
-            throw new InvalidAlgorithmParameterException
-                                        ("Collection must not be null");
-        }
-        buildIndex(coll);
-    }
-
-    /**
-     * Index the specified Collection copying all references to Certificates
-     * and CRLs.
-     */
-    private void buildIndex(Collection<?> coll) {
-        certSubjects = new HashMap<X500Principal, Object>();
-        crlIssuers = new HashMap<X500Principal, Object>();
-        otherCertificates = null;
-        otherCRLs = null;
-        for (Object obj : coll) {
-            if (obj instanceof X509Certificate) {
-                indexCertificate((X509Certificate)obj);
-            } else if (obj instanceof X509CRL) {
-                indexCRL((X509CRL)obj);
-            } else if (obj instanceof Certificate) {
-                if (otherCertificates == null) {
-                    otherCertificates = new HashSet<Certificate>();
-                }
-                otherCertificates.add((Certificate)obj);
-            } else if (obj instanceof CRL) {
-                if (otherCRLs == null) {
-                    otherCRLs = new HashSet<CRL>();
-                }
-                otherCRLs.add((CRL)obj);
-            } else {
-                // ignore
-            }
-        }
-        if (otherCertificates == null) {
-            otherCertificates = Collections.<Certificate>emptySet();
-        }
-        if (otherCRLs == null) {
-            otherCRLs = Collections.<CRL>emptySet();
-        }
-    }
-
-    /**
-     * Add an X509Certificate to the index.
-     */
-    private void indexCertificate(X509Certificate cert) {
-        X500Principal subject = cert.getSubjectX500Principal();
-        Object oldEntry = certSubjects.put(subject, cert);
-        if (oldEntry != null) { // assume this is unlikely
-            if (oldEntry instanceof X509Certificate) {
-                if (cert.equals(oldEntry)) {
-                    return;
-                }
-                List<X509Certificate> list = new ArrayList<>(2);
-                list.add(cert);
-                list.add((X509Certificate)oldEntry);
-                certSubjects.put(subject, list);
-            } else {
-                @SuppressWarnings("unchecked") // See certSubjects javadoc.
-                List<X509Certificate> list = (List<X509Certificate>)oldEntry;
-                if (list.contains(cert) == false) {
-                    list.add(cert);
-                }
-                certSubjects.put(subject, list);
-            }
-        }
-    }
-
-    /**
-     * Add an X509CRL to the index.
-     */
-    private void indexCRL(X509CRL crl) {
-        X500Principal issuer = crl.getIssuerX500Principal();
-        Object oldEntry = crlIssuers.put(issuer, crl);
-        if (oldEntry != null) { // assume this is unlikely
-            if (oldEntry instanceof X509CRL) {
-                if (crl.equals(oldEntry)) {
-                    return;
-                }
-                List<X509CRL> list = new ArrayList<>(2);
-                list.add(crl);
-                list.add((X509CRL)oldEntry);
-                crlIssuers.put(issuer, list);
-            } else {
-                // See crlIssuers javadoc.
-                @SuppressWarnings("unchecked")
-                List<X509CRL> list = (List<X509CRL>)oldEntry;
-                if (list.contains(crl) == false) {
-                    list.add(crl);
-                }
-                crlIssuers.put(issuer, list);
-            }
-        }
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>Certificate</code>s that
-     * match the specified selector. If no <code>Certificate</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     *
-     * @param selector a <code>CertSelector</code> used to select which
-     *  <code>Certificate</code>s should be returned. Specify <code>null</code>
-     *  to return all <code>Certificate</code>s.
-     * @return a <code>Collection</code> of <code>Certificate</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    @Override
-    public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
-            throws CertStoreException {
-
-        // no selector means match all
-        if (selector == null) {
-            Set<Certificate> matches = new HashSet<>();
-            matchX509Certs(new X509CertSelector(), matches);
-            matches.addAll(otherCertificates);
-            return matches;
-        }
-
-        if (selector instanceof X509CertSelector == false) {
-            Set<Certificate> matches = new HashSet<>();
-            matchX509Certs(selector, matches);
-            for (Certificate cert : otherCertificates) {
-                if (selector.match(cert)) {
-                    matches.add(cert);
-                }
-            }
-            return matches;
-        }
-
-        if (certSubjects.isEmpty()) {
-            return Collections.<X509Certificate>emptySet();
-        }
-        X509CertSelector x509Selector = (X509CertSelector)selector;
-        // see if the subject is specified
-        X500Principal subject;
-        X509Certificate matchCert = x509Selector.getCertificate();
-        if (matchCert != null) {
-            subject = matchCert.getSubjectX500Principal();
-        } else {
-            subject = x509Selector.getSubject();
-        }
-        if (subject != null) {
-            // yes, narrow down candidates to indexed possibilities
-            Object entry = certSubjects.get(subject);
-            if (entry == null) {
-                return Collections.<X509Certificate>emptySet();
-            }
-            if (entry instanceof X509Certificate) {
-                X509Certificate x509Entry = (X509Certificate)entry;
-                if (x509Selector.match(x509Entry)) {
-                    return Collections.singleton(x509Entry);
-                } else {
-                    return Collections.<X509Certificate>emptySet();
-                }
-            } else {
-                // See certSubjects javadoc.
-                @SuppressWarnings("unchecked")
-                List<X509Certificate> list = (List<X509Certificate>)entry;
-                Set<X509Certificate> matches = new HashSet<>(16);
-                for (X509Certificate cert : list) {
-                    if (x509Selector.match(cert)) {
-                        matches.add(cert);
-                    }
-                }
-                return matches;
-            }
-        }
-        // cannot use index, iterate all
-        Set<Certificate> matches = new HashSet<>(16);
-        matchX509Certs(x509Selector, matches);
-        return matches;
-    }
-
-    /**
-     * Iterate through all the X509Certificates and add matches to the
-     * collection.
-     */
-    private void matchX509Certs(CertSelector selector,
-        Collection<Certificate> matches) {
-
-        for (Object obj : certSubjects.values()) {
-            if (obj instanceof X509Certificate) {
-                X509Certificate cert = (X509Certificate)obj;
-                if (selector.match(cert)) {
-                    matches.add(cert);
-                }
-            } else {
-                // See certSubjects javadoc.
-                @SuppressWarnings("unchecked")
-                List<X509Certificate> list = (List<X509Certificate>)obj;
-                for (X509Certificate cert : list) {
-                    if (selector.match(cert)) {
-                        matches.add(cert);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>CRL</code>s that
-     * match the specified selector. If no <code>CRL</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     *
-     * @param selector a <code>CRLSelector</code> used to select which
-     *  <code>CRL</code>s should be returned. Specify <code>null</code>
-     *  to return all <code>CRL</code>s.
-     * @return a <code>Collection</code> of <code>CRL</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    @Override
-    public Collection<CRL> engineGetCRLs(CRLSelector selector)
-            throws CertStoreException {
-
-        if (selector == null) {
-            Set<CRL> matches = new HashSet<>();
-            matchX509CRLs(new X509CRLSelector(), matches);
-            matches.addAll(otherCRLs);
-            return matches;
-        }
-
-        if (selector instanceof X509CRLSelector == false) {
-            Set<CRL> matches = new HashSet<>();
-            matchX509CRLs(selector, matches);
-            for (CRL crl : otherCRLs) {
-                if (selector.match(crl)) {
-                    matches.add(crl);
-                }
-            }
-            return matches;
-        }
-
-        if (crlIssuers.isEmpty()) {
-            return Collections.<CRL>emptySet();
-        }
-        X509CRLSelector x509Selector = (X509CRLSelector)selector;
-        // see if the issuer is specified
-        Collection<X500Principal> issuers = x509Selector.getIssuers();
-        if (issuers != null) {
-            HashSet<CRL> matches = new HashSet<>(16);
-            for (X500Principal issuer : issuers) {
-                Object entry = crlIssuers.get(issuer);
-                if (entry == null) {
-                    // empty
-                } else if (entry instanceof X509CRL) {
-                    X509CRL crl = (X509CRL)entry;
-                    if (x509Selector.match(crl)) {
-                        matches.add(crl);
-                    }
-                } else { // List
-                    // See crlIssuers javadoc.
-                    @SuppressWarnings("unchecked")
-                    List<X509CRL> list = (List<X509CRL>)entry;
-                    for (X509CRL crl : list) {
-                        if (x509Selector.match(crl)) {
-                            matches.add(crl);
-                        }
-                    }
-                }
-            }
-            return matches;
-        }
-        // cannot use index, iterate all
-        Set<CRL> matches = new HashSet<>(16);
-        matchX509CRLs(x509Selector, matches);
-        return matches;
-    }
-
-    /**
-     * Iterate through all the X509CRLs and add matches to the
-     * collection.
-     */
-    private void matchX509CRLs(CRLSelector selector, Collection<CRL> matches) {
-        for (Object obj : crlIssuers.values()) {
-            if (obj instanceof X509CRL) {
-                X509CRL crl = (X509CRL)obj;
-                if (selector.match(crl)) {
-                    matches.add(crl);
-                }
-            } else {
-                // See crlIssuers javadoc.
-                @SuppressWarnings("unchecked")
-                List<X509CRL> list = (List<X509CRL>)obj;
-                for (X509CRL crl : list) {
-                    if (selector.match(crl)) {
-                        matches.add(crl);
-                    }
-                }
-            }
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStore.java b/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStore.java
deleted file mode 100644
index 5a24a69..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStore.java
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath.ldap;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URI;
-import java.util.*;
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.NameNotFoundException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-import java.security.*;
-import java.security.cert.Certificate;
-import java.security.cert.*;
-import javax.security.auth.x500.X500Principal;
-
-import sun.misc.HexDumpEncoder;
-import sun.security.provider.certpath.X509CertificatePair;
-import sun.security.util.Cache;
-import sun.security.util.Debug;
-import sun.security.x509.X500Name;
-import sun.security.action.GetBooleanAction;
-import sun.security.action.GetPropertyAction;
-
-/**
- * A <code>CertStore</code> that retrieves <code>Certificates</code> and
- * <code>CRL</code>s from an LDAP directory, using the PKIX LDAP V2 Schema
- * (RFC 2587):
- * <a href="http://www.ietf.org/rfc/rfc2587.txt">
- * http://www.ietf.org/rfc/rfc2587.txt</a>.
- * <p>
- * Before calling the {@link #engineGetCertificates engineGetCertificates} or
- * {@link #engineGetCRLs engineGetCRLs} methods, the
- * {@link #LDAPCertStore(CertStoreParameters)
- * LDAPCertStore(CertStoreParameters)} constructor is called to create the
- * <code>CertStore</code> and establish the DNS name and port of the LDAP
- * server from which <code>Certificate</code>s and <code>CRL</code>s will be
- * retrieved.
- * <p>
- * <b>Concurrent Access</b>
- * <p>
- * As described in the javadoc for <code>CertStoreSpi</code>, the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
- * must be thread-safe. That is, multiple threads may concurrently
- * invoke these methods on a single <code>LDAPCertStore</code> object
- * (or more than one) with no ill effects. This allows a
- * <code>CertPathBuilder</code> to search for a CRL while simultaneously
- * searching for further certificates, for instance.
- * <p>
- * This is achieved by adding the <code>synchronized</code> keyword to the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods.
- * <p>
- * This classes uses caching and requests multiple attributes at once to
- * minimize LDAP round trips. The cache is associated with the CertStore
- * instance. It uses soft references to hold the values to minimize impact
- * on footprint and currently has a maximum size of 750 attributes and a
- * 30 second default lifetime.
- * <p>
- * We always request CA certificates, cross certificate pairs, and ARLs in
- * a single LDAP request when any one of them is needed. The reason is that
- * we typically need all of them anyway and requesting them in one go can
- * reduce the number of requests to a third. Even if we don't need them,
- * these attributes are typically small enough not to cause a noticeable
- * overhead. In addition, when the prefetchCRLs flag is true, we also request
- * the full CRLs. It is currently false initially but set to true once any
- * request for an ARL to the server returns an null value. The reason is
- * that CRLs could be rather large but are rarely used. This implementation
- * should improve performance in most cases.
- *
- * @see java.security.cert.CertStore
- *
- * @since       1.4
- * @author      Steve Hanna
- * @author      Andreas Sterbenz
- */
-public final class LDAPCertStore extends CertStoreSpi {
-
-    private static final Debug debug = Debug.getInstance("certpath");
-
-    private final static boolean DEBUG = false;
-
-    /**
-     * LDAP attribute identifiers.
-     */
-    private static final String USER_CERT = "userCertificate;binary";
-    private static final String CA_CERT = "cACertificate;binary";
-    private static final String CROSS_CERT = "crossCertificatePair;binary";
-    private static final String CRL = "certificateRevocationList;binary";
-    private static final String ARL = "authorityRevocationList;binary";
-    private static final String DELTA_CRL = "deltaRevocationList;binary";
-
-    // Constants for various empty values
-    private final static String[] STRING0 = new String[0];
-
-    private final static byte[][] BB0 = new byte[0][];
-
-    private final static Attributes EMPTY_ATTRIBUTES = new BasicAttributes();
-
-    // cache related constants
-    private final static int DEFAULT_CACHE_SIZE = 750;
-    private final static int DEFAULT_CACHE_LIFETIME = 30;
-
-    private final static int LIFETIME;
-
-    private final static String PROP_LIFETIME =
-                            "sun.security.certpath.ldap.cache.lifetime";
-
-    /*
-     * Internal system property, that when set to "true", disables the
-     * JNDI application resource files lookup to prevent recursion issues
-     * when validating signed JARs with LDAP URLs in certificates.
-     */
-    private final static String PROP_DISABLE_APP_RESOURCE_FILES =
-        "sun.security.certpath.ldap.disable.app.resource.files";
-
-    static {
-        String s = AccessController.doPrivileged(
-                                new GetPropertyAction(PROP_LIFETIME));
-        if (s != null) {
-            LIFETIME = Integer.parseInt(s); // throws NumberFormatException
-        } else {
-            LIFETIME = DEFAULT_CACHE_LIFETIME;
-        }
-    }
-
-    /**
-     * The CertificateFactory used to decode certificates from
-     * their binary stored form.
-     */
-    private CertificateFactory cf;
-    /**
-     * The JNDI directory context.
-     */
-    private DirContext ctx;
-
-    /**
-     * Flag indicating whether we should prefetch CRLs.
-     */
-    private boolean prefetchCRLs = false;
-
-    private final Cache<String, byte[][]> valueCache;
-
-    private int cacheHits = 0;
-    private int cacheMisses = 0;
-    private int requests = 0;
-
-    /**
-     * Creates a <code>CertStore</code> with the specified parameters.
-     * For this class, the parameters object must be an instance of
-     * <code>LDAPCertStoreParameters</code>.
-     *
-     * @param params the algorithm parameters
-     * @exception InvalidAlgorithmParameterException if params is not an
-     *   instance of <code>LDAPCertStoreParameters</code>
-     */
-    public LDAPCertStore(CertStoreParameters params)
-            throws InvalidAlgorithmParameterException {
-        super(params);
-        if (!(params instanceof LDAPCertStoreParameters))
-          throw new InvalidAlgorithmParameterException(
-            "parameters must be LDAPCertStoreParameters");
-
-        LDAPCertStoreParameters lparams = (LDAPCertStoreParameters) params;
-
-        // Create InitialDirContext needed to communicate with the server
-        createInitialDirContext(lparams.getServerName(), lparams.getPort());
-
-        // Create CertificateFactory for use later on
-        try {
-            cf = CertificateFactory.getInstance("X.509");
-        } catch (CertificateException e) {
-            throw new InvalidAlgorithmParameterException(
-                "unable to create CertificateFactory for X.509");
-        }
-        if (LIFETIME == 0) {
-            valueCache = Cache.newNullCache();
-        } else if (LIFETIME < 0) {
-            valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE);
-        } else {
-            valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE, LIFETIME);
-        }
-    }
-
-    /**
-     * Returns an LDAP CertStore. This method consults a cache of
-     * CertStores (shared per JVM) using the LDAP server/port as a key.
-     */
-    private static final Cache<LDAPCertStoreParameters, CertStore>
-        certStoreCache = Cache.newSoftMemoryCache(185);
-    static synchronized CertStore getInstance(LDAPCertStoreParameters params)
-        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
-        CertStore lcs = certStoreCache.get(params);
-        if (lcs == null) {
-            lcs = CertStore.getInstance("LDAP", params);
-            certStoreCache.put(params, lcs);
-        } else {
-            if (debug != null) {
-                debug.println("LDAPCertStore.getInstance: cache hit");
-            }
-        }
-        return lcs;
-    }
-
-    /**
-     * Create InitialDirContext.
-     *
-     * @param server Server DNS name hosting LDAP service
-     * @param port   Port at which server listens for requests
-     * @throws InvalidAlgorithmParameterException if creation fails
-     */
-    private void createInitialDirContext(String server, int port)
-            throws InvalidAlgorithmParameterException {
-        String url = "ldap://" + server + ":" + port;
-        Hashtable<String,Object> env = new Hashtable<>();
-        env.put(Context.INITIAL_CONTEXT_FACTORY,
-                "com.sun.jndi.ldap.LdapCtxFactory");
-        env.put(Context.PROVIDER_URL, url);
-
-        // If property is set to true, disable application resource file lookup.
-        boolean disableAppResourceFiles = AccessController.doPrivileged(
-            new GetBooleanAction(PROP_DISABLE_APP_RESOURCE_FILES));
-        if (disableAppResourceFiles) {
-            if (debug != null) {
-                debug.println("LDAPCertStore disabling app resource files");
-            }
-            env.put("com.sun.naming.disable.app.resource.files", "true");
-        }
-
-        try {
-            ctx = new InitialDirContext(env);
-            /*
-             * By default, follow referrals unless application has
-             * overridden property in an application resource file.
-             */
-            Hashtable<?,?> currentEnv = ctx.getEnvironment();
-            if (currentEnv.get(Context.REFERRAL) == null) {
-                ctx.addToEnvironment(Context.REFERRAL, "follow");
-            }
-        } catch (NamingException e) {
-            if (debug != null) {
-                debug.println("LDAPCertStore.engineInit about to throw "
-                    + "InvalidAlgorithmParameterException");
-                e.printStackTrace();
-            }
-            Exception ee = new InvalidAlgorithmParameterException
-                ("unable to create InitialDirContext using supplied parameters");
-            ee.initCause(e);
-            throw (InvalidAlgorithmParameterException)ee;
-        }
-    }
-
-    /**
-     * Private class encapsulating the actual LDAP operations and cache
-     * handling. Use:
-     *
-     *   LDAPRequest request = new LDAPRequest(dn);
-     *   request.addRequestedAttribute(CROSS_CERT);
-     *   request.addRequestedAttribute(CA_CERT);
-     *   byte[][] crossValues = request.getValues(CROSS_CERT);
-     *   byte[][] caValues = request.getValues(CA_CERT);
-     *
-     * At most one LDAP request is sent for each instance created. If all
-     * getValues() calls can be satisfied from the cache, no request
-     * is sent at all. If a request is sent, all requested attributes
-     * are always added to the cache irrespective of whether the getValues()
-     * method is called.
-     */
-    private class LDAPRequest {
-
-        private final String name;
-        private Map<String, byte[][]> valueMap;
-        private final List<String> requestedAttributes;
-
-        LDAPRequest(String name) {
-            this.name = name;
-            requestedAttributes = new ArrayList<>(5);
-        }
-
-        String getName() {
-            return name;
-        }
-
-        void addRequestedAttribute(String attrId) {
-            if (valueMap != null) {
-                throw new IllegalStateException("Request already sent");
-            }
-            requestedAttributes.add(attrId);
-        }
-
-        /**
-         * Gets one or more binary values from an attribute.
-         *
-         * @param name          the location holding the attribute
-         * @param attrId                the attribute identifier
-         * @return                      an array of binary values (byte arrays)
-         * @throws NamingException      if a naming exception occurs
-         */
-        byte[][] getValues(String attrId) throws NamingException {
-            if (DEBUG && ((cacheHits + cacheMisses) % 50 == 0)) {
-                System.out.println("Cache hits: " + cacheHits + "; misses: "
-                        + cacheMisses);
-            }
-            String cacheKey = name + "|" + attrId;
-            byte[][] values = valueCache.get(cacheKey);
-            if (values != null) {
-                cacheHits++;
-                return values;
-            }
-            cacheMisses++;
-            Map<String, byte[][]> attrs = getValueMap();
-            values = attrs.get(attrId);
-            return values;
-        }
-
-        /**
-         * Get a map containing the values for this request. The first time
-         * this method is called on an object, the LDAP request is sent,
-         * the results parsed and added to a private map and also to the
-         * cache of this LDAPCertStore. Subsequent calls return the private
-         * map immediately.
-         *
-         * The map contains an entry for each requested attribute. The
-         * attribute name is the key, values are byte[][]. If there are no
-         * values for that attribute, values are byte[0][].
-         *
-         * @return                      the value Map
-         * @throws NamingException      if a naming exception occurs
-         */
-        private Map<String, byte[][]> getValueMap() throws NamingException {
-            if (valueMap != null) {
-                return valueMap;
-            }
-            if (DEBUG) {
-                System.out.println("Request: " + name + ":" + requestedAttributes);
-                requests++;
-                if (requests % 5 == 0) {
-                    System.out.println("LDAP requests: " + requests);
-                }
-            }
-            valueMap = new HashMap<>(8);
-            String[] attrIds = requestedAttributes.toArray(STRING0);
-            Attributes attrs;
-            try {
-                attrs = ctx.getAttributes(name, attrIds);
-            } catch (NameNotFoundException e) {
-                // name does not exist on this LDAP server
-                // treat same as not attributes found
-                attrs = EMPTY_ATTRIBUTES;
-            }
-            for (String attrId : requestedAttributes) {
-                Attribute attr = attrs.get(attrId);
-                byte[][] values = getAttributeValues(attr);
-                cacheAttribute(attrId, values);
-                valueMap.put(attrId, values);
-            }
-            return valueMap;
-        }
-
-        /**
-         * Add the values to the cache.
-         */
-        private void cacheAttribute(String attrId, byte[][] values) {
-            String cacheKey = name + "|" + attrId;
-            valueCache.put(cacheKey, values);
-        }
-
-        /**
-         * Get the values for the given attribute. If the attribute is null
-         * or does not contain any values, a zero length byte array is
-         * returned. NOTE that it is assumed that all values are byte arrays.
-         */
-        private byte[][] getAttributeValues(Attribute attr)
-                throws NamingException {
-            byte[][] values;
-            if (attr == null) {
-                values = BB0;
-            } else {
-                values = new byte[attr.size()][];
-                int i = 0;
-                NamingEnumeration<?> enum_ = attr.getAll();
-                while (enum_.hasMore()) {
-                    Object obj = enum_.next();
-                    if (debug != null) {
-                        if (obj instanceof String) {
-                            debug.println("LDAPCertStore.getAttrValues() "
-                                + "enum.next is a string!: " + obj);
-                        }
-                    }
-                    byte[] value = (byte[])obj;
-                    values[i++] = value;
-                }
-            }
-            return values;
-        }
-
-    }
-
-    /*
-     * Gets certificates from an attribute id and location in the LDAP
-     * directory. Returns a Collection containing only the Certificates that
-     * match the specified CertSelector.
-     *
-     * @param name the location holding the attribute
-     * @param id the attribute identifier
-     * @param sel a CertSelector that the Certificates must match
-     * @return a Collection of Certificates found
-     * @throws CertStoreException       if an exception occurs
-     */
-    private Collection<X509Certificate> getCertificates(LDAPRequest request,
-        String id, X509CertSelector sel) throws CertStoreException {
-
-        /* fetch encoded certs from storage */
-        byte[][] encodedCert;
-        try {
-            encodedCert = request.getValues(id);
-        } catch (NamingException namingEx) {
-            throw new CertStoreException(namingEx);
-        }
-
-        int n = encodedCert.length;
-        if (n == 0) {
-            return Collections.emptySet();
-        }
-
-        List<X509Certificate> certs = new ArrayList<>(n);
-        /* decode certs and check if they satisfy selector */
-        for (int i = 0; i < n; i++) {
-            ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]);
-            try {
-                Certificate cert = cf.generateCertificate(bais);
-                if (sel.match(cert)) {
-                  certs.add((X509Certificate)cert);
-                }
-            } catch (CertificateException e) {
-                if (debug != null) {
-                    debug.println("LDAPCertStore.getCertificates() encountered "
-                        + "exception while parsing cert, skipping the bad data: ");
-                    HexDumpEncoder encoder = new HexDumpEncoder();
-                    debug.println(
-                        "[ " + encoder.encodeBuffer(encodedCert[i]) + " ]");
-                }
-            }
-        }
-
-        return certs;
-    }
-
-    /*
-     * Gets certificate pairs from an attribute id and location in the LDAP
-     * directory.
-     *
-     * @param name the location holding the attribute
-     * @param id the attribute identifier
-     * @return a Collection of X509CertificatePairs found
-     * @throws CertStoreException       if an exception occurs
-     */
-    private Collection<X509CertificatePair> getCertPairs(
-        LDAPRequest request, String id) throws CertStoreException {
-
-        /* fetch the encoded cert pairs from storage */
-        byte[][] encodedCertPair;
-        try {
-            encodedCertPair = request.getValues(id);
-        } catch (NamingException namingEx) {
-            throw new CertStoreException(namingEx);
-        }
-
-        int n = encodedCertPair.length;
-        if (n == 0) {
-            return Collections.emptySet();
-        }
-
-        List<X509CertificatePair> certPairs = new ArrayList<>(n);
-        /* decode each cert pair and add it to the Collection */
-        for (int i = 0; i < n; i++) {
-            try {
-                X509CertificatePair certPair =
-                    X509CertificatePair.generateCertificatePair(encodedCertPair[i]);
-                certPairs.add(certPair);
-            } catch (CertificateException e) {
-                if (debug != null) {
-                    debug.println(
-                        "LDAPCertStore.getCertPairs() encountered exception "
-                        + "while parsing cert, skipping the bad data: ");
-                    HexDumpEncoder encoder = new HexDumpEncoder();
-                    debug.println(
-                        "[ " + encoder.encodeBuffer(encodedCertPair[i]) + " ]");
-                }
-            }
-        }
-
-        return certPairs;
-    }
-
-    /*
-     * Looks at certificate pairs stored in the crossCertificatePair attribute
-     * at the specified location in the LDAP directory. Returns a Collection
-     * containing all Certificates stored in the forward component that match
-     * the forward CertSelector and all Certificates stored in the reverse
-     * component that match the reverse CertSelector.
-     * <p>
-     * If either forward or reverse is null, all certificates from the
-     * corresponding component will be rejected.
-     *
-     * @param name the location to look in
-     * @param forward the forward CertSelector (or null)
-     * @param reverse the reverse CertSelector (or null)
-     * @return a Collection of Certificates found
-     * @throws CertStoreException       if an exception occurs
-     */
-    private Collection<X509Certificate> getMatchingCrossCerts(
-            LDAPRequest request, X509CertSelector forward,
-            X509CertSelector reverse)
-            throws CertStoreException {
-        // Get the cert pairs
-        Collection<X509CertificatePair> certPairs =
-                                getCertPairs(request, CROSS_CERT);
-
-        // Find Certificates that match and put them in a list
-        ArrayList<X509Certificate> matchingCerts = new ArrayList<>();
-        for (X509CertificatePair certPair : certPairs) {
-            X509Certificate cert;
-            if (forward != null) {
-                cert = certPair.getForward();
-                if ((cert != null) && forward.match(cert)) {
-                    matchingCerts.add(cert);
-                }
-            }
-            if (reverse != null) {
-                cert = certPair.getReverse();
-                if ((cert != null) && reverse.match(cert)) {
-                    matchingCerts.add(cert);
-                }
-            }
-        }
-        return matchingCerts;
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>Certificate</code>s that
-     * match the specified selector. If no <code>Certificate</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     * <p>
-     * It is not practical to search every entry in the LDAP database for
-     * matching <code>Certificate</code>s. Instead, the <code>CertSelector</code>
-     * is examined in order to determine where matching <code>Certificate</code>s
-     * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
-     * If the subject is specified, its directory entry is searched. If the
-     * issuer is specified, its directory entry is searched. If neither the
-     * subject nor the issuer are specified (or the selector is not an
-     * <code>X509CertSelector</code>), a <code>CertStoreException</code> is
-     * thrown.
-     *
-     * @param selector a <code>CertSelector</code> used to select which
-     *  <code>Certificate</code>s should be returned.
-     * @return a <code>Collection</code> of <code>Certificate</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    public synchronized Collection<X509Certificate> engineGetCertificates
-            (CertSelector selector) throws CertStoreException {
-        if (debug != null) {
-            debug.println("LDAPCertStore.engineGetCertificates() selector: "
-                + String.valueOf(selector));
-        }
-
-        if (selector == null) {
-            selector = new X509CertSelector();
-        }
-        if (!(selector instanceof X509CertSelector)) {
-            throw new CertStoreException("LDAPCertStore needs an X509CertSelector " +
-                                         "to find certs");
-        }
-        X509CertSelector xsel = (X509CertSelector) selector;
-        int basicConstraints = xsel.getBasicConstraints();
-        String subject = xsel.getSubjectAsString();
-        String issuer = xsel.getIssuerAsString();
-        HashSet<X509Certificate> certs = new HashSet<>();
-        if (debug != null) {
-            debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: "
-                + basicConstraints);
-        }
-
-        // basicConstraints:
-        // -2: only EE certs accepted
-        // -1: no check is done
-        //  0: any CA certificate accepted
-        // >1: certificate's basicConstraints extension pathlen must match
-        if (subject != null) {
-            if (debug != null) {
-                debug.println("LDAPCertStore.engineGetCertificates() "
-                    + "subject is not null");
-            }
-            LDAPRequest request = new LDAPRequest(subject);
-            if (basicConstraints > -2) {
-                request.addRequestedAttribute(CROSS_CERT);
-                request.addRequestedAttribute(CA_CERT);
-                request.addRequestedAttribute(ARL);
-                if (prefetchCRLs) {
-                    request.addRequestedAttribute(CRL);
-                }
-            }
-            if (basicConstraints < 0) {
-                request.addRequestedAttribute(USER_CERT);
-            }
-
-            if (basicConstraints > -2) {
-                certs.addAll(getMatchingCrossCerts(request, xsel, null));
-                if (debug != null) {
-                    debug.println("LDAPCertStore.engineGetCertificates() after "
-                        + "getMatchingCrossCerts(subject,xsel,null),certs.size(): "
-                        + certs.size());
-                }
-                certs.addAll(getCertificates(request, CA_CERT, xsel));
-                if (debug != null) {
-                    debug.println("LDAPCertStore.engineGetCertificates() after "
-                        + "getCertificates(subject,CA_CERT,xsel),certs.size(): "
-                        + certs.size());
-                }
-            }
-            if (basicConstraints < 0) {
-                certs.addAll(getCertificates(request, USER_CERT, xsel));
-                if (debug != null) {
-                    debug.println("LDAPCertStore.engineGetCertificates() after "
-                        + "getCertificates(subject,USER_CERT, xsel),certs.size(): "
-                        + certs.size());
-                }
-            }
-        } else {
-            if (debug != null) {
-                debug.println
-                    ("LDAPCertStore.engineGetCertificates() subject is null");
-            }
-            if (basicConstraints == -2) {
-                throw new CertStoreException("need subject to find EE certs");
-            }
-            if (issuer == null) {
-                throw new CertStoreException("need subject or issuer to find certs");
-            }
-        }
-        if (debug != null) {
-            debug.println("LDAPCertStore.engineGetCertificates() about to "
-                + "getMatchingCrossCerts...");
-        }
-        if ((issuer != null) && (basicConstraints > -2)) {
-            LDAPRequest request = new LDAPRequest(issuer);
-            request.addRequestedAttribute(CROSS_CERT);
-            request.addRequestedAttribute(CA_CERT);
-            request.addRequestedAttribute(ARL);
-            if (prefetchCRLs) {
-                request.addRequestedAttribute(CRL);
-            }
-
-            certs.addAll(getMatchingCrossCerts(request, null, xsel));
-            if (debug != null) {
-                debug.println("LDAPCertStore.engineGetCertificates() after "
-                    + "getMatchingCrossCerts(issuer,null,xsel),certs.size(): "
-                    + certs.size());
-            }
-            certs.addAll(getCertificates(request, CA_CERT, xsel));
-            if (debug != null) {
-                debug.println("LDAPCertStore.engineGetCertificates() after "
-                    + "getCertificates(issuer,CA_CERT,xsel),certs.size(): "
-                    + certs.size());
-            }
-        }
-        if (debug != null) {
-            debug.println("LDAPCertStore.engineGetCertificates() returning certs");
-        }
-        return certs;
-    }
-
-    /*
-     * Gets CRLs from an attribute id and location in the LDAP directory.
-     * Returns a Collection containing only the CRLs that match the
-     * specified CRLSelector.
-     *
-     * @param name the location holding the attribute
-     * @param id the attribute identifier
-     * @param sel a CRLSelector that the CRLs must match
-     * @return a Collection of CRLs found
-     * @throws CertStoreException       if an exception occurs
-     */
-    private Collection<X509CRL> getCRLs(LDAPRequest request, String id,
-            X509CRLSelector sel) throws CertStoreException {
-
-        /* fetch the encoded crls from storage */
-        byte[][] encodedCRL;
-        try {
-            encodedCRL = request.getValues(id);
-        } catch (NamingException namingEx) {
-            throw new CertStoreException(namingEx);
-        }
-
-        int n = encodedCRL.length;
-        if (n == 0) {
-            return Collections.emptySet();
-        }
-
-        List<X509CRL> crls = new ArrayList<>(n);
-        /* decode each crl and check if it matches selector */
-        for (int i = 0; i < n; i++) {
-            try {
-                CRL crl = cf.generateCRL(new ByteArrayInputStream(encodedCRL[i]));
-                if (sel.match(crl)) {
-                    crls.add((X509CRL)crl);
-                }
-            } catch (CRLException e) {
-                if (debug != null) {
-                    debug.println("LDAPCertStore.getCRLs() encountered exception"
-                        + " while parsing CRL, skipping the bad data: ");
-                    HexDumpEncoder encoder = new HexDumpEncoder();
-                    debug.println("[ " + encoder.encodeBuffer(encodedCRL[i]) + " ]");
-                }
-            }
-        }
-
-        return crls;
-    }
-
-    /**
-     * Returns a <code>Collection</code> of <code>CRL</code>s that
-     * match the specified selector. If no <code>CRL</code>s
-     * match the selector, an empty <code>Collection</code> will be returned.
-     * <p>
-     * It is not practical to search every entry in the LDAP database for
-     * matching <code>CRL</code>s. Instead, the <code>CRLSelector</code>
-     * is examined in order to determine where matching <code>CRL</code>s
-     * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
-     * If issuerNames or certChecking are specified, the issuer's directory
-     * entry is searched. If neither issuerNames or certChecking are specified
-     * (or the selector is not an <code>X509CRLSelector</code>), a
-     * <code>CertStoreException</code> is thrown.
-     *
-     * @param selector A <code>CRLSelector</code> used to select which
-     *  <code>CRL</code>s should be returned. Specify <code>null</code>
-     *  to return all <code>CRL</code>s.
-     * @return A <code>Collection</code> of <code>CRL</code>s that
-     *         match the specified selector
-     * @throws CertStoreException if an exception occurs
-     */
-    public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
-            throws CertStoreException {
-        if (debug != null) {
-            debug.println("LDAPCertStore.engineGetCRLs() selector: "
-                + selector);
-        }
-        // Set up selector and collection to hold CRLs
-        if (selector == null) {
-            selector = new X509CRLSelector();
-        }
-        if (!(selector instanceof X509CRLSelector)) {
-            throw new CertStoreException("need X509CRLSelector to find CRLs");
-        }
-        X509CRLSelector xsel = (X509CRLSelector) selector;
-        HashSet<X509CRL> crls = new HashSet<>();
-
-        // Look in directory entry for issuer of cert we're checking.
-        Collection<Object> issuerNames;
-        X509Certificate certChecking = xsel.getCertificateChecking();
-        if (certChecking != null) {
-            issuerNames = new HashSet<>();
-            X500Principal issuer = certChecking.getIssuerX500Principal();
-            issuerNames.add(issuer.getName(X500Principal.RFC2253));
-        } else {
-            // But if we don't know which cert we're checking, try the directory
-            // entries of all acceptable CRL issuers
-            issuerNames = xsel.getIssuerNames();
-            if (issuerNames == null) {
-                throw new CertStoreException("need issuerNames or certChecking to "
-                    + "find CRLs");
-            }
-        }
-        for (Object nameObject : issuerNames) {
-            String issuerName;
-            if (nameObject instanceof byte[]) {
-                try {
-                    X500Principal issuer = new X500Principal((byte[])nameObject);
-                    issuerName = issuer.getName(X500Principal.RFC2253);
-                } catch (IllegalArgumentException e) {
-                    continue;
-                }
-            } else {
-                issuerName = (String)nameObject;
-            }
-            // If all we want is CA certs, try to get the (probably shorter) ARL
-            Collection<X509CRL> entryCRLs = Collections.emptySet();
-            if (certChecking == null || certChecking.getBasicConstraints() != -1) {
-                LDAPRequest request = new LDAPRequest(issuerName);
-                request.addRequestedAttribute(CROSS_CERT);
-                request.addRequestedAttribute(CA_CERT);
-                request.addRequestedAttribute(ARL);
-                if (prefetchCRLs) {
-                    request.addRequestedAttribute(CRL);
-                }
-                try {
-                    entryCRLs = getCRLs(request, ARL, xsel);
-                    if (entryCRLs.isEmpty()) {
-                        // no ARLs found. We assume that means that there are
-                        // no ARLs on this server at all and prefetch the CRLs.
-                        prefetchCRLs = true;
-                    } else {
-                        crls.addAll(entryCRLs);
-                    }
-                } catch (CertStoreException e) {
-                    if (debug != null) {
-                        debug.println("LDAPCertStore.engineGetCRLs non-fatal error "
-                            + "retrieving ARLs:" + e);
-                        e.printStackTrace();
-                    }
-                }
-            }
-            // Otherwise, get the CRL
-            // if certChecking is null, we don't know if we should look in ARL or CRL
-            // attribute, so check both for matching CRLs.
-            if (entryCRLs.isEmpty() || certChecking == null) {
-                LDAPRequest request = new LDAPRequest(issuerName);
-                request.addRequestedAttribute(CRL);
-                entryCRLs = getCRLs(request, CRL, xsel);
-                crls.addAll(entryCRLs);
-            }
-        }
-        return crls;
-    }
-
-    // converts an LDAP URI into LDAPCertStoreParameters
-    static LDAPCertStoreParameters getParameters(URI uri) {
-        String host = uri.getHost();
-        if (host == null) {
-            return new SunLDAPCertStoreParameters();
-        } else {
-            int port = uri.getPort();
-            return (port == -1
-                    ? new SunLDAPCertStoreParameters(host)
-                    : new SunLDAPCertStoreParameters(host, port));
-        }
-    }
-
-    /*
-     * Subclass of LDAPCertStoreParameters with overridden equals/hashCode
-     * methods. This is necessary because the parameters are used as
-     * keys in the LDAPCertStore cache.
-     */
-    private static class SunLDAPCertStoreParameters
-        extends LDAPCertStoreParameters {
-
-        private volatile int hashCode = 0;
-
-        SunLDAPCertStoreParameters(String serverName, int port) {
-            super(serverName, port);
-        }
-        SunLDAPCertStoreParameters(String serverName) {
-            super(serverName);
-        }
-        SunLDAPCertStoreParameters() {
-            super();
-        }
-        public boolean equals(Object obj) {
-            if (!(obj instanceof LDAPCertStoreParameters)) {
-                return false;
-            }
-            LDAPCertStoreParameters params = (LDAPCertStoreParameters) obj;
-            return (getPort() == params.getPort() &&
-                    getServerName().equalsIgnoreCase(params.getServerName()));
-        }
-        public int hashCode() {
-            if (hashCode == 0) {
-                int result = 17;
-                result = 37*result + getPort();
-                result = 37*result +
-                    getServerName().toLowerCase(Locale.ENGLISH).hashCode();
-                hashCode = result;
-            }
-            return hashCode;
-        }
-    }
-
-    /*
-     * This inner class wraps an existing X509CertSelector and adds
-     * additional criteria to match on when the certificate's subject is
-     * different than the LDAP Distinguished Name entry. The LDAPCertStore
-     * implementation uses the subject DN as the directory entry for
-     * looking up certificates. This can be problematic if the certificates
-     * that you want to fetch have a different subject DN than the entry
-     * where they are stored. You could set the selector's subject to the
-     * LDAP DN entry, but then the resulting match would fail to find the
-     * desired certificates because the subject DNs would not match. This
-     * class avoids that problem by introducing a certSubject which should
-     * be set to the certificate's subject DN when it is different than
-     * the LDAP DN.
-     */
-    static class LDAPCertSelector extends X509CertSelector {
-
-        private X500Principal certSubject;
-        private X509CertSelector selector;
-        private X500Principal subject;
-
-        /**
-         * Creates an LDAPCertSelector.
-         *
-         * @param selector the X509CertSelector to wrap
-         * @param certSubject the subject DN of the certificate that you want
-         *      to retrieve via LDAP
-         * @param ldapDN the LDAP DN where the certificate is stored
-         */
-        LDAPCertSelector(X509CertSelector selector, X500Principal certSubject,
-            String ldapDN) throws IOException {
-            this.selector = selector == null ? new X509CertSelector() : selector;
-            this.certSubject = certSubject;
-            this.subject = new X500Name(ldapDN).asX500Principal();
-        }
-
-        // we only override the get (accessor methods) since the set methods
-        // will not be invoked by the code that uses this LDAPCertSelector.
-        public X509Certificate getCertificate() {
-            return selector.getCertificate();
-        }
-        public BigInteger getSerialNumber() {
-            return selector.getSerialNumber();
-        }
-        public X500Principal getIssuer() {
-            return selector.getIssuer();
-        }
-        public String getIssuerAsString() {
-            return selector.getIssuerAsString();
-        }
-        public byte[] getIssuerAsBytes() throws IOException {
-            return selector.getIssuerAsBytes();
-        }
-        public X500Principal getSubject() {
-            // return the ldap DN
-            return subject;
-        }
-        public String getSubjectAsString() {
-            // return the ldap DN
-            return subject.getName();
-        }
-        public byte[] getSubjectAsBytes() throws IOException {
-            // return the encoded ldap DN
-            return subject.getEncoded();
-        }
-        public byte[] getSubjectKeyIdentifier() {
-            return selector.getSubjectKeyIdentifier();
-        }
-        public byte[] getAuthorityKeyIdentifier() {
-            return selector.getAuthorityKeyIdentifier();
-        }
-        public Date getCertificateValid() {
-            return selector.getCertificateValid();
-        }
-        public Date getPrivateKeyValid() {
-            return selector.getPrivateKeyValid();
-        }
-        public String getSubjectPublicKeyAlgID() {
-            return selector.getSubjectPublicKeyAlgID();
-        }
-        public PublicKey getSubjectPublicKey() {
-            return selector.getSubjectPublicKey();
-        }
-        public boolean[] getKeyUsage() {
-            return selector.getKeyUsage();
-        }
-        public Set<String> getExtendedKeyUsage() {
-            return selector.getExtendedKeyUsage();
-        }
-        public boolean getMatchAllSubjectAltNames() {
-            return selector.getMatchAllSubjectAltNames();
-        }
-        public Collection<List<?>> getSubjectAlternativeNames() {
-            return selector.getSubjectAlternativeNames();
-        }
-        public byte[] getNameConstraints() {
-            return selector.getNameConstraints();
-        }
-        public int getBasicConstraints() {
-            return selector.getBasicConstraints();
-        }
-        public Set<String> getPolicy() {
-            return selector.getPolicy();
-        }
-        public Collection<List<?>> getPathToNames() {
-            return selector.getPathToNames();
-        }
-
-        public boolean match(Certificate cert) {
-            // temporarily set the subject criterion to the certSubject
-            // so that match will not reject the desired certificates
-            selector.setSubject(certSubject);
-            boolean match = selector.match(cert);
-            selector.setSubject(subject);
-            return match;
-        }
-    }
-
-    /**
-     * This class has the same purpose as LDAPCertSelector except it is for
-     * X.509 CRLs.
-     */
-    static class LDAPCRLSelector extends X509CRLSelector {
-
-        private X509CRLSelector selector;
-        private Collection<X500Principal> certIssuers;
-        private Collection<X500Principal> issuers;
-        private HashSet<Object> issuerNames;
-
-        /**
-         * Creates an LDAPCRLSelector.
-         *
-         * @param selector the X509CRLSelector to wrap
-         * @param certIssuers the issuer DNs of the CRLs that you want
-         *      to retrieve via LDAP
-         * @param ldapDN the LDAP DN where the CRL is stored
-         */
-        LDAPCRLSelector(X509CRLSelector selector,
-            Collection<X500Principal> certIssuers, String ldapDN)
-            throws IOException {
-            this.selector = selector == null ? new X509CRLSelector() : selector;
-            this.certIssuers = certIssuers;
-            issuerNames = new HashSet<>();
-            issuerNames.add(ldapDN);
-            issuers = new HashSet<>();
-            issuers.add(new X500Name(ldapDN).asX500Principal());
-        }
-        // we only override the get (accessor methods) since the set methods
-        // will not be invoked by the code that uses this LDAPCRLSelector.
-        public Collection<X500Principal> getIssuers() {
-            // return the ldap DN
-            return Collections.unmodifiableCollection(issuers);
-        }
-        public Collection<Object> getIssuerNames() {
-            // return the ldap DN
-            return Collections.unmodifiableCollection(issuerNames);
-        }
-        public BigInteger getMinCRL() {
-            return selector.getMinCRL();
-        }
-        public BigInteger getMaxCRL() {
-            return selector.getMaxCRL();
-        }
-        public Date getDateAndTime() {
-            return selector.getDateAndTime();
-        }
-        public X509Certificate getCertificateChecking() {
-            return selector.getCertificateChecking();
-        }
-        public boolean match(CRL crl) {
-            // temporarily set the issuer criterion to the certIssuers
-            // so that match will not reject the desired CRL
-            selector.setIssuers(certIssuers);
-            boolean match = selector.match(crl);
-            selector.setIssuers(issuers);
-            return match;
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java b/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java
deleted file mode 100644
index 8e6899b..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath.ldap;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collection;
-import java.security.NoSuchAlgorithmException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509CRLSelector;
-import javax.naming.CommunicationException;
-import javax.naming.ServiceUnavailableException;
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.provider.certpath.CertStoreHelper;
-
-/**
- * LDAP implementation of CertStoreHelper.
- */
-
-public final class LDAPCertStoreHelper
-    extends CertStoreHelper
-{
-    @Override
-    public CertStore getCertStore(URI uri)
-        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException
-    {
-        return LDAPCertStore.getInstance(LDAPCertStore.getParameters(uri));
-    }
-
-    @Override
-    public X509CertSelector wrap(X509CertSelector selector,
-                                 X500Principal certSubject,
-                                 String ldapDN)
-        throws IOException
-    {
-        return new LDAPCertStore.LDAPCertSelector(selector, certSubject, ldapDN);
-    }
-
-    @Override
-    public X509CRLSelector wrap(X509CRLSelector selector,
-                                Collection<X500Principal> certIssuers,
-                                String ldapDN)
-        throws IOException
-    {
-        return new LDAPCertStore.LDAPCRLSelector(selector, certIssuers, ldapDN);
-    }
-
-    @Override
-    public boolean isCausedByNetworkIssue(CertStoreException e) {
-        Throwable t = e.getCause();
-        return (t != null && (t instanceof ServiceUnavailableException ||
-                              t instanceof CommunicationException));
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Alerts.java b/ojluni/src/main/java/sun/security/ssl/Alerts.java
deleted file mode 100755
index 672d9b7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Alerts.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-
-/*
- * A simple class to congregate alerts, their definitions, and common
- * support methods.
- */
-
-final class Alerts {
-
-    /*
-     * Alerts are always a fixed two byte format (level/description).
-     */
-
-    // warnings and fatal errors are package private facilities/constants
-
-    // Alert levels (enum AlertLevel)
-    static final byte           alert_warning = 1;
-    static final byte           alert_fatal = 2;
-
-    /*
-     * Alert descriptions (enum AlertDescription)
-     *
-     * We may not use them all in our processing, but if someone
-     * sends us one, we can at least convert it to a string for the
-     * user.
-     */
-    static final byte           alert_close_notify = 0;
-    static final byte           alert_unexpected_message = 10;
-    static final byte           alert_bad_record_mac = 20;
-    static final byte           alert_decryption_failed = 21;
-    static final byte           alert_record_overflow = 22;
-    static final byte           alert_decompression_failure = 30;
-    static final byte           alert_handshake_failure = 40;
-    static final byte           alert_no_certificate = 41;
-    static final byte           alert_bad_certificate = 42;
-    static final byte           alert_unsupported_certificate = 43;
-    static final byte           alert_certificate_revoked = 44;
-    static final byte           alert_certificate_expired = 45;
-    static final byte           alert_certificate_unknown = 46;
-    static final byte           alert_illegal_parameter = 47;
-    static final byte           alert_unknown_ca = 48;
-    static final byte           alert_access_denied = 49;
-    static final byte           alert_decode_error = 50;
-    static final byte           alert_decrypt_error = 51;
-    static final byte           alert_export_restriction = 60;
-    static final byte           alert_protocol_version = 70;
-    static final byte           alert_insufficient_security = 71;
-    static final byte           alert_internal_error = 80;
-    static final byte           alert_user_canceled = 90;
-    static final byte           alert_no_renegotiation = 100;
-
-    // from RFC 3546 (TLS Extensions)
-    static final byte           alert_unsupported_extension = 110;
-    static final byte           alert_certificate_unobtainable = 111;
-    static final byte           alert_unrecognized_name = 112;
-    static final byte           alert_bad_certificate_status_response = 113;
-    static final byte           alert_bad_certificate_hash_value = 114;
-
-    static String alertDescription(byte code) {
-        switch (code) {
-
-        case alert_close_notify:
-            return "close_notify";
-        case alert_unexpected_message:
-            return "unexpected_message";
-        case alert_bad_record_mac:
-            return "bad_record_mac";
-        case alert_decryption_failed:
-            return "decryption_failed";
-        case alert_record_overflow:
-            return "record_overflow";
-        case alert_decompression_failure:
-            return "decompression_failure";
-        case alert_handshake_failure:
-            return "handshake_failure";
-        case alert_no_certificate:
-            return "no_certificate";
-        case alert_bad_certificate:
-            return "bad_certificate";
-        case alert_unsupported_certificate:
-            return "unsupported_certificate";
-        case alert_certificate_revoked:
-            return "certificate_revoked";
-        case alert_certificate_expired:
-            return "certificate_expired";
-        case alert_certificate_unknown:
-            return "certificate_unknown";
-        case alert_illegal_parameter:
-            return "illegal_parameter";
-        case alert_unknown_ca:
-            return "unknown_ca";
-        case alert_access_denied:
-            return "access_denied";
-        case alert_decode_error:
-            return "decode_error";
-        case alert_decrypt_error:
-            return "decrypt_error";
-        case alert_export_restriction:
-            return "export_restriction";
-        case alert_protocol_version:
-            return "protocol_version";
-        case alert_insufficient_security:
-            return "insufficient_security";
-        case alert_internal_error:
-            return "internal_error";
-        case alert_user_canceled:
-            return "user_canceled";
-        case alert_no_renegotiation:
-            return "no_renegotiation";
-        case alert_unsupported_extension:
-            return "unsupported_extension";
-        case alert_certificate_unobtainable:
-            return "certificate_unobtainable";
-        case alert_unrecognized_name:
-            return "unrecognized_name";
-        case alert_bad_certificate_status_response:
-            return "bad_certificate_status_response";
-        case alert_bad_certificate_hash_value:
-            return "bad_certificate_hash_value";
-
-        default:
-            return "<UNKNOWN ALERT: " + (code & 0x0ff) + ">";
-        }
-    }
-
-    static SSLException getSSLException(byte description, String reason) {
-        return getSSLException(description, null, reason);
-    }
-
-    /*
-     * Try to be a little more specific in our choice of
-     * exceptions to throw.
-     */
-    static SSLException getSSLException(byte description, Throwable cause,
-            String reason) {
-
-        SSLException e;
-        // the SSLException classes do not have a no-args constructor
-        // make up a message if there is none
-        if (reason == null) {
-            if (cause != null) {
-                reason = cause.toString();
-            } else {
-                reason = "";
-            }
-        }
-        switch (description) {
-        case alert_handshake_failure:
-        case alert_no_certificate:
-        case alert_bad_certificate:
-        case alert_unsupported_certificate:
-        case alert_certificate_revoked:
-        case alert_certificate_expired:
-        case alert_certificate_unknown:
-        case alert_unknown_ca:
-        case alert_access_denied:
-        case alert_decrypt_error:
-        case alert_export_restriction:
-        case alert_insufficient_security:
-        case alert_unsupported_extension:
-        case alert_certificate_unobtainable:
-        case alert_unrecognized_name:
-        case alert_bad_certificate_status_response:
-        case alert_bad_certificate_hash_value:
-            e = new SSLHandshakeException(reason);
-            break;
-
-        case alert_close_notify:
-        case alert_unexpected_message:
-        case alert_bad_record_mac:
-        case alert_decryption_failed:
-        case alert_record_overflow:
-        case alert_decompression_failure:
-        case alert_illegal_parameter:
-        case alert_decode_error:
-        case alert_protocol_version:
-        case alert_internal_error:
-        case alert_user_canceled:
-        case alert_no_renegotiation:
-        default:
-            e = new SSLException(reason);
-            break;
-        }
-
-        if (cause != null) {
-            e.initCause(cause);
-        }
-        return e;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/AppInputStream.java b/ojluni/src/main/java/sun/security/ssl/AppInputStream.java
deleted file mode 100755
index 6c47978..0000000
--- a/ojluni/src/main/java/sun/security/ssl/AppInputStream.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-
-/**
- * InputStream for application data as returned by SSLSocket.getInputStream().
- * It uses an InputRecord as internal buffer that is refilled on demand
- * whenever it runs out of data.
- *
- * @author David Brownell
- */
-class AppInputStream extends InputStream {
-
-    // static dummy array we use to implement skip()
-    private final static byte[] SKIP_ARRAY = new byte[1024];
-
-    private SSLSocketImpl c;
-    InputRecord r;
-
-    // One element array used to implement the single byte read() method
-    private final byte[] oneByte = new byte[1];
-
-    AppInputStream(SSLSocketImpl conn) {
-        r = new InputRecord();
-        c = conn;
-    }
-
-    /**
-     * Return the minimum number of bytes that can be read without blocking.
-     * Currently not synchronized.
-     */
-    public int available() throws IOException {
-        if (c.checkEOF() || (r.isAppDataValid() == false)) {
-            return 0;
-        }
-        return r.available();
-    }
-
-    /**
-     * Read a single byte, returning -1 on non-fault EOF status.
-     */
-    public synchronized int read() throws IOException {
-        int n = read(oneByte, 0, 1);
-        if (n <= 0) { // EOF
-            return -1;
-        }
-        return oneByte[0] & 0xff;
-    }
-
-    /**
-     * Read up to "len" bytes into this buffer, starting at "off".
-     * If the layer above needs more data, it asks for more, so we
-     * are responsible only for blocking to fill at most one buffer,
-     * and returning "-1" on non-fault EOF status.
-     */
-    public synchronized int read(byte b[], int off, int len)
-            throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        if (c.checkEOF()) {
-            return -1;
-        }
-        try {
-            /*
-             * Read data if needed ... notice that the connection guarantees
-             * that handshake, alert, and change cipher spec data streams are
-             * handled as they arrive, so we never see them here.
-             */
-            while (r.available() == 0) {
-                c.readDataRecord(r);
-                if (c.checkEOF()) {
-                    return -1;
-                }
-            }
-
-            int howmany = Math.min(len, r.available());
-            howmany = r.read(b, off, howmany);
-            return howmany;
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
-            // dummy for compiler
-            return -1;
-        }
-    }
-
-
-    /**
-     * Skip n bytes. This implementation is somewhat less efficient
-     * than possible, but not badly so (redundant copy). We reuse
-     * the read() code to keep things simpler. Note that SKIP_ARRAY
-     * is static and may garbled by concurrent use, but we are not interested
-     * in the data anyway.
-     */
-    public synchronized long skip(long n) throws IOException {
-        long skipped = 0;
-        while (n > 0) {
-            int len = (int)Math.min(n, SKIP_ARRAY.length);
-            int r = read(SKIP_ARRAY, 0, len);
-            if (r <= 0) {
-                break;
-            }
-            n -= r;
-            skipped += r;
-        }
-        return skipped;
-    }
-
-    /*
-     * Socket close is already synchronized, no need to block here.
-     */
-    public void close() throws IOException {
-        c.close();
-    }
-
-    // inherit default mark/reset behavior (throw Exceptions) from InputStream
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java b/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java
deleted file mode 100755
index 5082bec..0000000
--- a/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-/*
- * Output stream for application data. This is the kind of stream
- * that's handed out via SSLSocket.getOutputStream(). It's all the application
- * ever sees.
- *
- * Once the initial handshake has completed, application data may be
- * interleaved with handshake data. That is handled internally and remains
- * transparent to the application.
- *
- * @author  David Brownell
- */
-class AppOutputStream extends OutputStream {
-
-    private SSLSocketImpl c;
-    OutputRecord r;
-
-    // One element array used to implement the write(byte) method
-    private final byte[] oneByte = new byte[1];
-
-    AppOutputStream(SSLSocketImpl conn) {
-        r = new OutputRecord(Record.ct_application_data);
-        c = conn;
-    }
-
-    /**
-     * Write the data out, NOW.
-     */
-    synchronized public void write(byte b[], int off, int len)
-            throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return;
-        }
-
-        // check if the Socket is invalid (error or closed)
-        c.checkWrite();
-
-        /*
-         * By default, we counter chosen plaintext issues on CBC mode
-         * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
-         * data in the first record of every payload, and the rest in
-         * subsequent record(s). Note that the issues have been solved in
-         * TLS 1.1 or later.
-         *
-         * It is not necessary to split the very first application record of
-         * a freshly negotiated TLS session, as there is no previous
-         * application data to guess.  To improve compatibility, we will not
-         * split such records.
-         *
-         * This avoids issues in the outbound direction.  For a full fix,
-         * the peer must have similar protections.
-         */
-        boolean isFirstRecordOfThePayload = true;
-
-        // Always flush at the end of each application level record.
-        // This lets application synchronize read and write streams
-        // however they like; if we buffered here, they couldn't.
-        try {
-            do {
-                boolean holdRecord = false;
-                int howmuch;
-                if (isFirstRecordOfThePayload && c.needToSplitPayload()) {
-                    howmuch = Math.min(0x01, r.availableDataBytes());
-                    /*
-                     * Nagle's algorithm (TCP_NODELAY) was coming into
-                     * play here when writing short (split) packets.
-                     * Signal to the OutputRecord code to internally
-                     * buffer this small packet until the next outbound
-                     * packet (of any type) is written.
-                     */
-                    if ((len != 1) && (howmuch == 1)) {
-                        holdRecord = true;
-                    }
-                } else {
-                    howmuch = Math.min(len, r.availableDataBytes());
-                }
-
-                if (isFirstRecordOfThePayload && howmuch != 0) {
-                    isFirstRecordOfThePayload = false;
-                }
-
-                // NOTE: *must* call c.writeRecord() even for howmuch == 0
-                if (howmuch > 0) {
-                    r.write(b, off, howmuch);
-                    off += howmuch;
-                    len -= howmuch;
-                }
-                c.writeRecord(r, holdRecord);
-                c.checkWrite();
-            } while (len > 0);
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            c.handleException(e);
-        }
-    }
-
-    /**
-     * Write one byte now.
-     */
-    synchronized public void write(int i) throws IOException {
-        oneByte[0] = (byte)i;
-        write(oneByte, 0, 1);
-    }
-
-    /*
-     * Socket close is already synchronized, no need to block here.
-     */
-    public void close() throws IOException {
-        c.close();
-    }
-
-    // inherit no-op flush()
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java
deleted file mode 100755
index ef7503b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.channels.SocketChannel;
-import java.net.*;
-
-import javax.net.ssl.*;
-
-/**
- * Abstract base class for SSLSocketImpl. Its purpose is to house code with
- * no SSL related logic (or no logic at all). This makes SSLSocketImpl shorter
- * and easier to read. It contains a few constants and static methods plus
- * overridden java.net.Socket methods.
- *
- * Methods are defined final to ensure that they are not accidentally
- * overridden in SSLSocketImpl.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLSocketImpl
- *
- */
-abstract class BaseSSLSocketImpl extends SSLSocket {
-
-    /*
-     * Normally "self" is "this" ... but not when this connection is
-     * layered over a preexisting socket.  If we're using an existing
-     * socket, we delegate some actions to it.  Else, we delegate
-     * instead to "super".  This is important to ensure that we don't
-     * recurse infinitely ... e.g. close() calling itself, or doing
-     * I/O in terms of our own streams.
-     */
-    final Socket self;
-
-    BaseSSLSocketImpl() {
-        super();
-        this.self = this;
-    }
-
-    BaseSSLSocketImpl(Socket socket) {
-        super();
-        this.self = socket;
-    }
-
-    //
-    // CONSTANTS AND STATIC METHODS
-    //
-
-    /**
-     * TLS requires that a close_notify warning alert is sent before the
-     * connection is closed in order to avoid truncation attacks. Some
-     * implementations (MS IIS and others) don't do that. The property
-     * below controls whether we accept that or treat it as an error.
-     *
-     * The default is "false", i.e. tolerate the broken behavior.
-     */
-    private final static String PROP_NAME =
-                                "com.sun.net.ssl.requireCloseNotify";
-
-    final static boolean requireCloseNotify =
-                                Debug.getBooleanProperty(PROP_NAME, false);
-
-    //
-    // MISC SOCKET METHODS
-    //
-
-    /**
-     * Returns the unique {@link java.nio.SocketChannel SocketChannel} object
-     * associated with this socket, if any.
-     * @see java.net.Socket#getChannel
-     */
-    public final SocketChannel getChannel() {
-        if (self == this) {
-            return super.getChannel();
-        } else {
-            return self.getChannel();
-        }
-    }
-
-    /**
-     * Binds the address to the socket.
-     * @see java.net.Socket#bind
-     */
-    public void bind(SocketAddress bindpoint) throws IOException {
-        /*
-         * Bind to this socket
-         */
-        if (self == this) {
-            super.bind(bindpoint);
-        } else {
-            // If we're binding on a layered socket...
-            throw new IOException(
-                "Underlying socket should already be connected");
-        }
-    }
-
-    /**
-     * Returns the address of the endpoint this socket is connected to
-     * @see java.net.Socket#getLocalSocketAddress
-     */
-    public SocketAddress getLocalSocketAddress() {
-        if (self == this) {
-            return super.getLocalSocketAddress();
-        } else {
-            return self.getLocalSocketAddress();
-        }
-    }
-
-    /**
-     * Returns the address of the endpoint this socket is connected to
-     * @see java.net.Socket#getRemoteSocketAddress
-     */
-    public SocketAddress getRemoteSocketAddress() {
-        if (self == this) {
-            return super.getRemoteSocketAddress();
-        } else {
-            return self.getRemoteSocketAddress();
-        }
-    }
-
-    /**
-     * Connects this socket to the server.
-     *
-     * This method is either called on an unconnected SSLSocketImpl by the
-     * application, or it is called in the constructor of a regular
-     * SSLSocketImpl. If we are layering on top on another socket, then
-     * this method should not be called, because we assume that the
-     * underlying socket is already connected by the time it is passed to
-     * us.
-     *
-     * @param   endpoint the <code>SocketAddress</code>
-     * @throws  IOException if an error occurs during the connection
-     */
-    public final void connect(SocketAddress endpoint) throws IOException {
-        connect(endpoint, 0);
-    }
-
-    /**
-     * Returns the connection state of the socket.
-     * @see java.net.Socket#isConnected
-     */
-    public final boolean isConnected() {
-        if (self == this) {
-            return super.isConnected();
-        } else {
-            return self.isConnected();
-        }
-    }
-
-    /**
-     * Returns the binding state of the socket.
-     * @see java.net.Socket#isBound
-     */
-    public final boolean isBound() {
-        if (self == this) {
-            return super.isBound();
-        } else {
-            return self.isBound();
-        }
-    }
-
-    //
-    // CLOSE RELATED METHODS
-    //
-
-    /**
-     * The semantics of shutdownInput is not supported in TLS 1.0
-     * spec. Thus when the method is called on an SSL socket, an
-     * UnsupportedOperationException will be thrown.
-     *
-     * @throws UnsupportedOperationException
-     */
-    public final void shutdownInput() throws IOException {
-        throw new UnsupportedOperationException("The method shutdownInput()" +
-                   " is not supported in SSLSocket");
-    }
-
-    /**
-     * The semantics of shutdownOutput is not supported in TLS 1.0
-     * spec. Thus when the method is called on an SSL socket, an
-     * UnsupportedOperationException will be thrown.
-     *
-     * @throws UnsupportedOperationException
-     */
-    public final void shutdownOutput() throws IOException {
-        throw new UnsupportedOperationException("The method shutdownOutput()" +
-                   " is not supported in SSLSocket");
-
-    }
-
-    /**
-     * Returns the input state of the socket
-     * @see java.net.Socket#isInputShutdown
-     */
-    public final boolean isInputShutdown() {
-        if (self == this) {
-            return super.isInputShutdown();
-        } else {
-            return self.isInputShutdown();
-        }
-    }
-
-    /**
-     * Returns the output state of the socket
-     * @see java.net.Socket#isOutputShutdown
-     */
-    public final boolean isOutputShutdown() {
-        if (self == this) {
-            return super.isOutputShutdown();
-        } else {
-            return self.isOutputShutdown();
-        }
-    }
-
-    /**
-     * Ensures that the SSL connection is closed down as cleanly
-     * as possible, in case the application forgets to do so.
-     * This allows SSL connections to be implicitly reclaimed,
-     * rather than forcing them to be explicitly reclaimed at
-     * the penalty of prematurly killing SSL sessions.
-     */
-    protected final void finalize() throws Throwable {
-        try {
-            close();
-        } catch (IOException e1) {
-            try {
-                if (self == this) {
-                    super.close();
-                }
-            } catch (IOException e2) {
-                // ignore
-            }
-        } finally {
-            // We called close on the underlying socket above to
-            // make doubly sure all resources got released.  We
-            // don't finalize self in the case of overlain sockets,
-            // that's a different object which the GC will finalize
-            // separately.
-
-            super.finalize();
-        }
-    }
-
-    //
-    // GET ADDRESS METHODS
-    //
-
-    /**
-     * Returns the address of the remote peer for this connection.
-     */
-    public final InetAddress getInetAddress() {
-        if (self == this) {
-            return super.getInetAddress();
-        } else {
-            return self.getInetAddress();
-        }
-    }
-
-    /**
-     * Gets the local address to which the socket is bound.
-     *
-     * @return the local address to which the socket is bound.
-     * @since   JDK1.1
-     */
-    public final InetAddress getLocalAddress() {
-        if (self == this) {
-            return super.getLocalAddress();
-        } else {
-            return self.getLocalAddress();
-        }
-    }
-
-    /**
-     * Returns the number of the remote port that this connection uses.
-     */
-    public final int getPort() {
-        if (self == this) {
-            return super.getPort();
-        } else {
-            return self.getPort();
-        }
-    }
-
-    /**
-     * Returns the number of the local port that this connection uses.
-     */
-    public final int getLocalPort() {
-        if (self == this) {
-            return super.getLocalPort();
-        } else {
-            return self.getLocalPort();
-        }
-    }
-
-    //
-    // SOCKET OPTION METHODS
-    //
-
-    /**
-     * Enables or disables the Nagle optimization.
-     * @see java.net.Socket#setTcpNoDelay
-     */
-    public final void setTcpNoDelay(boolean value) throws SocketException {
-        if (self == this) {
-            super.setTcpNoDelay(value);
-        } else {
-            self.setTcpNoDelay(value);
-        }
-    }
-
-    /**
-     * Returns true if the Nagle optimization is disabled.  This
-     * relates to low-level buffering of TCP traffic, delaying the
-     * traffic to promote better throughput.
-     *
-     * @see java.net.Socket#getTcpNoDelay
-     */
-    public final boolean getTcpNoDelay() throws SocketException {
-        if (self == this) {
-            return super.getTcpNoDelay();
-        } else {
-            return self.getTcpNoDelay();
-        }
-    }
-
-    /**
-     * Assigns the socket's linger timeout.
-     * @see java.net.Socket#setSoLinger
-     */
-    public final void setSoLinger(boolean flag, int linger)
-            throws SocketException {
-        if (self == this) {
-            super.setSoLinger(flag, linger);
-        } else {
-            self.setSoLinger(flag, linger);
-        }
-    }
-
-    /**
-     * Returns the socket's linger timeout.
-     * @see java.net.Socket#getSoLinger
-     */
-    public final int getSoLinger() throws SocketException {
-        if (self == this) {
-            return super.getSoLinger();
-        } else {
-            return self.getSoLinger();
-        }
-    }
-
-    /**
-     * Send one byte of urgent data on the socket.
-     * @see java.net.Socket#sendUrgentData
-     * At this point, there seems to be no specific requirement to support
-     * this for an SSLSocket. An implementation can be provided if a need
-     * arises in future.
-     */
-    public final void sendUrgentData(int data) throws SocketException {
-        throw new SocketException("This method is not supported "
-                        + "by SSLSockets");
-    }
-
-    /**
-     * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
-     * option is disabled and TCP urgent data received on a socket is silently
-     * discarded.
-     * @see java.net.Socket#setOOBInline
-     * Setting OOBInline does not have any effect on SSLSocket,
-     * since currently we don't support sending urgent data.
-     */
-    public final void setOOBInline(boolean on) throws SocketException {
-        throw new SocketException("This method is ineffective, since"
-                + " sending urgent data is not supported by SSLSockets");
-    }
-
-    /**
-     * Tests if OOBINLINE is enabled.
-     * @see java.net.Socket#getOOBInline
-     */
-    public final boolean getOOBInline() throws SocketException {
-        throw new SocketException("This method is ineffective, since"
-                + " sending urgent data is not supported by SSLSockets");
-    }
-
-    /**
-     * Returns the socket timeout.
-     * @see java.net.Socket#getSoTimeout
-     */
-    public final int getSoTimeout() throws SocketException {
-        if (self == this) {
-            return super.getSoTimeout();
-        } else {
-            return self.getSoTimeout();
-        }
-    }
-
-    public final void setSendBufferSize(int size) throws SocketException {
-        if (self == this) {
-            super.setSendBufferSize(size);
-        } else {
-            self.setSendBufferSize(size);
-        }
-    }
-
-    public final int getSendBufferSize() throws SocketException {
-        if (self == this) {
-            return super.getSendBufferSize();
-        } else {
-            return self.getSendBufferSize();
-        }
-    }
-
-    public final void setReceiveBufferSize(int size) throws SocketException {
-        if (self == this) {
-            super.setReceiveBufferSize(size);
-        } else {
-            self.setReceiveBufferSize(size);
-        }
-    }
-
-    public final int getReceiveBufferSize() throws SocketException {
-        if (self == this) {
-            return super.getReceiveBufferSize();
-        } else {
-            return self.getReceiveBufferSize();
-        }
-    }
-
-    /**
-     * Enable/disable SO_KEEPALIVE.
-     * @see java.net.Socket#setKeepAlive
-     */
-    public final void setKeepAlive(boolean on) throws SocketException {
-        if (self == this) {
-            super.setKeepAlive(on);
-        } else {
-            self.setKeepAlive(on);
-        }
-    }
-
-    /**
-     * Tests if SO_KEEPALIVE is enabled.
-     * @see java.net.Socket#getKeepAlive
-     */
-    public final boolean getKeepAlive() throws SocketException {
-        if (self == this) {
-            return super.getKeepAlive();
-        } else {
-            return self.getKeepAlive();
-        }
-    }
-
-    /**
-     * Sets traffic class or type-of-service octet in the IP header for
-     * packets sent from this Socket.
-     * @see java.net.Socket#setTrafficClass
-     */
-    public final void setTrafficClass(int tc) throws SocketException {
-        if (self == this) {
-            super.setTrafficClass(tc);
-        } else {
-            self.setTrafficClass(tc);
-        }
-    }
-
-    /**
-     * Gets traffic class or type-of-service in the IP header for packets
-     * sent from this Socket.
-     * @see java.net.Socket#getTrafficClass
-     */
-    public final int getTrafficClass() throws SocketException {
-        if (self == this) {
-            return super.getTrafficClass();
-        } else {
-            return self.getTrafficClass();
-        }
-    }
-
-    /**
-     * Enable/disable SO_REUSEADDR.
-     * @see java.net.Socket#setReuseAddress
-     */
-    public final void setReuseAddress(boolean on) throws SocketException {
-        if (self == this) {
-            super.setReuseAddress(on);
-        } else {
-            self.setReuseAddress(on);
-        }
-    }
-
-    /**
-     * Tests if SO_REUSEADDR is enabled.
-     * @see java.net.Socket#getReuseAddress
-     */
-    public final boolean getReuseAddress() throws SocketException {
-        if (self == this) {
-            return super.getReuseAddress();
-        } else {
-            return self.getReuseAddress();
-        }
-    }
-
-    /**
-     * Sets performance preferences for this socket.
-     *
-     * @see java.net.Socket#setPerformancePreferences(int, int, int)
-     */
-    public void setPerformancePreferences(int connectionTime,
-            int latency, int bandwidth) {
-        if (self == this) {
-            super.setPerformancePreferences(
-                connectionTime, latency, bandwidth);
-        } else {
-            self.setPerformancePreferences(
-                connectionTime, latency, bandwidth);
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java b/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java
deleted file mode 100755
index 7191621..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-
-/**
- * A simple InputStream which uses ByteBuffers as it's backing store.
- * <P>
- * The only IOException should come if the InputStream has been closed.
- * All other IOException should not occur because all the data is local.
- * Data reads on an exhausted ByteBuffer returns a -1.
- *
- * @author  Brad Wetmore
- */
-class ByteBufferInputStream extends InputStream {
-
-    ByteBuffer bb;
-
-    ByteBufferInputStream(ByteBuffer bb) {
-        this.bb = bb;
-    }
-
-    /**
-     * Returns a byte from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    public int read() throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        if (bb.remaining() == 0) {
-            return -1;
-        }
-        return bb.get();
-    }
-
-    /**
-     * Returns a byte array from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    public int read(byte b[]) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        return read(b, 0, b.length);
-    }
-
-    /**
-     * Returns a byte array from the ByteBuffer.
-     *
-     * Increments position().
-     */
-    public int read(byte b[], int off, int len) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("read on a closed InputStream");
-        }
-
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        int length = Math.min(bb.remaining(), len);
-        if (length == 0) {
-            return -1;
-        }
-
-        bb.get(b, off, length);
-        return length;
-    }
-
-    /**
-     * Skips over and discards <code>n</code> bytes of data from this input
-     * stream.
-     */
-    public long skip(long n) throws IOException {
-
-        if (bb == null) {
-            throw new IOException("skip on a closed InputStream");
-        }
-
-        if (n <= 0) {
-            return 0;
-        }
-
-        /*
-         * ByteBuffers have at most an int, so lose the upper bits.
-         * The contract allows this.
-         */
-        int nInt = (int) n;
-        int skip = Math.min(bb.remaining(), nInt);
-
-        bb.position(bb.position() + skip);
-
-        return nInt;
-    }
-
-    /**
-     * Returns the number of bytes that can be read (or skipped over)
-     * from this input stream without blocking by the next caller of a
-     * method for this input stream.
-     */
-    public int available() throws IOException {
-
-        if (bb == null) {
-            throw new IOException("available on a closed InputStream");
-        }
-
-        return bb.remaining();
-    }
-
-    /**
-     * Closes this input stream and releases any system resources associated
-     * with the stream.
-     *
-     * @exception  IOException  if an I/O error occurs.
-     */
-    public void close() throws IOException {
-        bb = null;
-    }
-
-    /**
-     * Marks the current position in this input stream.
-     */
-    public synchronized void mark(int readlimit) {}
-
-    /**
-     * Repositions this stream to the position at the time the
-     * <code>mark</code> method was last called on this input stream.
-     */
-    public synchronized void reset() throws IOException {
-        throw new IOException("mark/reset not supported");
-    }
-
-    /**
-     * Tests if this input stream supports the <code>mark</code> and
-     * <code>reset</code> methods.
-     */
-    public boolean markSupported() {
-        return false;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherBox.java b/ojluni/src/main/java/sun/security/ssl/CipherBox.java
deleted file mode 100755
index 4dfbadd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherBox.java
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Hashtable;
-
-import java.security.*;
-import javax.crypto.*;
-import javax.crypto.spec.SecretKeySpec;
-import javax.crypto.spec.IvParameterSpec;
-
-import java.nio.*;
-
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * This class handles bulk data enciphering/deciphering for each SSLv3
- * message.  This provides data confidentiality.  Stream ciphers (such
- * as RC4) don't need to do padding; block ciphers (e.g. DES) need it.
- *
- * Individual instances are obtained by calling the static method
- * newCipherBox(), which should only be invoked by BulkCipher.newCipher().
- *
- * In RFC 2246, with bock ciphers in CBC mode, the Initialization
- * Vector (IV) for the first record is generated with the other keys
- * and secrets when the security parameters are set.  The IV for
- * subsequent records is the last ciphertext block from the previous
- * record.
- *
- * In RFC 4346, the implicit Initialization Vector (IV) is replaced
- * with an explicit IV to protect against CBC attacks.  RFC 4346
- * recommends two algorithms used to generated the per-record IV.
- * The implementation uses the algorithm (2)(b), as described at
- * section 6.2.3.2 of RFC 4346.
- *
- * The usage of IV in CBC block cipher can be illustrated in
- * the following diagrams.
- *
- *   (random)
- *        R         P1                    IV        C1
- *        |          |                     |         |
- *  SIV---+    |-----+    |-...            |-----    |------
- *        |    |     |    |                |    |    |     |
- *     +----+  |  +----+  |             +----+  |  +----+  |
- *     | Ek |  |  + Ek +  |             | Dk |  |  | Dk |  |
- *     +----+  |  +----+  |             +----+  |  +----+  |
- *        |    |     |    |                |    |    |     |
- *        |----|     |----|           SIV--+    |----|     |-...
- *        |          |                     |       |
- *       IV         C1                     R      P1
- *                                     (discard)
- *
- *       CBC Encryption                    CBC Decryption
- *
- * NOTE that any ciphering involved in key exchange (e.g. with RSA) is
- * handled separately.
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class CipherBox {
-
-    // A CipherBox that implements the identity operation
-    final static CipherBox NULL = new CipherBox();
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    // the protocol version this cipher conforms to
-    private final ProtocolVersion protocolVersion;
-
-    // cipher object
-    private final Cipher cipher;
-
-    /**
-     * Cipher blocksize, 0 for stream ciphers
-     */
-    private int blockSize;
-
-    /**
-     * secure random
-     */
-    private SecureRandom random;
-
-    /**
-     * Is the cipher of CBC mode?
-     */
-    private final boolean isCBCMode;
-
-    /**
-     * Fixed masks of various block size, as the initial decryption IVs
-     * for TLS 1.1 or later.
-     *
-     * For performance, we do not use random IVs. As the initial decryption
-     * IVs will be discarded by TLS decryption processes, so the fixed masks
-     * do not hurt cryptographic strength.
-     */
-    private static Hashtable<Integer, IvParameterSpec> masks;
-
-    /**
-     * NULL cipherbox. Identity operation, no encryption.
-     */
-    private CipherBox() {
-        this.protocolVersion = ProtocolVersion.DEFAULT;
-        this.cipher = null;
-        this.isCBCMode = false;
-    }
-
-    /**
-     * Construct a new CipherBox using the cipher transformation.
-     *
-     * @exception NoSuchAlgorithmException if no appropriate JCE Cipher
-     * implementation could be found.
-     */
-    private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
-            SecretKey key, IvParameterSpec iv, SecureRandom random,
-            boolean encrypt) throws NoSuchAlgorithmException {
-        try {
-            this.protocolVersion = protocolVersion;
-            this.cipher = JsseJce.getCipher(bulkCipher.transformation);
-            int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-
-            if (random == null) {
-                random = JsseJce.getSecureRandom();
-            }
-            this.random = random;
-            this.isCBCMode = bulkCipher.isCBCMode;
-
-            /*
-             * RFC 4346 recommends two algorithms used to generated the
-             * per-record IV. The implementation uses the algorithm (2)(b),
-             * as described at section 6.2.3.2 of RFC 4346.
-             *
-             * As we don't care about the initial IV value for TLS 1.1 or
-             * later, so if the "iv" parameter is null, we use the default
-             * value generated by Cipher.init() for encryption, and a fixed
-             * mask for decryption.
-             */
-            if (iv == null && bulkCipher.ivSize != 0 &&
-                    mode == Cipher.DECRYPT_MODE &&
-                    protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                iv = getFixedMask(bulkCipher.ivSize);
-            }
-
-            cipher.init(mode, key, iv, random);
-
-            // Do not call getBlockSize until after init()
-            // otherwise we would disrupt JCE delayed provider selection
-            blockSize = cipher.getBlockSize();
-            // some providers implement getBlockSize() incorrectly
-            if (blockSize == 1) {
-                blockSize = 0;
-            }
-        } catch (NoSuchAlgorithmException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new NoSuchAlgorithmException
-                    ("Could not create cipher " + bulkCipher, e);
-        } catch (ExceptionInInitializerError e) {
-            throw new NoSuchAlgorithmException
-                    ("Could not create cipher " + bulkCipher, e);
-        }
-    }
-
-    /*
-     * Factory method to obtain a new CipherBox object.
-     */
-    static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
-            SecretKey key, IvParameterSpec iv, SecureRandom random,
-            boolean encrypt) throws NoSuchAlgorithmException {
-        if (cipher.allowed == false) {
-            throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
-        }
-
-        if (cipher == B_NULL) {
-            return NULL;
-        } else {
-            return new CipherBox(version, cipher, key, iv, random, encrypt);
-        }
-    }
-
-    /*
-     * Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
-     */
-    private static IvParameterSpec getFixedMask(int ivSize) {
-        if (masks == null) {
-            masks = new Hashtable<Integer, IvParameterSpec>(5);
-        }
-
-        IvParameterSpec iv = masks.get(ivSize);
-        if (iv == null) {
-            iv = new IvParameterSpec(new byte[ivSize]);
-            masks.put(ivSize, iv);
-        }
-
-        return iv;
-    }
-
-    /*
-     * Encrypts a block of data, returning the size of the
-     * resulting block.
-     */
-    int encrypt(byte[] buf, int offset, int len) {
-        if (cipher == null) {
-            return len;
-        }
-
-        try {
-            if (blockSize != 0) {
-                // TLSv1.1 needs a IV block
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    // generate a random number
-                    byte[] prefix = new byte[blockSize];
-                    random.nextBytes(prefix);
-
-                    // move forward the plaintext
-                    System.arraycopy(buf, offset,
-                                     buf, offset + prefix.length, len);
-
-                    // prefix the plaintext
-                    System.arraycopy(prefix, 0,
-                                     buf, offset, prefix.length);
-
-                    len += prefix.length;
-                }
-
-                len = addPadding(buf, offset, len, blockSize);
-            }
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext before ENCRYPTION:  len = "
-                        + len);
-                    hd.encodeBuffer(
-                        new ByteArrayInputStream(buf, offset, len),
-                        System.out);
-                } catch (IOException e) { }
-            }
-            int newLen = cipher.update(buf, offset, len, buf, offset);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            throw new ArrayIndexOutOfBoundsException(e.toString());
-        }
-    }
-
-    /*
-     * Encrypts a ByteBuffer block of data, returning the size of the
-     * resulting block.
-     *
-     * The byte buffers position and limit initially define the amount
-     * to encrypt.  On return, the position and limit are
-     * set to last position padded/encrypted.  The limit may have changed
-     * because of the added padding bytes.
-     */
-    int encrypt(ByteBuffer bb) {
-
-        int len = bb.remaining();
-
-        if (cipher == null) {
-            bb.position(bb.limit());
-            return len;
-        }
-
-        try {
-            int pos = bb.position();
-
-            if (blockSize != 0) {
-                // TLSv1.1 needs a IV block
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    // generate a random number
-                    byte[] prefix = new byte[blockSize];
-                    random.nextBytes(prefix);
-
-                    // move forward the plaintext
-                    byte[] buf = null;
-                    int limit = bb.limit();
-                    if (bb.hasArray()) {
-                        int arrayOffset = bb.arrayOffset();
-                        buf = bb.array();
-                        System.arraycopy(buf, arrayOffset + pos,
-                            buf, arrayOffset + pos + prefix.length,
-                            limit - pos);
-                        bb.limit(limit + prefix.length);
-                    } else {
-                        buf = new byte[limit - pos];
-                        bb.get(buf, 0, limit - pos);
-                        bb.position(pos + prefix.length);
-                        bb.limit(limit + prefix.length);
-                        bb.put(buf);
-                    }
-                    bb.position(pos);
-
-                    // prefix the plaintext
-                    bb.put(prefix);
-                    bb.position(pos);
-                }
-
-                // addPadding adjusts pos/limit
-                len = addPadding(bb, blockSize);
-                bb.position(pos);
-            }
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext before ENCRYPTION:  len = "
-                        + len);
-                    hd.encodeBuffer(bb, System.out);
-
-                } catch (IOException e) { }
-                /*
-                 * reset back to beginning
-                 */
-                bb.position(pos);
-            }
-
-            /*
-             * Encrypt "in-place".  This does not add its own padding.
-             */
-            ByteBuffer dup = bb.duplicate();
-            int newLen = cipher.update(dup, bb);
-
-            if (bb.position() != dup.position()) {
-                throw new RuntimeException("bytebuffer padding error");
-            }
-
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            RuntimeException exc = new RuntimeException(e.toString());
-            exc.initCause(e);
-            throw exc;
-        }
-    }
-
-
-    /*
-     * Decrypts a block of data, returning the size of the
-     * resulting block if padding was required.
-     *
-     * For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
-     * Initialization Vector (IV) for the first record is generated by
-     * the handshake protocol, the IV for subsequent records is the
-     * last ciphertext block from the previous record.
-     *
-     * From TLSv1.1, the implicit IV is replaced with an explicit IV to
-     * protect against CBC attacks.
-     *
-     * Differentiating between bad_record_mac and decryption_failed alerts
-     * may permit certain attacks against CBC mode. It is preferable to
-     * uniformly use the bad_record_mac alert to hide the specific type of
-     * the error.
-     */
-    int decrypt(byte[] buf, int offset, int len,
-            int tagLen) throws BadPaddingException {
-        if (cipher == null) {
-            return len;
-        }
-
-        try {
-            int newLen = cipher.update(buf, offset, len, buf, offset);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext after DECRYPTION:  len = "
-                        + newLen);
-                    hd.encodeBuffer(
-                        new ByteArrayInputStream(buf, offset, newLen),
-                        System.out);
-                } catch (IOException e) { }
-            }
-
-            if (blockSize != 0) {
-                newLen = removePadding(
-                    buf, offset, newLen, tagLen, blockSize, protocolVersion);
-
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    if (newLen < blockSize) {
-                        throw new BadPaddingException("invalid explicit IV");
-                    }
-
-                    // discards the first cipher block, the IV component.
-                    System.arraycopy(buf, offset + blockSize,
-                                     buf, offset, newLen - blockSize);
-
-                    newLen -= blockSize;
-                }
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            throw new ArrayIndexOutOfBoundsException(e.toString());
-        }
-    }
-
-
-    /*
-     * Decrypts a block of data, returning the size of the
-     * resulting block if padding was required.  position and limit
-     * point to the end of the decrypted/depadded data.  The initial
-     * limit and new limit may be different, given we may
-     * have stripped off some padding bytes.
-     *
-     *  @see decrypt(byte[], int, int)
-     */
-    int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
-
-        int len = bb.remaining();
-
-        if (cipher == null) {
-            bb.position(bb.limit());
-            return len;
-        }
-
-        try {
-            /*
-             * Decrypt "in-place".
-             */
-            int pos = bb.position();
-            ByteBuffer dup = bb.duplicate();
-            int newLen = cipher.update(dup, bb);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
-            }
-
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext after DECRYPTION:  len = "
-                        + newLen);
-
-                    hd.encodeBuffer(
-                        (ByteBuffer)bb.duplicate().position(pos), System.out);
-                } catch (IOException e) { }
-            }
-
-            /*
-             * Remove the block padding.
-             */
-            if (blockSize != 0) {
-                bb.position(pos);
-                newLen = removePadding(
-                    bb, tagLen, blockSize, protocolVersion);
-
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    if (newLen < blockSize) {
-                        throw new BadPaddingException("invalid explicit IV");
-                    }
-
-                    // discards the first cipher block, the IV component.
-                    byte[] buf = null;
-                    int limit = bb.limit();
-                    if (bb.hasArray()) {
-                        int arrayOffset = bb.arrayOffset();
-                        buf = bb.array();
-                        System.arraycopy(buf, arrayOffset + pos + blockSize,
-                            buf, arrayOffset + pos, limit - pos - blockSize);
-                        bb.limit(limit - blockSize);
-                    } else {
-                        buf = new byte[limit - pos - blockSize];
-                        bb.position(pos + blockSize);
-                        bb.get(buf);
-                        bb.position(pos);
-                        bb.put(buf);
-                        bb.limit(limit - blockSize);
-                    }
-
-                    // reset the position to the end of the decrypted data
-                    limit = bb.limit();
-                    bb.position(limit);
-                }
-            }
-            return newLen;
-        } catch (ShortBufferException e) {
-            RuntimeException exc = new RuntimeException(e.toString());
-            exc.initCause(e);
-            throw exc;
-        }
-    }
-
-    private static int addPadding(byte[] buf, int offset, int len,
-            int blockSize) {
-        int     newlen = len + 1;
-        byte    pad;
-        int     i;
-
-        if ((newlen % blockSize) != 0) {
-            newlen += blockSize - 1;
-            newlen -= newlen % blockSize;
-        }
-        pad = (byte) (newlen - len);
-
-        if (buf.length < (newlen + offset)) {
-            throw new IllegalArgumentException("no space to pad buffer");
-        }
-
-        /*
-         * TLS version of the padding works for both SSLv3 and TLSv1
-         */
-        for (i = 0, offset += len; i < pad; i++) {
-            buf [offset++] = (byte) (pad - 1);
-        }
-        return newlen;
-    }
-
-    /*
-     * Apply the padding to the buffer.
-     *
-     * Limit is advanced to the new buffer length.
-     * Position is equal to limit.
-     */
-    private static int addPadding(ByteBuffer bb, int blockSize) {
-
-        int     len = bb.remaining();
-        int     offset = bb.position();
-
-        int     newlen = len + 1;
-        byte    pad;
-        int     i;
-
-        if ((newlen % blockSize) != 0) {
-            newlen += blockSize - 1;
-            newlen -= newlen % blockSize;
-        }
-        pad = (byte) (newlen - len);
-
-        /*
-         * Update the limit to what will be padded.
-         */
-        bb.limit(newlen + offset);
-
-        /*
-         * TLS version of the padding works for both SSLv3 and TLSv1
-         */
-        for (i = 0, offset += len; i < pad; i++) {
-            bb.put(offset++, (byte) (pad - 1));
-        }
-
-        bb.position(offset);
-        bb.limit(offset);
-
-        return newlen;
-    }
-
-    /*
-     * A constant-time check of the padding.
-     *
-     * NOTE that we are checking both the padding and the padLen bytes here.
-     *
-     * The caller MUST ensure that the len parameter is a positive number.
-     */
-    private static int[] checkPadding(
-            byte[] buf, int offset, int len, byte pad) {
-
-        if (len <= 0) {
-            throw new RuntimeException("padding len must be positive");
-        }
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-        for (int i = 0; i <= 256;) {
-            for (int j = 0; j < len && i <= 256; j++, i++) {     // j <= i
-                if (buf[offset + j] != pad) {
-                    results[0]++;       // mismatched padding data
-                } else {
-                    results[1]++;       // matched padding data
-                }
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * A constant-time check of the padding.
-     *
-     * NOTE that we are checking both the padding and the padLen bytes here.
-     *
-     * The caller MUST ensure that the bb parameter has remaining.
-     */
-    private static int[] checkPadding(ByteBuffer bb, byte pad) {
-
-        if (!bb.hasRemaining()) {
-            throw new RuntimeException("hasRemaining() must be positive");
-        }
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-        bb.mark();
-        for (int i = 0; i <= 256; bb.reset()) {
-            for (; bb.hasRemaining() && i <= 256; i++) {
-                if (bb.get() != pad) {
-                    results[0]++;       // mismatched padding data
-                } else {
-                    results[1]++;       // matched padding data
-                }
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Typical TLS padding format for a 64 bit block cipher is as follows:
-     *   xx xx xx xx xx xx xx 00
-     *   xx xx xx xx xx xx 01 01
-     *   ...
-     *   xx 06 06 06 06 06 06 06
-     *   07 07 07 07 07 07 07 07
-     * TLS also allows any amount of padding from 1 and 256 bytes as long
-     * as it makes the data a multiple of the block size
-     */
-    private static int removePadding(byte[] buf, int offset, int len,
-            int tagLen, int blockSize,
-            ProtocolVersion protocolVersion) throws BadPaddingException {
-
-        // last byte is length byte (i.e. actual padding length - 1)
-        int padOffset = offset + len - 1;
-        int padLen = buf[padOffset] & 0xFF;
-
-        int newLen = len - (padLen + 1);
-        if ((newLen - tagLen) < 0) {
-            // If the buffer is not long enough to contain the padding plus
-            // a MAC tag, do a dummy constant-time padding check.
-            //
-            // Note that it is a dummy check, so we won't care about what is
-            // the actual padding data.
-            checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
-
-            throw new BadPaddingException("Invalid Padding length: " + padLen);
-        }
-
-        // The padding data should be filled with the padding length value.
-        int[] results = checkPadding(buf, offset + newLen,
-                        padLen + 1, (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            if (results[0] != 0) {          // padding data has invalid bytes
-                throw new BadPaddingException("Invalid TLS padding data");
-            }
-        } else { // SSLv3
-            // SSLv3 requires 0 <= length byte < block size
-            // some implementations do 1 <= length byte <= block size,
-            // so accept that as well
-            // v3 does not require any particular value for the other bytes
-            if (padLen > blockSize) {
-                throw new BadPaddingException("Invalid SSLv3 padding");
-            }
-        }
-        return newLen;
-    }
-
-    /*
-     * Position/limit is equal the removed padding.
-     */
-    private static int removePadding(ByteBuffer bb,
-            int tagLen, int blockSize,
-            ProtocolVersion protocolVersion) throws BadPaddingException {
-
-        int len = bb.remaining();
-        int offset = bb.position();
-
-        // last byte is length byte (i.e. actual padding length - 1)
-        int padOffset = offset + len - 1;
-        int padLen = bb.get(padOffset) & 0xFF;
-
-        int newLen = len - (padLen + 1);
-        if ((newLen - tagLen) < 0) {
-            // If the buffer is not long enough to contain the padding plus
-            // a MAC tag, do a dummy constant-time padding check.
-            //
-            // Note that it is a dummy check, so we won't care about what is
-            // the actual padding data.
-            checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
-
-            throw new BadPaddingException("Invalid Padding length: " + padLen);
-        }
-
-        // The padding data should be filled with the padding length value.
-        int[] results = checkPadding(
-                (ByteBuffer)bb.duplicate().position(offset + newLen),
-                (byte)(padLen & 0xFF));
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            if (results[0] != 0) {          // padding data has invalid bytes
-                throw new BadPaddingException("Invalid TLS padding data");
-            }
-        } else { // SSLv3
-            // SSLv3 requires 0 <= length byte < block size
-            // some implementations do 1 <= length byte <= block size,
-            // so accept that as well
-            // v3 does not require any particular value for the other bytes
-            if (padLen > blockSize) {
-                throw new BadPaddingException("Invalid SSLv3 padding");
-            }
-        }
-
-        /*
-         * Reset buffer limit to remove padding.
-         */
-        bb.position(offset + newLen);
-        bb.limit(offset + newLen);
-
-        return newLen;
-    }
-
-    /*
-     * Dispose of any intermediate state in the underlying cipher.
-     * For PKCS11 ciphers, this will release any attached sessions, and
-     * thus make finalization faster.
-     */
-    void dispose() {
-        try {
-            if (cipher != null) {
-                // ignore return value.
-                cipher.doFinal();
-            }
-        } catch (GeneralSecurityException e) {
-            // swallow for now.
-        }
-    }
-
-    /*
-     * Does the cipher use CBC mode?
-     *
-     * @return true if the cipher use CBC mode, false otherwise.
-     */
-    boolean isCBCMode() {
-        return isCBCMode;
-    }
-
-    /**
-     * Is the cipher null?
-     *
-     * @return true if the cipher is null, false otherwise.
-     */
-    boolean isNullCipher() {
-        return cipher == null;
-    }
-
-    /**
-     * Sanity check the length of a fragment before decryption.
-     *
-     * In CBC mode, check that the fragment length is one or multiple times
-     * of the block size of the cipher suite, and is at least one (one is the
-     * smallest size of padding in CBC mode) bigger than the tag size of the
-     * MAC algorithm except the explicit IV size for TLS 1.1 or later.
-     *
-     * In non-CBC mode, check that the fragment length is not less than the
-     * tag size of the MAC algorithm.
-     *
-     * @return true if the length of a fragment matches above requirements
-     */
-    boolean sanityCheck(int tagLen, int fragmentLen) {
-        if (!isCBCMode) {
-            return fragmentLen >= tagLen;
-        }
-
-        if ((fragmentLen % blockSize) == 0) {
-            int minimal = tagLen + 1;
-            minimal = (minimal >= blockSize) ? minimal : blockSize;
-            if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                minimal += blockSize;   // plus the size of the explicit IV
-            }
-
-            return (fragmentLen >= minimal);
-        }
-
-        return false;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherSuite.java b/ojluni/src/main/java/sun/security/ssl/CipherSuite.java
deleted file mode 100755
index 3bf67fa..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherSuite.java
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.*;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.JsseJce.*;
-
-/**
- * An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
- * and mac algorithms are also defined in this class.
- *
- * The CipherSuite class and the inner classes defined in this file roughly
- * follow the type safe enum pattern described in Effective Java. This means:
- *
- *  . instances are immutable, classes are final
- *
- *  . there is a unique instance of every value, i.e. there are never two
- *    instances representing the same CipherSuite, etc. This means equality
- *    tests can be performed using == instead of equals() (although that works
- *    as well). [A minor exception are *unsupported* CipherSuites read from a
- *    handshake message, but this is usually irrelevant]
- *
- *  . instances are obtained using the static valueOf() factory methods.
- *
- *  . properties are defined as final variables and made available as
- *    package private variables without method accessors
- *
- *  . if the member variable allowed is false, the given algorithm is either
- *    unavailable or disabled at compile time
- *
- */
-final class CipherSuite implements Comparable {
-
-    // minimum priority for supported CipherSuites
-    final static int SUPPORTED_SUITES_PRIORITY = 1;
-
-    // minimum priority for default enabled CipherSuites
-    final static int DEFAULT_SUITES_PRIORITY = 300;
-
-    // Flag indicating if CipherSuite availability can change dynamically.
-    // This is the case when we rely on a JCE cipher implementation that
-    // may not be available in the installed JCE providers.
-    // It is true because we might not have an ECC implementation.
-    final static boolean DYNAMIC_AVAILABILITY = true;
-
-    private final static boolean ALLOW_ECC = Debug.getBooleanProperty
-        ("com.sun.net.ssl.enableECC", true);
-
-    // Map Integer(id) -> CipherSuite
-    // contains all known CipherSuites
-    private final static Map<Integer,CipherSuite> idMap;
-
-    // Map String(name) -> CipherSuite
-    // contains only supported CipherSuites (i.e. allowed == true)
-    private final static Map<String,CipherSuite> nameMap;
-
-    // Protocol defined CipherSuite name, e.g. SSL_RSA_WITH_RC4_128_MD5
-    // we use TLS_* only for new CipherSuites, still SSL_* for old ones
-    final String name;
-
-    // id in 16 bit MSB format, i.e. 0x0004 for SSL_RSA_WITH_RC4_128_MD5
-    final int id;
-
-    // priority for the internal default preference order. the higher the
-    // better. Each supported CipherSuite *must* have a unique priority.
-    // Ciphersuites with priority >= DEFAULT_SUITES_PRIORITY are enabled
-    // by default
-    final int priority;
-
-    // key exchange, bulk cipher, mac and prf algorithms. See those
-    // classes below.
-    final KeyExchange keyExchange;
-    final BulkCipher cipher;
-    final MacAlg macAlg;
-    final PRF prfAlg;
-
-    // whether a CipherSuite qualifies as exportable under 512/40 bit rules.
-    // TLS 1.1+ (RFC 4346) must not negotiate to these suites.
-    final boolean exportable;
-
-    // true iff implemented and enabled at compile time
-    final boolean allowed;
-
-    // obsoleted since protocol version
-    final int obsoleted;
-
-    // supported since protocol version
-    final int supported;
-
-    /**
-     * Constructor for implemented CipherSuites.
-     */
-    private CipherSuite(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted, int supported, PRF prfAlg) {
-        this.name = name;
-        this.id = id;
-        this.priority = priority;
-        this.keyExchange = keyExchange;
-        this.cipher = cipher;
-        this.exportable = cipher.exportable;
-        if (name.endsWith("_MD5")) {
-            macAlg = M_MD5;
-        } else if (name.endsWith("_SHA")) {
-            macAlg = M_SHA;
-        } else if (name.endsWith("_SHA256")) {
-            macAlg = M_SHA256;
-        } else if (name.endsWith("_SHA384")) {
-            macAlg = M_SHA384;
-        } else if (name.endsWith("_NULL")) {
-            macAlg = M_NULL;
-        } else if (name.endsWith("_SCSV")) {
-            macAlg = M_NULL;
-        } else {
-            throw new IllegalArgumentException
-                    ("Unknown MAC algorithm for ciphersuite " + name);
-        }
-
-        allowed &= keyExchange.allowed;
-        allowed &= cipher.allowed;
-        this.allowed = allowed;
-        this.obsoleted = obsoleted;
-        this.supported = supported;
-        this.prfAlg = prfAlg;
-    }
-
-    /**
-     * Constructor for unimplemented CipherSuites.
-     */
-    private CipherSuite(String name, int id) {
-        this.name = name;
-        this.id = id;
-        this.allowed = false;
-
-        this.priority = 0;
-        this.keyExchange = null;
-        this.cipher = null;
-        this.macAlg = null;
-        this.exportable = false;
-        this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
-        this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
-        this.prfAlg = P_NONE;
-    }
-
-    /**
-     * Return whether this CipherSuite is available for use. A
-     * CipherSuite may be unavailable even if it is supported
-     * (i.e. allowed == true) if the required JCE cipher is not installed.
-     * In some configuration, this situation may change over time, call
-     * CipherSuiteList.clearAvailableCache() before this method to obtain
-     * the most current status.
-     */
-    boolean isAvailable() {
-        return allowed && keyExchange.isAvailable() && cipher.isAvailable();
-    }
-
-    boolean isNegotiable() {
-        return this != C_SCSV && isAvailable();
-    }
-
-    /**
-     * Compares CipherSuites based on their priority. Has the effect of
-     * sorting CipherSuites when put in a sorted collection, which is
-     * used by CipherSuiteList. Follows standard Comparable contract.
-     *
-     * Note that for unsupported CipherSuites parsed from a handshake
-     * message we violate the equals() contract.
-     */
-    public int compareTo(Object o) {
-        return ((CipherSuite)o).priority - priority;
-    }
-
-    /**
-     * Returns this.name.
-     */
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * Return a CipherSuite for the given name. The returned CipherSuite
-     * is supported by this implementation but may not actually be
-     * currently useable. See isAvailable().
-     *
-     * @exception IllegalArgumentException if the CipherSuite is unknown or
-     * unsupported.
-     */
-    static CipherSuite valueOf(String s) {
-        if (s == null) {
-            throw new IllegalArgumentException("Name must not be null");
-        }
-
-        CipherSuite c = nameMap.get(s);
-        if ((c == null) || (c.allowed == false)) {
-            throw new IllegalArgumentException("Unsupported ciphersuite " + s);
-        }
-
-        return c;
-    }
-
-    /**
-     * Return a CipherSuite with the given ID. A temporary object is
-     * constructed if the ID is unknown. Use isAvailable() to verify that
-     * the CipherSuite can actually be used.
-     */
-    static CipherSuite valueOf(int id1, int id2) {
-        id1 &= 0xff;
-        id2 &= 0xff;
-        int id = (id1 << 8) | id2;
-        CipherSuite c = idMap.get(id);
-        if (c == null) {
-            String h1 = Integer.toString(id1, 16);
-            String h2 = Integer.toString(id2, 16);
-            c = new CipherSuite("Unknown 0x" + h1 + ":0x" + h2, id);
-        }
-        return c;
-    }
-
-    // for use by CipherSuiteList only
-    static Collection<CipherSuite> allowedCipherSuites() {
-        return nameMap.values();
-    }
-
-    /*
-     * Use this method when all of the values need to be specified.
-     * This is primarily used when defining a new ciphersuite for
-     * TLS 1.2+ that doesn't use the "default" PRF.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted, int supported, PRF prf) {
-
-        CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
-            cipher, allowed, obsoleted, supported, prf);
-        if (idMap.put(id, c) != null) {
-            throw new RuntimeException("Duplicate ciphersuite definition: "
-                                        + id + ", " + name);
-        }
-        if (c.allowed) {
-            if (nameMap.put(name, c) != null) {
-                throw new RuntimeException("Duplicate ciphersuite definition: "
-                                            + id + ", " + name);
-            }
-        }
-    }
-
-    /*
-     * Use this method when there is no lower protocol limit where this
-     * suite can be used, and the PRF is P_SHA256.  That is, the
-     * existing ciphersuites.  From RFC 5246:
-     *
-     *     All cipher suites in this document use P_SHA256.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher,
-            boolean allowed, int obsoleted) {
-        // If this is an obsoleted suite, then don't let the TLS 1.2
-        // protocol have a valid PRF value.
-        PRF prf = P_SHA256;
-        if (obsoleted < ProtocolVersion.TLS12.v) {
-            prf = P_NONE;
-        }
-
-        add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
-            ProtocolVersion.LIMIT_MIN_VALUE, prf);
-    }
-
-    /*
-     * Use this method when there is no upper protocol limit.  That is,
-     * suites which have not been obsoleted.
-     */
-    private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
-        add(name, id, priority, keyExchange,
-            cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
-    }
-
-    /*
-     * Use this method to define an unimplemented suite.  This provides
-     * a number<->name mapping that can be used for debugging.
-     */
-    private static void add(String name, int id) {
-        CipherSuite c = new CipherSuite(name, id);
-        if (idMap.put(id, c) != null) {
-            throw new RuntimeException("Duplicate ciphersuite definition: "
-                                        + id + ", " + name);
-        }
-    }
-
-    /**
-     * An SSL/TLS key exchange algorithm.
-     */
-    static enum KeyExchange {
-
-        // key exchange algorithms
-        K_NULL       ("NULL",       false),
-        K_RSA        ("RSA",        true),
-        K_RSA_EXPORT ("RSA_EXPORT", true),
-        K_DH_RSA     ("DH_RSA",     false),
-        K_DH_DSS     ("DH_DSS",     false),
-        K_DHE_DSS    ("DHE_DSS",    true),
-        K_DHE_RSA    ("DHE_RSA",    true),
-        K_DH_ANON    ("DH_anon",    true),
-
-        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC),
-        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC),
-        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC),
-        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC),
-        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC),
-
-        // Kerberos cipher suites
-        K_KRB5       ("KRB5", true),
-        K_KRB5_EXPORT("KRB5_EXPORT", true),
-
-        // renegotiation protection request signaling cipher suite
-        K_SCSV       ("SCSV",        true);
-
-        // name of the key exchange algorithm, e.g. DHE_DSS
-        final String name;
-        final boolean allowed;
-        private final boolean alwaysAvailable;
-
-        KeyExchange(String name, boolean allowed) {
-            this.name = name;
-            this.allowed = allowed;
-            this.alwaysAvailable = allowed &&
-                (!name.startsWith("EC")) && (!name.startsWith("KRB"));
-        }
-
-        boolean isAvailable() {
-            if (alwaysAvailable) {
-                return true;
-            }
-
-            if (name.startsWith("EC")) {
-                return (allowed && JsseJce.isEcAvailable());
-            } else if (name.startsWith("KRB")) {
-                return (allowed && JsseJce.isKerberosAvailable());
-            } else {
-                return allowed;
-            }
-        }
-
-        public String toString() {
-            return name;
-        }
-    }
-
-    /**
-     * An SSL/TLS bulk cipher algorithm. One instance per combination of
-     * cipher and key length.
-     *
-     * Also contains a factory method to obtain in initialized CipherBox
-     * for this algorithm.
-     */
-    final static class BulkCipher {
-
-        // Map BulkCipher -> Boolean(available)
-        private final static Map<BulkCipher,Boolean> availableCache =
-                                            new HashMap<>(8);
-
-        // descriptive name including key size, e.g. AES/128
-        final String description;
-
-        // JCE cipher transformation string, e.g. AES/CBC/NoPadding
-        final String transformation;
-
-        // algorithm name, e.g. AES
-        final String algorithm;
-
-        // supported and compile time enabled. Also see isAvailable()
-        final boolean allowed;
-
-        // number of bytes of entropy in the key
-        final int keySize;
-
-        // length of the actual cipher key in bytes.
-        // for non-exportable ciphers, this is the same as keySize
-        final int expandedKeySize;
-
-        // size of the IV (also block size)
-        final int ivSize;
-
-        // exportable under 512/40 bit rules
-        final boolean exportable;
-
-        // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
-        final boolean isCBCMode;
-
-        BulkCipher(String transformation, int keySize,
-                int expandedKeySize, int ivSize, boolean allowed) {
-            this.transformation = transformation;
-            String[] splits = transformation.split("/");
-            this.algorithm = splits[0];
-            this.isCBCMode =
-                splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
-            this.description = this.algorithm + "/" + (keySize << 3);
-            this.keySize = keySize;
-            this.ivSize = ivSize;
-            this.allowed = allowed;
-
-            this.expandedKeySize = expandedKeySize;
-            this.exportable = true;
-        }
-
-        BulkCipher(String transformation, int keySize,
-                int ivSize, boolean allowed) {
-            this.transformation = transformation;
-            String[] splits = transformation.split("/");
-            this.algorithm = splits[0];
-            this.isCBCMode =
-                splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
-            this.description = this.algorithm + "/" + (keySize << 3);
-            this.keySize = keySize;
-            this.ivSize = ivSize;
-            this.allowed = allowed;
-
-            this.expandedKeySize = keySize;
-            this.exportable = false;
-        }
-
-        /**
-         * Return an initialized CipherBox for this BulkCipher.
-         * IV must be null for stream ciphers.
-         *
-         * @exception NoSuchAlgorithmException if anything goes wrong
-         */
-        CipherBox newCipher(ProtocolVersion version, SecretKey key,
-                IvParameterSpec iv, SecureRandom random,
-                boolean encrypt) throws NoSuchAlgorithmException {
-            return CipherBox.newCipherBox(version, this,
-                                            key, iv, random, encrypt);
-        }
-
-        /**
-         * Test if this bulk cipher is available. For use by CipherSuite.
-         *
-         * Currently all supported ciphers except AES are always available
-         * via the JSSE internal implementations. We also assume AES/128
-         * is always available since it is shipped with the SunJCE provider.
-         * However, AES/256 is unavailable when the default JCE policy
-         * jurisdiction files are installed because of key length restrictions.
-         */
-        boolean isAvailable() {
-            if (allowed == false) {
-                return false;
-            }
-            if (this == B_AES_256) {
-                return isAvailable(this);
-            }
-
-            // always available
-            return true;
-        }
-
-        // for use by CipherSuiteList.clearAvailableCache();
-        static synchronized void clearAvailableCache() {
-            if (DYNAMIC_AVAILABILITY) {
-                availableCache.clear();
-            }
-        }
-
-        private static synchronized boolean isAvailable(BulkCipher cipher) {
-            Boolean b = availableCache.get(cipher);
-            if (b == null) {
-                try {
-                    SecretKey key = new SecretKeySpec
-                        (new byte[cipher.expandedKeySize], cipher.algorithm);
-                    IvParameterSpec iv =
-                        new IvParameterSpec(new byte[cipher.ivSize]);
-                    cipher.newCipher(ProtocolVersion.DEFAULT,
-                                                key, iv, null, true);
-                    b = Boolean.TRUE;
-                } catch (NoSuchAlgorithmException e) {
-                    b = Boolean.FALSE;
-                }
-                availableCache.put(cipher, b);
-            }
-            return b.booleanValue();
-        }
-
-        public String toString() {
-            return description;
-        }
-    }
-
-    /**
-     * An SSL/TLS key MAC algorithm.
-     *
-     * Also contains a factory method to obtain an initialized MAC
-     * for this algorithm.
-     */
-    final static class MacAlg {
-
-        // descriptive name, e.g. MD5
-        final String name;
-
-        // size of the MAC value (and MAC key) in bytes
-        final int size;
-
-        // block size of the underlying hash algorithm
-        final int hashBlockSize;
-
-        // minimal padding size of the underlying hash algorithm
-        final int minimalPaddingSize;
-
-        MacAlg(String name, int size,
-                int hashBlockSize, int minimalPaddingSize) {
-            this.name = name;
-            this.size = size;
-            this.hashBlockSize = hashBlockSize;
-            this.minimalPaddingSize = minimalPaddingSize;
-        }
-
-        /**
-         * Return an initialized MAC for this MacAlg. ProtocolVersion
-         * must either be SSL30 (SSLv3 custom MAC) or TLS10 (std. HMAC).
-         *
-         * @exception NoSuchAlgorithmException if anything goes wrong
-         */
-        MAC newMac(ProtocolVersion protocolVersion, SecretKey secret)
-                throws NoSuchAlgorithmException, InvalidKeyException {
-            return new MAC(this, protocolVersion, secret);
-        }
-
-        public String toString() {
-            return name;
-        }
-    }
-
-    // export strength ciphers
-    final static BulkCipher B_NULL    =
-                        new BulkCipher("NULL",         0,  0, 0, true);
-    final static BulkCipher B_RC4_40  =
-                        new BulkCipher(CIPHER_RC4,     5, 16, 0, true);
-    final static BulkCipher B_RC2_40  =
-                        new BulkCipher("RC2",          5, 16, 8, false);
-    final static BulkCipher B_DES_40  =
-                        new BulkCipher(CIPHER_DES,     5,  8, 8, true);
-
-    // domestic strength ciphers
-    final static BulkCipher B_RC4_128 =
-                        new BulkCipher(CIPHER_RC4,     16,  0, true);
-    final static BulkCipher B_DES     =
-                        new BulkCipher(CIPHER_DES,      8,  8, true);
-    final static BulkCipher B_3DES    =
-                        new BulkCipher(CIPHER_3DES,    24,  8, true);
-    final static BulkCipher B_IDEA    =
-                        new BulkCipher("IDEA",         16,  8, false);
-    final static BulkCipher B_AES_128 =
-                        new BulkCipher(CIPHER_AES,     16, 16, true);
-    final static BulkCipher B_AES_256 =
-                        new BulkCipher(CIPHER_AES,     32, 16, true);
-
-    // MACs
-    final static MacAlg M_NULL    = new MacAlg("NULL",     0,   0,   0);
-    final static MacAlg M_MD5     = new MacAlg("MD5",     16,  64,   9);
-    final static MacAlg M_SHA     = new MacAlg("SHA",     20,  64,   9);
-    final static MacAlg M_SHA256  = new MacAlg("SHA256",  32,  64,   9);
-    final static MacAlg M_SHA384  = new MacAlg("SHA384",  48, 128,  17);
-
-    /**
-     * PRFs (PseudoRandom Function) from TLS specifications.
-     *
-     * TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
-     * the necessary material.
-     *
-     * In TLS 1.2+, all existing/known CipherSuites use SHA256, however
-     * new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
-     * algorithms.
-     */
-    static enum PRF {
-
-        // PRF algorithms
-        P_NONE(     "NONE",  0,   0),
-        P_SHA256("SHA-256", 32,  64),
-        P_SHA384("SHA-384", 48, 128),
-        P_SHA512("SHA-512", 64, 128);  // not currently used.
-
-        // PRF characteristics
-        private final String prfHashAlg;
-        private final int prfHashLength;
-        private final int prfBlockSize;
-
-        PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
-            this.prfHashAlg = prfHashAlg;
-            this.prfHashLength = prfHashLength;
-            this.prfBlockSize = prfBlockSize;
-        }
-
-        String getPRFHashAlg() {
-            return prfHashAlg;
-        }
-
-        int getPRFHashLength() {
-            return prfHashLength;
-        }
-
-        int getPRFBlockSize() {
-            return prfBlockSize;
-        }
-    }
-
-    static {
-        idMap = new HashMap<Integer,CipherSuite>();
-        nameMap = new HashMap<String,CipherSuite>();
-
-        final boolean F = false;
-        final boolean T = true;
-        // N: ciphersuites only allowed if we are not in FIPS mode
-        final boolean N = (SunJSSE.isFIPS() == false);
-
-        /*
-         * TLS Cipher Suite Registry, as of August 2010.
-         *
-         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
-         *
-         * Range      Registration Procedures   Notes
-         * 000-191    Standards Action          Refers to value of first byte
-         * 192-254    Specification Required    Refers to value of first byte
-         * 255        Reserved for Private Use  Refers to value of first byte
-         *
-         * Value      Description                               Reference
-         * 0x00,0x00  TLS_NULL_WITH_NULL_NULL                   [RFC5246]
-         * 0x00,0x01  TLS_RSA_WITH_NULL_MD5                     [RFC5246]
-         * 0x00,0x02  TLS_RSA_WITH_NULL_SHA                     [RFC5246]
-         * 0x00,0x03  TLS_RSA_EXPORT_WITH_RC4_40_MD5            [RFC4346]
-         * 0x00,0x04  TLS_RSA_WITH_RC4_128_MD5                  [RFC5246]
-         * 0x00,0x05  TLS_RSA_WITH_RC4_128_SHA                  [RFC5246]
-         * 0x00,0x06  TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5        [RFC4346]
-         * 0x00,0x07  TLS_RSA_WITH_IDEA_CBC_SHA                 [RFC5469]
-         * 0x00,0x08  TLS_RSA_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
-         * 0x00,0x09  TLS_RSA_WITH_DES_CBC_SHA                  [RFC5469]
-         * 0x00,0x0A  TLS_RSA_WITH_3DES_EDE_CBC_SHA             [RFC5246]
-         * 0x00,0x0B  TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
-         * 0x00,0x0C  TLS_DH_DSS_WITH_DES_CBC_SHA               [RFC5469]
-         * 0x00,0x0D  TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA          [RFC5246]
-         * 0x00,0x0E  TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
-         * 0x00,0x0F  TLS_DH_RSA_WITH_DES_CBC_SHA               [RFC5469]
-         * 0x00,0x10  TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA          [RFC5246]
-         * 0x00,0x11  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x12  TLS_DHE_DSS_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x13  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x14  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x15  TLS_DHE_RSA_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x16  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x17  TLS_DH_anon_EXPORT_WITH_RC4_40_MD5        [RFC4346]
-         * 0x00,0x18  TLS_DH_anon_WITH_RC4_128_MD5              [RFC5246]
-         * 0x00,0x19  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
-         * 0x00,0x1A  TLS_DH_anon_WITH_DES_CBC_SHA              [RFC5469]
-         * 0x00,0x1B  TLS_DH_anon_WITH_3DES_EDE_CBC_SHA         [RFC5246]
-         * 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3  [RFC5246]
-         * 0x00,0x1E  TLS_KRB5_WITH_DES_CBC_SHA                 [RFC2712]
-         * 0x00,0x1F  TLS_KRB5_WITH_3DES_EDE_CBC_SHA            [RFC2712]
-         * 0x00,0x20  TLS_KRB5_WITH_RC4_128_SHA                 [RFC2712]
-         * 0x00,0x21  TLS_KRB5_WITH_IDEA_CBC_SHA                [RFC2712]
-         * 0x00,0x22  TLS_KRB5_WITH_DES_CBC_MD5                 [RFC2712]
-         * 0x00,0x23  TLS_KRB5_WITH_3DES_EDE_CBC_MD5            [RFC2712]
-         * 0x00,0x24  TLS_KRB5_WITH_RC4_128_MD5                 [RFC2712]
-         * 0x00,0x25  TLS_KRB5_WITH_IDEA_CBC_MD5                [RFC2712]
-         * 0x00,0x26  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA       [RFC2712]
-         * 0x00,0x27  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA       [RFC2712]
-         * 0x00,0x28  TLS_KRB5_EXPORT_WITH_RC4_40_SHA           [RFC2712]
-         * 0x00,0x29  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5       [RFC2712]
-         * 0x00,0x2A  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5       [RFC2712]
-         * 0x00,0x2B  TLS_KRB5_EXPORT_WITH_RC4_40_MD5           [RFC2712]
-         * 0x00,0x2C  TLS_PSK_WITH_NULL_SHA                     [RFC4785]
-         * 0x00,0x2D  TLS_DHE_PSK_WITH_NULL_SHA                 [RFC4785]
-         * 0x00,0x2E  TLS_RSA_PSK_WITH_NULL_SHA                 [RFC4785]
-         * 0x00,0x2F  TLS_RSA_WITH_AES_128_CBC_SHA              [RFC5246]
-         * 0x00,0x30  TLS_DH_DSS_WITH_AES_128_CBC_SHA           [RFC5246]
-         * 0x00,0x31  TLS_DH_RSA_WITH_AES_128_CBC_SHA           [RFC5246]
-         * 0x00,0x32  TLS_DHE_DSS_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x33  TLS_DHE_RSA_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x34  TLS_DH_anon_WITH_AES_128_CBC_SHA          [RFC5246]
-         * 0x00,0x35  TLS_RSA_WITH_AES_256_CBC_SHA              [RFC5246]
-         * 0x00,0x36  TLS_DH_DSS_WITH_AES_256_CBC_SHA           [RFC5246]
-         * 0x00,0x37  TLS_DH_RSA_WITH_AES_256_CBC_SHA           [RFC5246]
-         * 0x00,0x38  TLS_DHE_DSS_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x39  TLS_DHE_RSA_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x3A  TLS_DH_anon_WITH_AES_256_CBC_SHA          [RFC5246]
-         * 0x00,0x3B  TLS_RSA_WITH_NULL_SHA256                  [RFC5246]
-         * 0x00,0x3C  TLS_RSA_WITH_AES_128_CBC_SHA256           [RFC5246]
-         * 0x00,0x3D  TLS_RSA_WITH_AES_256_CBC_SHA256           [RFC5246]
-         * 0x00,0x3E  TLS_DH_DSS_WITH_AES_128_CBC_SHA256        [RFC5246]
-         * 0x00,0x3F  TLS_DH_RSA_WITH_AES_128_CBC_SHA256        [RFC5246]
-         * 0x00,0x40  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x41  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
-         * 0x00,0x42  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
-         * 0x00,0x43  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
-         * 0x00,0x44  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
-         * 0x00,0x45  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
-         * 0x00,0x46  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
-         * 0x00,0x47-4F Reserved to avoid conflicts with
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0x00,0x50-58 Reserved to avoid conflicts             [Pasi Eronen]
-         * 0x00,0x59-5C Reserved to avoid conflicts with
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0x00,0x5D-5F Unassigned
-         * 0x00,0x60-66 Reserved to avoid conflicts with widely
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0x00,0x67  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x68  TLS_DH_DSS_WITH_AES_256_CBC_SHA256        [RFC5246]
-         * 0x00,0x69  TLS_DH_RSA_WITH_AES_256_CBC_SHA256        [RFC5246]
-         * 0x00,0x6A  TLS_DHE_DSS_WITH_AES_256_CBC_SHA256       [RFC5246]
-         * 0x00,0x6B  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256       [RFC5246]
-         * 0x00,0x6C  TLS_DH_anon_WITH_AES_128_CBC_SHA256       [RFC5246]
-         * 0x00,0x6D  TLS_DH_anon_WITH_AES_256_CBC_SHA256       [RFC5246]
-         * 0x00,0x6E-83 Unassigned
-         * 0x00,0x84  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
-         * 0x00,0x85  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
-         * 0x00,0x86  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
-         * 0x00,0x87  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x88  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x89  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
-         * 0x00,0x8A  TLS_PSK_WITH_RC4_128_SHA                  [RFC4279]
-         * 0x00,0x8B  TLS_PSK_WITH_3DES_EDE_CBC_SHA             [RFC4279]
-         * 0x00,0x8C  TLS_PSK_WITH_AES_128_CBC_SHA              [RFC4279]
-         * 0x00,0x8D  TLS_PSK_WITH_AES_256_CBC_SHA              [RFC4279]
-         * 0x00,0x8E  TLS_DHE_PSK_WITH_RC4_128_SHA              [RFC4279]
-         * 0x00,0x8F  TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
-         * 0x00,0x90  TLS_DHE_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
-         * 0x00,0x91  TLS_DHE_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
-         * 0x00,0x92  TLS_RSA_PSK_WITH_RC4_128_SHA              [RFC4279]
-         * 0x00,0x93  TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
-         * 0x00,0x94  TLS_RSA_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
-         * 0x00,0x95  TLS_RSA_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
-         * 0x00,0x96  TLS_RSA_WITH_SEED_CBC_SHA                 [RFC4162]
-         * 0x00,0x97  TLS_DH_DSS_WITH_SEED_CBC_SHA              [RFC4162]
-         * 0x00,0x98  TLS_DH_RSA_WITH_SEED_CBC_SHA              [RFC4162]
-         * 0x00,0x99  TLS_DHE_DSS_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9A  TLS_DHE_RSA_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9B  TLS_DH_anon_WITH_SEED_CBC_SHA             [RFC4162]
-         * 0x00,0x9C  TLS_RSA_WITH_AES_128_GCM_SHA256           [RFC5288]
-         * 0x00,0x9D  TLS_RSA_WITH_AES_256_GCM_SHA384           [RFC5288]
-         * 0x00,0x9E  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0x9F  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA0  TLS_DH_RSA_WITH_AES_128_GCM_SHA256        [RFC5288]
-         * 0x00,0xA1  TLS_DH_RSA_WITH_AES_256_GCM_SHA384        [RFC5288]
-         * 0x00,0xA2  TLS_DHE_DSS_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0xA3  TLS_DHE_DSS_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA4  TLS_DH_DSS_WITH_AES_128_GCM_SHA256        [RFC5288]
-         * 0x00,0xA5  TLS_DH_DSS_WITH_AES_256_GCM_SHA384        [RFC5288]
-         * 0x00,0xA6  TLS_DH_anon_WITH_AES_128_GCM_SHA256       [RFC5288]
-         * 0x00,0xA7  TLS_DH_anon_WITH_AES_256_GCM_SHA384       [RFC5288]
-         * 0x00,0xA8  TLS_PSK_WITH_AES_128_GCM_SHA256           [RFC5487]
-         * 0x00,0xA9  TLS_PSK_WITH_AES_256_GCM_SHA384           [RFC5487]
-         * 0x00,0xAA  TLS_DHE_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
-         * 0x00,0xAB  TLS_DHE_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
-         * 0x00,0xAC  TLS_RSA_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
-         * 0x00,0xAD  TLS_RSA_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
-         * 0x00,0xAE  TLS_PSK_WITH_AES_128_CBC_SHA256           [RFC5487]
-         * 0x00,0xAF  TLS_PSK_WITH_AES_256_CBC_SHA384           [RFC5487]
-         * 0x00,0xB0  TLS_PSK_WITH_NULL_SHA256                  [RFC5487]
-         * 0x00,0xB1  TLS_PSK_WITH_NULL_SHA384                  [RFC5487]
-         * 0x00,0xB2  TLS_DHE_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
-         * 0x00,0xB3  TLS_DHE_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
-         * 0x00,0xB4  TLS_DHE_PSK_WITH_NULL_SHA256              [RFC5487]
-         * 0x00,0xB5  TLS_DHE_PSK_WITH_NULL_SHA384              [RFC5487]
-         * 0x00,0xB6  TLS_RSA_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
-         * 0x00,0xB7  TLS_RSA_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
-         * 0x00,0xB8  TLS_RSA_PSK_WITH_NULL_SHA256              [RFC5487]
-         * 0x00,0xB9  TLS_RSA_PSK_WITH_NULL_SHA384              [RFC5487]
-         * 0x00,0xBA  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
-         * 0x00,0xBB  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
-         * 0x00,0xBC  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
-         * 0x00,0xBD  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xBE  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xBF  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
-         * 0x00,0xC0  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
-         * 0x00,0xC1  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
-         * 0x00,0xC2  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
-         * 0x00,0xC3  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
-         * 0x00,0xC4  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
-         * 0x00,0xC5  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
-         * 0x00,0xC6-FE         Unassigned
-         * 0x00,0xFF  TLS_EMPTY_RENEGOTIATION_INFO_SCSV         [RFC5746]
-         * 0x01-BF,*  Unassigned
-         * 0xC0,0x01  TLS_ECDH_ECDSA_WITH_NULL_SHA              [RFC4492]
-         * 0xC0,0x02  TLS_ECDH_ECDSA_WITH_RC4_128_SHA           [RFC4492]
-         * 0xC0,0x03  TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA      [RFC4492]
-         * 0xC0,0x04  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA       [RFC4492]
-         * 0xC0,0x05  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA       [RFC4492]
-         * 0xC0,0x06  TLS_ECDHE_ECDSA_WITH_NULL_SHA             [RFC4492]
-         * 0xC0,0x07  TLS_ECDHE_ECDSA_WITH_RC4_128_SHA          [RFC4492]
-         * 0xC0,0x08  TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA     [RFC4492]
-         * 0xC0,0x09  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA      [RFC4492]
-         * 0xC0,0x0A  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA      [RFC4492]
-         * 0xC0,0x0B  TLS_ECDH_RSA_WITH_NULL_SHA                [RFC4492]
-         * 0xC0,0x0C  TLS_ECDH_RSA_WITH_RC4_128_SHA             [RFC4492]
-         * 0xC0,0x0D  TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA        [RFC4492]
-         * 0xC0,0x0E  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA         [RFC4492]
-         * 0xC0,0x0F  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA         [RFC4492]
-         * 0xC0,0x10  TLS_ECDHE_RSA_WITH_NULL_SHA               [RFC4492]
-         * 0xC0,0x11  TLS_ECDHE_RSA_WITH_RC4_128_SHA            [RFC4492]
-         * 0xC0,0x12  TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA       [RFC4492]
-         * 0xC0,0x13  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA        [RFC4492]
-         * 0xC0,0x14  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA        [RFC4492]
-         * 0xC0,0x15  TLS_ECDH_anon_WITH_NULL_SHA               [RFC4492]
-         * 0xC0,0x16  TLS_ECDH_anon_WITH_RC4_128_SHA            [RFC4492]
-         * 0xC0,0x17  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA       [RFC4492]
-         * 0xC0,0x18  TLS_ECDH_anon_WITH_AES_128_CBC_SHA        [RFC4492]
-         * 0xC0,0x19  TLS_ECDH_anon_WITH_AES_256_CBC_SHA        [RFC4492]
-         * 0xC0,0x1A  TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA         [RFC5054]
-         * 0xC0,0x1B  TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA     [RFC5054]
-         * 0xC0,0x1C  TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA     [RFC5054]
-         * 0xC0,0x1D  TLS_SRP_SHA_WITH_AES_128_CBC_SHA          [RFC5054]
-         * 0xC0,0x1E  TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA      [RFC5054]
-         * 0xC0,0x1F  TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA      [RFC5054]
-         * 0xC0,0x20  TLS_SRP_SHA_WITH_AES_256_CBC_SHA          [RFC5054]
-         * 0xC0,0x21  TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA      [RFC5054]
-         * 0xC0,0x22  TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA      [RFC5054]
-         * 0xC0,0x23  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256   [RFC5289]
-         * 0xC0,0x24  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384   [RFC5289]
-         * 0xC0,0x25  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256    [RFC5289]
-         * 0xC0,0x26  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384    [RFC5289]
-         * 0xC0,0x27  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256     [RFC5289]
-         * 0xC0,0x28  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384     [RFC5289]
-         * 0xC0,0x29  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256      [RFC5289]
-         * 0xC0,0x2A  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384      [RFC5289]
-         * 0xC0,0x2B  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256   [RFC5289]
-         * 0xC0,0x2C  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384   [RFC5289]
-         * 0xC0,0x2D  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256    [RFC5289]
-         * 0xC0,0x2E  TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384    [RFC5289]
-         * 0xC0,0x2F  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256     [RFC5289]
-         * 0xC0,0x30  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384     [RFC5289]
-         * 0xC0,0x31  TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256      [RFC5289]
-         * 0xC0,0x32  TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384      [RFC5289]
-         * 0xC0,0x33  TLS_ECDHE_PSK_WITH_RC4_128_SHA            [RFC5489]
-         * 0xC0,0x34  TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA       [RFC5489]
-         * 0xC0,0x35  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA        [RFC5489]
-         * 0xC0,0x36  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA        [RFC5489]
-         * 0xC0,0x37  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256     [RFC5489]
-         * 0xC0,0x38  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384     [RFC5489]
-         * 0xC0,0x39  TLS_ECDHE_PSK_WITH_NULL_SHA               [RFC5489]
-         * 0xC0,0x3A  TLS_ECDHE_PSK_WITH_NULL_SHA256            [RFC5489]
-         * 0xC0,0x3B  TLS_ECDHE_PSK_WITH_NULL_SHA384            [RFC5489]
-         * 0xC0,0x3C-FF Unassigned
-         * 0xC1-FD,*  Unassigned
-         * 0xFE,0x00-FD Unassigned
-         * 0xFE,0xFE-FF Reserved to avoid conflicts with widely
-         *            deployed implementations                  [Pasi_Eronen]
-         * 0xFF,0x00-FF Reserved for Private Use                [RFC5246]
-         */
-
-        add("SSL_NULL_WITH_NULL_NULL",
-                              0x0000,   1, K_NULL,       B_NULL,    F);
-
-        /*
-         * Definition of the CipherSuites that are enabled by default.
-         * They are listed in preference order, most preferred first, using
-         * the following criteria:
-         * 1. Prefer the stronger buld cipher, in the order of AES_256,
-         *    AES_128, RC-4, 3DES-EDE.
-         * 2. Prefer the stronger MAC algorithm, in the order of SHA384,
-         *    SHA256, SHA, MD5.
-         * 3. Prefer the better performance of key exchange and digital
-         *    signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
-         *    RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
-         */
-        int p = DEFAULT_SUITES_PRIORITY * 2;
-
-        // shorten names to fit the following table cleanly.
-        int max = ProtocolVersion.LIMIT_MAX_VALUE;
-        int tls11 = ProtocolVersion.TLS11.v;
-        int tls12 = ProtocolVersion.TLS12.v;
-
-        //  ID           Key Exchange   Cipher     A  obs  suprt  PRF
-        //  ======       ============   =========  =  ===  =====  ========
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
-            0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
-            0xc028, --p, K_ECDHE_RSA,   B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_RSA_WITH_AES_256_CBC_SHA256",
-            0x003d, --p, K_RSA,         B_AES_256, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
-            0xc026, --p, K_ECDH_ECDSA,  B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
-            0xc02a, --p, K_ECDH_RSA,    B_AES_256, T, max, tls12, P_SHA384);
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
-            0x006b, --p, K_DHE_RSA,     B_AES_256, T, max, tls12, P_SHA256);
-        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
-            0x006a, --p, K_DHE_DSS,     B_AES_256, T, max, tls12, P_SHA256);
-
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-            0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-            0xC014, --p, K_ECDHE_RSA,   B_AES_256, T);
-        add("TLS_RSA_WITH_AES_256_CBC_SHA",
-            0x0035, --p, K_RSA,         B_AES_256, T);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
-            0xC005, --p, K_ECDH_ECDSA,  B_AES_256, T);
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
-            0xC00F, --p, K_ECDH_RSA,    B_AES_256, T);
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-            0x0039, --p, K_DHE_RSA,     B_AES_256, T);
-        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
-            0x0038, --p, K_DHE_DSS,     B_AES_256, T);
-
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
-            0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
-            0xc027, --p, K_ECDHE_RSA,   B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_RSA_WITH_AES_128_CBC_SHA256",
-            0x003c, --p, K_RSA,         B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
-            0xc025, --p, K_ECDH_ECDSA,  B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
-            0xc029, --p, K_ECDH_RSA,    B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
-            0x0067, --p, K_DHE_RSA,     B_AES_128, T, max, tls12, P_SHA256);
-        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
-            0x0040, --p, K_DHE_DSS,     B_AES_128, T, max, tls12, P_SHA256);
-
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-            0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-            0xC013, --p, K_ECDHE_RSA,   B_AES_128, T);
-        add("TLS_RSA_WITH_AES_128_CBC_SHA",
-            0x002f, --p, K_RSA,         B_AES_128, T);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
-            0xC004, --p, K_ECDH_ECDSA,  B_AES_128, T);
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
-            0xC00E, --p, K_ECDH_RSA,    B_AES_128, T);
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-            0x0033, --p, K_DHE_RSA,     B_AES_128, T);
-        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
-            0x0032, --p, K_DHE_DSS,     B_AES_128, T);
-
-        add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
-            0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
-        add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
-            0xC011, --p, K_ECDHE_RSA,   B_RC4_128, N);
-        add("SSL_RSA_WITH_RC4_128_SHA",
-            0x0005, --p, K_RSA,         B_RC4_128, N);
-        add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
-            0xC002, --p, K_ECDH_ECDSA,  B_RC4_128, N);
-        add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
-            0xC00C, --p, K_ECDH_RSA,    B_RC4_128, N);
-
-        add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
-            0xC008, --p, K_ECDHE_ECDSA, B_3DES,    T);
-        add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
-            0xC012, --p, K_ECDHE_RSA,   B_3DES,    T);
-        add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
-            0x000a, --p, K_RSA,         B_3DES,    T);
-        add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
-            0xC003, --p, K_ECDH_ECDSA,  B_3DES,    T);
-        add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
-            0xC00D, --p, K_ECDH_RSA,    B_3DES,    T);
-        add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
-            0x0016, --p, K_DHE_RSA,     B_3DES,    T);
-        add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
-            0x0013, --p, K_DHE_DSS,     B_3DES,    N);
-
-        add("SSL_RSA_WITH_RC4_128_MD5",
-            0x0004, --p, K_RSA,         B_RC4_128, N);
-
-        // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
-        add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
-            0x00ff, --p, K_SCSV,        B_NULL,    T);
-
-        /*
-         * Definition of the CipherSuites that are supported but not enabled
-         * by default.
-         * They are listed in preference order, preferred first, using the
-         * following criteria:
-         * 1. CipherSuites for KRB5 need additional KRB5 service
-         *    configuration, and these suites are not common in practice,
-         *    so we put KRB5 based cipher suites at the end of the supported
-         *    list.
-         * 2. If a cipher suite has been obsoleted, we put it at the end of
-         *    the list.
-         * 3. Prefer the stronger bulk cipher, in the order of AES_256,
-         *    AES_128, RC-4, 3DES-EDE, DES, RC4_40, DES40, NULL.
-         * 4. Prefer the stronger MAC algorithm, in the order of SHA384,
-         *    SHA256, SHA, MD5.
-         * 5. Prefer the better performance of key exchange and digital
-         *    signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
-         *    RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS, anonymous.
-         */
-        p = DEFAULT_SUITES_PRIORITY;
-
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
-            0x006d, --p, K_DH_ANON,     B_AES_256, N, max, tls12, P_SHA256);
-        add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
-            0xC019, --p, K_ECDH_ANON,   B_AES_256, T);
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
-            0x003a, --p, K_DH_ANON,     B_AES_256, N);
-
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
-            0x006c, --p, K_DH_ANON,     B_AES_128, N, max, tls12, P_SHA256);
-        add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
-            0xC018, --p, K_ECDH_ANON,   B_AES_128, T);
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
-            0x0034, --p, K_DH_ANON,     B_AES_128, N);
-
-        add("TLS_ECDH_anon_WITH_RC4_128_SHA",
-            0xC016, --p, K_ECDH_ANON,   B_RC4_128, N);
-        add("SSL_DH_anon_WITH_RC4_128_MD5",
-            0x0018, --p, K_DH_ANON,     B_RC4_128, N);
-
-        add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
-            0xC017, --p, K_ECDH_ANON,   B_3DES,    T);
-        add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
-            0x001b, --p, K_DH_ANON,     B_3DES,    N);
-
-        add("TLS_RSA_WITH_NULL_SHA256",
-            0x003b, --p, K_RSA,         B_NULL,    N, max, tls12, P_SHA256);
-        add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
-            0xC006, --p, K_ECDHE_ECDSA, B_NULL,    N);
-        add("TLS_ECDHE_RSA_WITH_NULL_SHA",
-            0xC010, --p, K_ECDHE_RSA,   B_NULL,    N);
-        add("SSL_RSA_WITH_NULL_SHA",
-            0x0002, --p, K_RSA,         B_NULL,    N);
-        add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
-            0xC001, --p, K_ECDH_ECDSA,  B_NULL,    N);
-        add("TLS_ECDH_RSA_WITH_NULL_SHA",
-            0xC00B, --p, K_ECDH_RSA,    B_NULL,    N);
-        add("TLS_ECDH_anon_WITH_NULL_SHA",
-            0xC015, --p, K_ECDH_ANON,   B_NULL,    N);
-        add("SSL_RSA_WITH_NULL_MD5",
-            0x0001, --p, K_RSA,         B_NULL,    N);
-
-        // weak cipher suites obsoleted in TLS 1.2
-        add("SSL_RSA_WITH_DES_CBC_SHA",
-            0x0009, --p, K_RSA,         B_DES,     N, tls12);
-        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
-            0x0015, --p, K_DHE_RSA,     B_DES,     N, tls12);
-        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
-            0x0012, --p, K_DHE_DSS,     B_DES,     N, tls12);
-        add("SSL_DH_anon_WITH_DES_CBC_SHA",
-            0x001a, --p, K_DH_ANON,     B_DES,     N, tls12);
-
-        // weak cipher suites obsoleted in TLS 1.1
-        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
-            0x0003, --p, K_RSA_EXPORT,  B_RC4_40,  N, tls11);
-        add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-            0x0017, --p, K_DH_ANON,     B_RC4_40,  N, tls11);
-
-        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
-            0x0008, --p, K_RSA_EXPORT,  B_DES_40,  N, tls11);
-        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
-            0x0014, --p, K_DHE_RSA,     B_DES_40,  N, tls11);
-        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
-            0x0011, --p, K_DHE_DSS,     B_DES_40,  N, tls11);
-        add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-            0x0019, --p, K_DH_ANON,     B_DES_40,  N, tls11);
-
-        // Supported Kerberos ciphersuites from RFC2712
-        add("TLS_KRB5_WITH_RC4_128_SHA",
-            0x0020, --p, K_KRB5,        B_RC4_128, N);
-        add("TLS_KRB5_WITH_RC4_128_MD5",
-            0x0024, --p, K_KRB5,        B_RC4_128, N);
-        add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
-            0x001f, --p, K_KRB5,        B_3DES,    N);
-        add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
-            0x0023, --p, K_KRB5,        B_3DES,    N);
-        add("TLS_KRB5_WITH_DES_CBC_SHA",
-            0x001e, --p, K_KRB5,        B_DES,     N, tls12);
-        add("TLS_KRB5_WITH_DES_CBC_MD5",
-            0x0022, --p, K_KRB5,        B_DES,     N, tls12);
-        add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
-            0x0028, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
-            0x002b, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
-            0x0026, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
-        add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
-            0x0029, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
-
-        /*
-         * Other values from the TLS Cipher Suite Registry, as of August 2010.
-         *
-         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
-         *
-         * Range      Registration Procedures   Notes
-         * 000-191    Standards Action          Refers to value of first byte
-         * 192-254    Specification Required    Refers to value of first byte
-         * 255        Reserved for Private Use  Refers to value of first byte
-         */
-
-        // Register the names of a few additional CipherSuites.
-        // Makes them show up as names instead of numbers in
-        // the debug output.
-
-        // remaining unsupported ciphersuites defined in RFC2246.
-        add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",          0x0006);
-        add("SSL_RSA_WITH_IDEA_CBC_SHA",                   0x0007);
-        add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",        0x000b);
-        add("SSL_DH_DSS_WITH_DES_CBC_SHA",                 0x000c);
-        add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",            0x000d);
-        add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",        0x000e);
-        add("SSL_DH_RSA_WITH_DES_CBC_SHA",                 0x000f);
-        add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",            0x0010);
-
-        // SSL 3.0 Fortezza ciphersuites
-        add("SSL_FORTEZZA_DMS_WITH_NULL_SHA",              0x001c);
-        add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",      0x001d);
-
-        // 1024/56 bit exportable ciphersuites from expired internet draft
-        add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",         0x0062);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA",     0x0063);
-        add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",          0x0064);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",      0x0065);
-        add("SSL_DHE_DSS_WITH_RC4_128_SHA",                0x0066);
-
-        // Netscape old and new SSL 3.0 FIPS ciphersuites
-        // see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
-        add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",     0xffe0);
-        add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA",          0xffe1);
-        add("SSL_RSA_FIPS_WITH_DES_CBC_SHA",               0xfefe);
-        add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",          0xfeff);
-
-        // Unsupported Kerberos cipher suites from RFC 2712
-        add("TLS_KRB5_WITH_IDEA_CBC_SHA",                  0x0021);
-        add("TLS_KRB5_WITH_IDEA_CBC_MD5",                  0x0025);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",         0x0027);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",         0x002a);
-
-        // Unsupported cipher suites from RFC 4162
-        add("TLS_RSA_WITH_SEED_CBC_SHA",                   0x0096);
-        add("TLS_DH_DSS_WITH_SEED_CBC_SHA",                0x0097);
-        add("TLS_DH_RSA_WITH_SEED_CBC_SHA",                0x0098);
-        add("TLS_DHE_DSS_WITH_SEED_CBC_SHA",               0x0099);
-        add("TLS_DHE_RSA_WITH_SEED_CBC_SHA",               0x009a);
-        add("TLS_DH_anon_WITH_SEED_CBC_SHA",               0x009b);
-
-        // Unsupported cipher suites from RFC 4279
-        add("TLS_PSK_WITH_RC4_128_SHA",                    0x008a);
-        add("TLS_PSK_WITH_3DES_EDE_CBC_SHA",               0x008b);
-        add("TLS_PSK_WITH_AES_128_CBC_SHA",                0x008c);
-        add("TLS_PSK_WITH_AES_256_CBC_SHA",                0x008d);
-        add("TLS_DHE_PSK_WITH_RC4_128_SHA",                0x008e);
-        add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",           0x008f);
-        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA",            0x0090);
-        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA",            0x0091);
-        add("TLS_RSA_PSK_WITH_RC4_128_SHA",                0x0092);
-        add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",           0x0093);
-        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA",            0x0094);
-        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA",            0x0095);
-
-        // Unsupported cipher suites from RFC 4785
-        add("TLS_PSK_WITH_NULL_SHA",                       0x002c);
-        add("TLS_DHE_PSK_WITH_NULL_SHA",                   0x002d);
-        add("TLS_RSA_PSK_WITH_NULL_SHA",                   0x002e);
-
-        // Unsupported cipher suites from RFC 5246
-        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA",             0x0030);
-        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA",             0x0031);
-        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA",             0x0036);
-        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA",             0x0037);
-        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256",          0x003e);
-        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256",          0x003f);
-        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256",          0x0068);
-        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256",          0x0069);
-
-        // Unsupported cipher suites from RFC 5288
-        add("TLS_RSA_WITH_AES_128_GCM_SHA256",             0x009c);
-        add("TLS_RSA_WITH_AES_256_GCM_SHA384",             0x009d);
-        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",         0x009e);
-        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",         0x009f);
-        add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256",          0x00a0);
-        add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384",          0x00a1);
-        add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",         0x00a2);
-        add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",         0x00a3);
-        add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256",          0x00a4);
-        add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384",          0x00a5);
-        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",         0x00a6);
-        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",         0x00a7);
-
-        // Unsupported cipher suites from RFC 5487
-        add("TLS_PSK_WITH_AES_128_GCM_SHA256",             0x00a8);
-        add("TLS_PSK_WITH_AES_256_GCM_SHA384",             0x00a9);
-        add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",         0x00aa);
-        add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",         0x00ab);
-        add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",         0x00ac);
-        add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",         0x00ad);
-        add("TLS_PSK_WITH_AES_128_CBC_SHA256",             0x00ae);
-        add("TLS_PSK_WITH_AES_256_CBC_SHA384",             0x00af);
-        add("TLS_PSK_WITH_NULL_SHA256",                    0x00b0);
-        add("TLS_PSK_WITH_NULL_SHA384",                    0x00b1);
-        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",         0x00b2);
-        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",         0x00b3);
-        add("TLS_DHE_PSK_WITH_NULL_SHA256",                0x00b4);
-        add("TLS_DHE_PSK_WITH_NULL_SHA384",                0x00b5);
-        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",         0x00b6);
-        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",         0x00b7);
-        add("TLS_RSA_PSK_WITH_NULL_SHA256",                0x00b8);
-        add("TLS_RSA_PSK_WITH_NULL_SHA384",                0x00b9);
-
-        // Unsupported cipher suites from RFC 5932
-        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",           0x0041);
-        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",        0x0042);
-        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",        0x0043);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",       0x0044);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",       0x0045);
-        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",       0x0046);
-        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",           0x0084);
-        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",        0x0085);
-        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",        0x0086);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",       0x0087);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",       0x0088);
-        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",       0x0089);
-        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",        0x00ba);
-        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",     0x00bb);
-        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",     0x00bc);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",    0x00bd);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",    0x00be);
-        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",    0x00bf);
-        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",        0x00c0);
-        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",     0x00c1);
-        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",     0x00c2);
-        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",    0x00c3);
-        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",    0x00c4);
-        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",    0x00c5);
-
-        // Unsupported cipher suites from RFC 5054
-        add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",           0xc01a);
-        add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",       0xc01b);
-        add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",       0xc01c);
-        add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA",            0xc01d);
-        add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",        0xc01e);
-        add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",        0xc01f);
-        add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA",            0xc020);
-        add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",        0xc021);
-        add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",        0xc022);
-
-        // Unsupported cipher suites from RFC 5289
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",     0xc02b);
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",     0xc02c);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",      0xc02d);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",      0xc02e);
-        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",       0xc02f);
-        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",       0xc030);
-        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",        0xc031);
-        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",        0xc032);
-
-        // Unsupported cipher suites from RFC 5489
-        add("TLS_ECDHE_PSK_WITH_RC4_128_SHA",              0xc033);
-        add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",         0xc034);
-        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",          0xc035);
-        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",          0xc036);
-        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",       0xc037);
-        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",       0xc038);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA",                 0xc039);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA256",              0xc03a);
-        add("TLS_ECDHE_PSK_WITH_NULL_SHA384",              0xc03b);
-    }
-
-    // ciphersuite SSL_NULL_WITH_NULL_NULL
-    final static CipherSuite C_NULL = CipherSuite.valueOf(0, 0);
-
-    // ciphersuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-    final static CipherSuite C_SCSV = CipherSuite.valueOf(0x00, 0xff);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java b/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java
deleted file mode 100755
index bf69b35..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-
-import javax.net.ssl.SSLException;
-
-/**
- * A list of CipherSuites. Also maintains the lists of supported and
- * default ciphersuites and supports I/O from handshake streams.
- *
- * Instances of this class are immutable.
- *
- */
-final class CipherSuiteList {
-
-    private final Collection<CipherSuite> cipherSuites;
-    private String[] suiteNames;
-
-    // flag indicating whether this list contains any ECC ciphersuites.
-    // null if not yet checked.
-    private volatile Boolean containsEC;
-
-    // for use by buildAvailableCache() and
-    // Handshaker.getKickstartMessage() only
-    CipherSuiteList(Collection<CipherSuite> cipherSuites) {
-        this.cipherSuites = cipherSuites;
-    }
-
-    /**
-     * Create a CipherSuiteList with a single element.
-     */
-    CipherSuiteList(CipherSuite suite) {
-        cipherSuites = new ArrayList<CipherSuite>(1);
-        cipherSuites.add(suite);
-    }
-
-    /**
-     * Construct a CipherSuiteList from a array of names. We don't bother
-     * to eliminate duplicates.
-     *
-     * @exception IllegalArgumentException if the array or any of its elements
-     * is null or if the ciphersuite name is unrecognized or unsupported
-     * using currently installed providers.
-     */
-    CipherSuiteList(String[] names) {
-        if (names == null) {
-            throw new IllegalArgumentException("CipherSuites may not be null");
-        }
-        cipherSuites = new ArrayList<CipherSuite>(names.length);
-        // refresh available cache once if a CipherSuite is not available
-        // (maybe new JCE providers have been installed)
-        boolean refreshed = false;
-        for (int i = 0; i < names.length; i++) {
-            String suiteName = names[i];
-            CipherSuite suite = CipherSuite.valueOf(suiteName);
-            if (suite.isAvailable() == false) {
-                if (refreshed == false) {
-                    // clear the cache so that the isAvailable() call below
-                    // does a full check
-                    clearAvailableCache();
-                    refreshed = true;
-                }
-                // still missing?
-                if (suite.isAvailable() == false) {
-                    throw new IllegalArgumentException("Cannot support "
-                        + suiteName + " with currently installed providers");
-                }
-            }
-            cipherSuites.add(suite);
-        }
-    }
-
-    /**
-     * Read a CipherSuiteList from a HandshakeInStream in V3 ClientHello
-     * format. Does not check if the listed ciphersuites are known or
-     * supported.
-     */
-    CipherSuiteList(HandshakeInStream in) throws IOException {
-        byte[] bytes = in.getBytes16();
-        if ((bytes.length & 1) != 0) {
-            throw new SSLException("Invalid ClientHello message");
-        }
-        cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
-        for (int i = 0; i < bytes.length; i += 2) {
-            cipherSuites.add(CipherSuite.valueOf(bytes[i], bytes[i+1]));
-        }
-    }
-
-    /**
-     * Return whether this list contains the given CipherSuite.
-     */
-    boolean contains(CipherSuite suite) {
-        return cipherSuites.contains(suite);
-    }
-
-    // Return whether this list contains any ECC ciphersuites
-    boolean containsEC() {
-        if (containsEC == null) {
-            for (CipherSuite c : cipherSuites) {
-                switch (c.keyExchange) {
-                case K_ECDH_ECDSA:
-                case K_ECDH_RSA:
-                case K_ECDHE_ECDSA:
-                case K_ECDHE_RSA:
-                case K_ECDH_ANON:
-                    containsEC = true;
-                    return true;
-                default:
-                    break;
-                }
-            }
-            containsEC = false;
-        }
-        return containsEC;
-    }
-
-    /**
-     * Return an Iterator for the CipherSuites in this list.
-     */
-    Iterator<CipherSuite> iterator() {
-        return cipherSuites.iterator();
-    }
-
-    /**
-     * Return a reference to the internal Collection of CipherSuites.
-     * The Collection MUST NOT be modified.
-     */
-    Collection<CipherSuite> collection() {
-        return cipherSuites;
-    }
-
-    /**
-     * Return the number of CipherSuites in this list.
-     */
-    int size() {
-        return cipherSuites.size();
-    }
-
-    /**
-     * Return an array with the names of the CipherSuites in this list.
-     */
-    synchronized String[] toStringArray() {
-        if (suiteNames == null) {
-            suiteNames = new String[cipherSuites.size()];
-            int i = 0;
-            for (CipherSuite c : cipherSuites) {
-                suiteNames[i++] = c.name;
-            }
-        }
-        return suiteNames.clone();
-    }
-
-    public String toString() {
-        return cipherSuites.toString();
-    }
-
-    /**
-     * Write this list to an HandshakeOutStream in V3 ClientHello format.
-     */
-    void send(HandshakeOutStream s) throws IOException {
-        byte[] suiteBytes = new byte[cipherSuites.size() * 2];
-        int i = 0;
-        for (CipherSuite c : cipherSuites) {
-            suiteBytes[i] = (byte)(c.id >> 8);
-            suiteBytes[i+1] = (byte)c.id;
-            i += 2;
-        }
-        s.putBytes16(suiteBytes);
-    }
-
-    /**
-     * Clear cache of available ciphersuites. If we support all ciphers
-     * internally, there is no need to clear the cache and calling this
-     * method has no effect.
-     */
-    static synchronized void clearAvailableCache() {
-        if (CipherSuite.DYNAMIC_AVAILABILITY) {
-            CipherSuite.BulkCipher.clearAvailableCache();
-            JsseJce.clearEcAvailable();
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java b/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java
deleted file mode 100755
index 0c1022b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java
+++ /dev/null
@@ -1,1345 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.util.*;
-
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECParameterSpec;
-
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-import sun.net.util.IPAddressUtil;
-
-/**
- * ClientHandshaker does the protocol handshaking from the point
- * of view of a client.  It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ClientHandshaker extends Handshaker {
-
-    // the server's public key from its certificate.
-    private PublicKey serverKey;
-
-    // the server's ephemeral public key from the server key exchange message
-    // for ECDHE/ECDH_anon and RSA_EXPORT.
-    private PublicKey ephemeralServerKey;
-
-    // server's ephemeral public value for DHE/DH_anon key exchanges
-    private BigInteger          serverDH;
-
-    private DHCrypt             dh;
-
-    private ECDHCrypt ecdh;
-
-    private CertificateRequest  certRequest;
-
-    private boolean serverKeyExchangeReceived;
-
-    /*
-     * The RSA PreMasterSecret needs to know the version of
-     * ClientHello that was used on this handshake.  This represents
-     * the "max version" this client is supporting.  In the
-     * case of an initial handshake, it's the max version enabled,
-     * but in the case of a resumption attempt, it's the version
-     * of the session we're trying to resume.
-     */
-    private ProtocolVersion maxProtocolVersion;
-
-    // To switch off the SNI extension.
-    private final static boolean enableSNIExtension =
-            Debug.getBooleanProperty("jsse.enableSNIExtension", true);
-
-    /*
-     * Constructors
-     */
-    ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
-            ProtocolList enabledProtocols,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(socket, context, enabledProtocols, true, true,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(engine, context, enabledProtocols, true, true,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    /*
-     * This routine handles all the client side handshake messages, one at
-     * a time.  Given the message type (and in some cases the pending cipher
-     * spec) it parses the type-specific message.  Then it calls a function
-     * that handles that specific message.
-     *
-     * It updates the state machine (need to verify it) as each message
-     * is processed, and writes responses as needed using the connection
-     * in the constructor.
-     */
-    void processMessage(byte type, int messageLen) throws IOException {
-        if (state >= type
-                && (type != HandshakeMessage.ht_hello_request)) {
-            throw new SSLProtocolException(
-                    "Handshake message sequence violation, " + type);
-        }
-
-        switch (type) {
-        case HandshakeMessage.ht_hello_request:
-            this.serverHelloRequest(new HelloRequest(input));
-            break;
-
-        case HandshakeMessage.ht_server_hello:
-            this.serverHello(new ServerHello(input, messageLen));
-            break;
-
-        case HandshakeMessage.ht_certificate:
-            if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
-                    || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-                fatalSE(Alerts.alert_unexpected_message,
-                    "unexpected server cert chain");
-                // NOTREACHED
-            }
-            this.serverCertificate(new CertificateMsg(input));
-            serverKey =
-                session.getPeerCertificates()[0].getPublicKey();
-            break;
-
-        case HandshakeMessage.ht_server_key_exchange:
-            serverKeyExchangeReceived = true;
-            switch (keyExchange) {
-            case K_RSA_EXPORT:
-                /**
-                 * The server key exchange message is sent by the server only
-                 * when the server certificate message does not contain the
-                 * proper amount of data to allow the client to exchange a
-                 * premaster secret, such as when RSA_EXPORT is used and the
-                 * public key in the server certificate is longer than 512 bits.
-                 */
-                if (serverKey == null) {
-                    throw new SSLProtocolException
-                        ("Server did not send certificate message");
-                }
-
-                if (!(serverKey instanceof RSAPublicKey)) {
-                    throw new SSLProtocolException("Protocol violation:" +
-                        " the certificate type must be appropriate for the" +
-                        " selected cipher suite's key exchange algorithm");
-                }
-
-                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
-                    throw new SSLProtocolException("Protocol violation:" +
-                        " server sent a server key exchange message for" +
-                        " key exchange " + keyExchange +
-                        " when the public key in the server certificate" +
-                        " is less than or equal to 512 bits in length");
-                }
-
-                try {
-                    this.serverKeyExchange(new RSA_ServerKeyExchange(input));
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_DH_ANON:
-                try {
-                    this.serverKeyExchange(new DH_ServerKeyExchange(
-                                                input, protocolVersion));
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_DHE_DSS:
-            case K_DHE_RSA:
-                try {
-                    this.serverKeyExchange(new DH_ServerKeyExchange(
-                        input, serverKey,
-                        clnt_random.random_bytes, svr_random.random_bytes,
-                        messageLen,
-                        localSupportedSignAlgs, protocolVersion));
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_ECDHE_ECDSA:
-            case K_ECDHE_RSA:
-            case K_ECDH_ANON:
-                try {
-                    this.serverKeyExchange(new ECDH_ServerKeyExchange
-                        (input, serverKey, clnt_random.random_bytes,
-                        svr_random.random_bytes,
-                        localSupportedSignAlgs, protocolVersion));
-                } catch (GeneralSecurityException e) {
-                    throwSSLException("Server key", e);
-                }
-                break;
-            case K_RSA:
-            case K_DH_RSA:
-            case K_DH_DSS:
-            case K_ECDH_ECDSA:
-            case K_ECDH_RSA:
-                throw new SSLProtocolException(
-                    "Protocol violation: server sent a server key exchange"
-                    + "message for key exchange " + keyExchange);
-            case K_KRB5:
-            case K_KRB5_EXPORT:
-                throw new SSLProtocolException(
-                    "unexpected receipt of server key exchange algorithm");
-            default:
-                throw new SSLProtocolException(
-                    "unsupported key exchange algorithm = "
-                    + keyExchange);
-            }
-            break;
-
-        case HandshakeMessage.ht_certificate_request:
-            // save for later, it's handled by serverHelloDone
-            if ((keyExchange == K_DH_ANON) || (keyExchange == K_ECDH_ANON)) {
-                throw new SSLHandshakeException(
-                    "Client authentication requested for "+
-                    "anonymous cipher suite.");
-            } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-                throw new SSLHandshakeException(
-                    "Client certificate requested for "+
-                    "kerberos cipher suite.");
-            }
-            certRequest = new CertificateRequest(input, protocolVersion);
-            if (debug != null && Debug.isOn("handshake")) {
-                certRequest.print(System.out);
-            }
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                Collection<SignatureAndHashAlgorithm> peerSignAlgs =
-                                        certRequest.getSignAlgorithms();
-                if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                        "No peer supported signature algorithms");
-                }
-
-                Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
-                    SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                                            peerSignAlgs);
-                if (supportedPeerSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                        "No supported signature and hash algorithm in common");
-                }
-
-                setPeerSupportedSignAlgs(supportedPeerSignAlgs);
-                session.setPeerSupportedSignatureAlgorithms(
-                                                supportedPeerSignAlgs);
-            }
-
-            break;
-
-        case HandshakeMessage.ht_server_hello_done:
-            this.serverHelloDone(new ServerHelloDone(input));
-            break;
-
-        case HandshakeMessage.ht_finished:
-            this.serverFinished(
-                new Finished(protocolVersion, input, cipherSuite));
-            break;
-
-        default:
-            throw new SSLProtocolException(
-                "Illegal client handshake msg, " + type);
-        }
-
-        //
-        // Move state machine forward if the message handling
-        // code didn't already do so
-        //
-        if (state < type) {
-            state = type;
-        }
-    }
-
-    /*
-     * Used by the server to kickstart negotiations -- this requests a
-     * "client hello" to renegotiate current cipher specs (e.g. maybe lots
-     * of data has been encrypted with the same keys, or the server needs
-     * the client to present a certificate).
-     */
-    private void serverHelloRequest(HelloRequest mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        //
-        // Could be (e.g. at connection setup) that we already
-        // sent the "client hello" but the server's not seen it.
-        //
-        if (state < HandshakeMessage.ht_client_hello) {
-            if (!secureRenegotiation && !allowUnsafeRenegotiation) {
-                // renegotiation is not allowed.
-                if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    // response with a no_renegotiation warning,
-                    warningSE(Alerts.alert_no_renegotiation);
-
-                    // invalidate the handshake so that the caller can
-                    // dispose this object.
-                    invalidated = true;
-
-                    // If there is still unread block in the handshake
-                    // input stream, it would be truncated with the disposal
-                    // and the next handshake message will become incomplete.
-                    //
-                    // However, according to SSL/TLS specifications, no more
-                    // handshake message should immediately follow ClientHello
-                    // or HelloRequest. So just let it be.
-                } else {
-                    // For SSLv3, send the handshake_failure fatal error.
-                    // Note that SSLv3 does not define a no_renegotiation
-                    // alert like TLSv1. However we cannot ignore the message
-                    // simply, otherwise the other side was waiting for a
-                    // response that would never come.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Renegotiation is not allowed");
-                }
-            } else {
-                if (!secureRenegotiation) {
-                    if (debug != null && Debug.isOn("handshake")) {
-                        System.out.println(
-                            "Warning: continue with insecure renegotiation");
-                    }
-                }
-                kickstart();
-            }
-        }
-    }
-
-
-    /*
-     * Server chooses session parameters given options created by the
-     * client -- basically, cipher options, session id, and someday a
-     * set of compression options.
-     *
-     * There are two branches of the state machine, decided by the
-     * details of this message.  One is the "fast" handshake, where we
-     * can resume the pre-existing session we asked resume.  The other
-     * is a more expensive "full" handshake, with key exchange and
-     * probably authentication getting done.
-     */
-    private void serverHello(ServerHello mesg) throws IOException {
-        serverKeyExchangeReceived = false;
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // check if the server selected protocol version is OK for us
-        ProtocolVersion mesgVersion = mesg.protocolVersion;
-        if (!isNegotiable(mesgVersion)) {
-            throw new SSLHandshakeException(
-                "Server chose " + mesgVersion +
-                ", but that protocol version is not enabled or not supported " +
-                "by the client.");
-        }
-
-        handshakeHash.protocolDetermined(mesgVersion);
-
-        // Set protocolVersion and propagate to SSLSocket and the
-        // Handshake streams
-        setVersion(mesgVersion);
-
-        // check the "renegotiation_info" extension
-        RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
-                    mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
-        if (serverHelloRI != null) {
-            if (isInitialHandshake) {
-                // verify the length of the "renegotiated_connection" field
-                if (!serverHelloRI.isEmpty()) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info field is not empty");
-                }
-
-                secureRenegotiation = true;
-            } else {
-                // For a legacy renegotiation, the client MUST verify that
-                // it does not contain the "renegotiation_info" extension.
-                if (!secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Unexpected renegotiation indication extension");
-                }
-
-                // verify the client_verify_data and server_verify_data values
-                byte[] verifyData =
-                    new byte[clientVerifyData.length + serverVerifyData.length];
-                System.arraycopy(clientVerifyData, 0, verifyData,
-                        0, clientVerifyData.length);
-                System.arraycopy(serverVerifyData, 0, verifyData,
-                        clientVerifyData.length, serverVerifyData.length);
-                if (!Arrays.equals(verifyData,
-                                serverHelloRI.getRenegotiatedConnection())) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Incorrect verify data in ServerHello " +
-                        "renegotiation_info message");
-                }
-            }
-        } else {
-            // no renegotiation indication extension
-            if (isInitialHandshake) {
-                if (!allowLegacyHelloMessages) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Failed to negotiate the use of secure renegotiation");
-                }
-
-                secureRenegotiation = false;
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Warning: No renegotiation " +
-                                    "indication extension in ServerHello");
-                }
-            } else {
-                // For a secure renegotiation, the client must abort the
-                // handshake if no "renegotiation_info" extension is present.
-                if (secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "No renegotiation indication extension");
-                }
-
-                // we have already allowed unsafe renegotation before request
-                // the renegotiation.
-            }
-        }
-
-        //
-        // Save server nonce, we always use it to compute connection
-        // keys and it's also used to create the master secret if we're
-        // creating a new session (i.e. in the full handshake).
-        //
-        svr_random = mesg.svr_random;
-
-        if (isNegotiable(mesg.cipherSuite) == false) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                "Server selected improper ciphersuite " + mesg.cipherSuite);
-        }
-
-        setCipherSuite(mesg.cipherSuite);
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
-        }
-
-        if (mesg.compression_method != 0) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                "compression type not supported, "
-                + mesg.compression_method);
-            // NOTREACHED
-        }
-
-        // so far so good, let's look at the session
-        if (session != null) {
-            // we tried to resume, let's see what the server decided
-            if (session.getSessionId().equals(mesg.sessionId)) {
-                // server resumed the session, let's make sure everything
-                // checks out
-
-                // Verify that the session ciphers are unchanged.
-                CipherSuite sessionSuite = session.getSuite();
-                if (cipherSuite != sessionSuite) {
-                    throw new SSLProtocolException
-                        ("Server returned wrong cipher suite for session");
-                }
-
-                // verify protocol version match
-                ProtocolVersion sessionVersion = session.getProtocolVersion();
-                if (protocolVersion != sessionVersion) {
-                    throw new SSLProtocolException
-                        ("Server resumed session with wrong protocol version");
-                }
-
-                // validate subject identity
-                if (sessionSuite.keyExchange == K_KRB5 ||
-                    sessionSuite.keyExchange == K_KRB5_EXPORT) {
-                    Principal localPrincipal = session.getLocalPrincipal();
-
-                    Subject subject = null;
-                    try {
-                        subject = AccessController.doPrivileged(
-                            new PrivilegedExceptionAction<Subject>() {
-                            public Subject run() throws Exception {
-                                return Krb5Helper.getClientSubject(getAccSE());
-                            }});
-                    } catch (PrivilegedActionException e) {
-                        subject = null;
-                        if (debug != null && Debug.isOn("session")) {
-                            System.out.println("Attempt to obtain" +
-                                        " subject failed!");
-                        }
-                    }
-
-                    if (subject != null) {
-                        // Eliminate dependency on KerberosPrincipal
-                        Set<Principal> principals =
-                            subject.getPrincipals(Principal.class);
-                        if (!principals.contains(localPrincipal)) {
-                            throw new SSLProtocolException("Server resumed" +
-                                " session with wrong subject identity");
-                        } else {
-                            if (debug != null && Debug.isOn("session"))
-                                System.out.println("Subject identity is same");
-                        }
-                    } else {
-                        if (debug != null && Debug.isOn("session"))
-                            System.out.println("Kerberos credentials are not" +
-                                " present in the current Subject; check if " +
-                                " javax.security.auth.useSubjectAsCreds" +
-                                " system property has been set to false");
-                        throw new SSLProtocolException
-                            ("Server resumed session with no subject");
-                    }
-                }
-
-                // looks fine; resume it, and update the state machine.
-                resumingSession = true;
-                state = HandshakeMessage.ht_finished - 1;
-                calculateConnectionKeys(session.getMasterSecret());
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% Server resumed " + session);
-                }
-            } else {
-                // we wanted to resume, but the server refused
-                session = null;
-                if (!enableNewSession) {
-                    throw new SSLException
-                        ("New session creation is disabled");
-                }
-            }
-        }
-
-        if (resumingSession && session != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                handshakeHash.setCertificateVerifyAlg(null);
-            }
-
-            setHandshakeSessionSE(session);
-            return;
-        }
-
-        // check extensions
-        for (HelloExtension ext : mesg.extensions.list()) {
-            ExtensionType type = ext.type;
-            if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
-                    && (type != ExtensionType.EXT_EC_POINT_FORMATS)
-                    && (type != ExtensionType.EXT_SERVER_NAME)
-                    && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
-                fatalSE(Alerts.alert_unsupported_extension,
-                    "Server sent an unsupported extension: " + type);
-            }
-        }
-
-        // Create a new session, we need to do the full handshake
-        session = new SSLSessionImpl(protocolVersion, cipherSuite,
-                            getLocalSupportedSignAlgs(),
-                            mesg.sessionId, getHostSE(), getPortSE());
-        setHandshakeSessionSE(session);
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("** " + cipherSuite);
-        }
-    }
-
-    /*
-     * Server's own key was either a signing-only key, or was too
-     * large for export rules ... this message holds an ephemeral
-     * RSA key to use for key exchange.
-     */
-    private void serverKeyExchange(RSA_ServerKeyExchange mesg)
-            throws IOException, GeneralSecurityException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        if (!mesg.verify(serverKey, clnt_random, svr_random)) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "server key exchange invalid");
-            // NOTREACHED
-        }
-        ephemeralServerKey = mesg.getPublicKey();
-    }
-
-
-    /*
-     * Diffie-Hellman key exchange.  We save the server public key and
-     * our own D-H algorithm object so we can defer key calculations
-     * until after we've sent the client key exchange message (which
-     * gives client and server some useful parallelism).
-     */
-    private void serverKeyExchange(DH_ServerKeyExchange mesg)
-            throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
-                                            sslContext.getSecureRandom());
-        serverDH = mesg.getServerPublicKey();
-    }
-
-    private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
-            throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        ECPublicKey key = mesg.getPublicKey();
-        ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom());
-        ephemeralServerKey = key;
-    }
-
-    /*
-     * The server's "Hello Done" message is the client's sign that
-     * it's time to do all the hard work.
-     */
-    private void serverHelloDone(ServerHelloDone mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        /*
-         * Always make sure the input has been digested before we
-         * start emitting data, to ensure the hashes are correctly
-         * computed for the Finished and CertificateVerify messages
-         * which we send (here).
-         */
-        input.digestNow();
-
-        /*
-         * FIRST ... if requested, send an appropriate Certificate chain
-         * to authenticate the client, and remember the associated private
-         * key to sign the CertificateVerify message.
-         */
-        PrivateKey signingKey = null;
-
-        if (certRequest != null) {
-            X509ExtendedKeyManager km = sslContext.getX509KeyManager();
-
-            ArrayList<String> keytypesTmp = new ArrayList<>(4);
-
-            for (int i = 0; i < certRequest.types.length; i++) {
-                String typeName;
-
-                switch (certRequest.types[i]) {
-                case CertificateRequest.cct_rsa_sign:
-                    typeName = "RSA";
-                    break;
-
-                case CertificateRequest.cct_dss_sign:
-                    typeName = "DSA";
-                    break;
-
-                case CertificateRequest.cct_ecdsa_sign:
-                    // ignore if we do not have EC crypto available
-                    typeName = JsseJce.isEcAvailable() ? "EC" : null;
-                    break;
-
-                // Fixed DH/ECDH client authentication not supported
-                case CertificateRequest.cct_rsa_fixed_dh:
-                case CertificateRequest.cct_dss_fixed_dh:
-                case CertificateRequest.cct_rsa_fixed_ecdh:
-                case CertificateRequest.cct_ecdsa_fixed_ecdh:
-                // Any other values (currently not used in TLS)
-                case CertificateRequest.cct_rsa_ephemeral_dh:
-                case CertificateRequest.cct_dss_ephemeral_dh:
-                default:
-                    typeName = null;
-                    break;
-                }
-
-                if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
-                    keytypesTmp.add(typeName);
-                }
-            }
-
-            String alias = null;
-            int keytypesTmpSize = keytypesTmp.size();
-            if (keytypesTmpSize != 0) {
-                String keytypes[] =
-                        keytypesTmp.toArray(new String[keytypesTmpSize]);
-
-                if (conn != null) {
-                    alias = km.chooseClientAlias(keytypes,
-                        certRequest.getAuthorities(), conn);
-                } else {
-                    alias = km.chooseEngineClientAlias(keytypes,
-                        certRequest.getAuthorities(), engine);
-                }
-            }
-
-            CertificateMsg m1 = null;
-            if (alias != null) {
-                X509Certificate[] certs = km.getCertificateChain(alias);
-                if ((certs != null) && (certs.length != 0)) {
-                    PublicKey publicKey = certs[0].getPublicKey();
-                    // for EC, make sure we use a supported named curve
-                    if (publicKey instanceof ECPublicKey) {
-                        ECParameterSpec params =
-                            ((ECPublicKey)publicKey).getParams();
-                        int index =
-                            SupportedEllipticCurvesExtension.getCurveIndex(
-                                params);
-                        if (!SupportedEllipticCurvesExtension.isSupported(
-                                index)) {
-                            publicKey = null;
-                        }
-                    }
-                    if (publicKey != null) {
-                        m1 = new CertificateMsg(certs);
-                        signingKey = km.getPrivateKey(alias);
-                        session.setLocalPrivateKey(signingKey);
-                        session.setLocalCertificates(certs);
-                    }
-                }
-            }
-            if (m1 == null) {
-                //
-                // No appropriate cert was found ... report this to the
-                // server.  For SSLv3, send the no_certificate alert;
-                // TLS uses an empty cert chain instead.
-                //
-                if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    m1 = new CertificateMsg(new X509Certificate [0]);
-                } else {
-                    warningSE(Alerts.alert_no_certificate);
-                }
-            }
-
-            //
-            // At last ... send any client certificate chain.
-            //
-            if (m1 != null) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    m1.print(System.out);
-                }
-                m1.write(output);
-            }
-        }
-
-        /*
-         * SECOND ... send the client key exchange message.  The
-         * procedure used is a function of the cipher suite selected;
-         * one is always needed.
-         */
-        HandshakeMessage m2;
-
-        switch (keyExchange) {
-
-        case K_RSA:
-        case K_RSA_EXPORT:
-            if (serverKey == null) {
-                throw new SSLProtocolException
-                        ("Server did not send certificate message");
-            }
-
-            if (!(serverKey instanceof RSAPublicKey)) {
-                throw new SSLProtocolException
-                        ("Server certificate does not include an RSA key");
-            }
-
-            /*
-             * For RSA key exchange, we randomly generate a new
-             * pre-master secret and encrypt it with the server's
-             * public key.  Then we save that pre-master secret
-             * so that we can calculate the keying data later;
-             * it's a performance speedup not to do that until
-             * the client's waiting for the server response, but
-             * more of a speedup for the D-H case.
-             *
-             * If the RSA_EXPORT scheme is active, when the public
-             * key in the server certificate is less than or equal
-             * to 512 bits in length, use the cert's public key,
-             * otherwise, the ephemeral one.
-             */
-            PublicKey key;
-            if (keyExchange == K_RSA) {
-                key = serverKey;
-            } else {    // K_RSA_EXPORT
-                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
-                    // extraneous ephemeralServerKey check done
-                    // above in processMessage()
-                    key = serverKey;
-                } else {
-                    if (ephemeralServerKey == null) {
-                        throw new SSLProtocolException("Server did not send" +
-                            " a RSA_EXPORT Server Key Exchange message");
-                    }
-                    key = ephemeralServerKey;
-                }
-            }
-
-            m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion,
-                                sslContext.getSecureRandom(), key);
-            break;
-        case K_DH_RSA:
-        case K_DH_DSS:
-            /*
-             * For DH Key exchange, we only need to make sure the server
-             * knows our public key, so we calculate the same pre-master
-             * secret.
-             *
-             * For certs that had DH keys in them, we send an empty
-             * handshake message (no key) ... we flag this case by
-             * passing a null "dhPublic" value.
-             *
-             * Otherwise we send ephemeral DH keys, unsigned.
-             */
-            // if (useDH_RSA || useDH_DSS)
-            m2 = new DHClientKeyExchange();
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-        case K_DH_ANON:
-            if (dh == null) {
-                throw new SSLProtocolException
-                    ("Server did not send a DH Server Key Exchange message");
-            }
-            m2 = new DHClientKeyExchange(dh.getPublicKey());
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            if (ecdh == null) {
-                throw new SSLProtocolException
-                    ("Server did not send a ECDH Server Key Exchange message");
-            }
-            m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            if (serverKey == null) {
-                throw new SSLProtocolException
-                        ("Server did not send certificate message");
-            }
-            if (serverKey instanceof ECPublicKey == false) {
-                throw new SSLProtocolException
-                        ("Server certificate does not include an EC key");
-            }
-            ECParameterSpec params = ((ECPublicKey)serverKey).getParams();
-            ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
-            m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            String hostname = getHostSE();
-            if (hostname == null) {
-                throw new IOException("Hostname is required" +
-                                " to use Kerberos cipher suites");
-            }
-            KerberosClientKeyExchange kerberosMsg =
-                new KerberosClientKeyExchange(
-                    hostname, isLoopbackSE(), getAccSE(), protocolVersion,
-                sslContext.getSecureRandom());
-            // Record the principals involved in exchange
-            session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
-            session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
-            m2 = kerberosMsg;
-            break;
-        default:
-            // somethings very wrong
-            throw new RuntimeException
-                                ("Unsupported key exchange: " + keyExchange);
-        }
-        if (debug != null && Debug.isOn("handshake")) {
-            m2.print(System.out);
-        }
-        m2.write(output);
-
-
-        /*
-         * THIRD, send a "change_cipher_spec" record followed by the
-         * "Finished" message.  We flush the messages we've queued up, to
-         * get concurrency between client and server.  The concurrency is
-         * useful as we calculate the master secret, which is needed both
-         * to compute the "Finished" message, and to compute the keys used
-         * to protect all records following the change_cipher_spec.
-         */
-
-        output.doHashes();
-        output.flush();
-
-        /*
-         * We deferred calculating the master secret and this connection's
-         * keying data; we do it now.  Deferring this calculation is good
-         * from a performance point of view, since it lets us do it during
-         * some time that network delays and the server's own calculations
-         * would otherwise cause to be "dead" in the critical path.
-         */
-        SecretKey preMasterSecret;
-        switch (keyExchange) {
-        case K_RSA:
-        case K_RSA_EXPORT:
-            preMasterSecret = ((RSAClientKeyExchange)m2).preMaster;
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            byte[] secretBytes =
-                ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
-            preMasterSecret = new SecretKeySpec(secretBytes,
-                "TlsPremasterSecret");
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-        case K_DH_ANON:
-            preMasterSecret = dh.getAgreedSecret(serverDH, true);
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey);
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            preMasterSecret = ecdh.getAgreedSecret(serverKey);
-            break;
-        default:
-            throw new IOException("Internal error: unknown key exchange "
-                + keyExchange);
-        }
-
-        calculateKeys(preMasterSecret, null);
-
-        /*
-         * FOURTH, if we sent a Certificate, we need to send a signed
-         * CertificateVerify (unless the key in the client's certificate
-         * was a Diffie-Hellman key).).
-         *
-         * This uses a hash of the previous handshake messages ... either
-         * a nonfinal one (if the particular implementation supports it)
-         * or else using the third element in the arrays of hashes being
-         * computed.
-         */
-        if (signingKey != null) {
-            CertificateVerify m3;
-            try {
-                SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    preferableSignatureAlgorithm =
-                        SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                            peerSupportedSignAlgs, signingKey.getAlgorithm(),
-                            signingKey);
-
-                    if (preferableSignatureAlgorithm == null) {
-                        throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                    }
-
-                    String hashAlg =
-                        SignatureAndHashAlgorithm.getHashAlgorithmName(
-                                preferableSignatureAlgorithm);
-                    if (hashAlg == null || hashAlg.length() == 0) {
-                        throw new SSLHandshakeException(
-                                "No supported hash algorithm");
-                    }
-
-                    handshakeHash.setCertificateVerifyAlg(hashAlg);
-                }
-
-                m3 = new CertificateVerify(protocolVersion, handshakeHash,
-                    signingKey, session.getMasterSecret(),
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm);
-            } catch (GeneralSecurityException e) {
-                fatalSE(Alerts.alert_handshake_failure,
-                    "Error signing certificate verify", e);
-                // NOTREACHED, make compiler happy
-                m3 = null;
-            }
-            if (debug != null && Debug.isOn("handshake")) {
-                m3.print(System.out);
-            }
-            m3.write(output);
-            output.doHashes();
-        } else {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                handshakeHash.setCertificateVerifyAlg(null);
-            }
-        }
-
-        /*
-         * OK, that's that!
-         */
-        sendChangeCipherAndFinish(false);
-    }
-
-
-    /*
-     * "Finished" is the last handshake message sent.  If we got this
-     * far, the MAC has been validated post-decryption.  We validate
-     * the two hashes here as an additional sanity check, protecting
-     * the handshake against various active attacks.
-     */
-    private void serverFinished(Finished mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
-            session.getMasterSecret());
-
-        if (!verified) {
-            fatalSE(Alerts.alert_illegal_parameter,
-                       "server 'finished' message doesn't verify");
-            // NOTREACHED
-        }
-
-        /*
-         * save server verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            serverVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * OK, it verified.  If we're doing the fast handshake, add that
-         * "Finished" message to the hash of handshake messages, then send
-         * our own change_cipher_spec and Finished message for the server
-         * to verify in turn.  These are the last handshake messages.
-         *
-         * In any case, update the session cache.  We're done handshaking,
-         * so there are no threats any more associated with partially
-         * completed handshakes.
-         */
-        if (resumingSession) {
-            input.digestNow();
-            sendChangeCipherAndFinish(true);
-        }
-        session.setLastAccessedTime(System.currentTimeMillis());
-
-        if (!resumingSession) {
-            if (session.isRejoinable()) {
-                ((SSLSessionContextImpl) sslContext
-                        .engineGetClientSessionContext())
-                        .put(session);
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% Cached client session: " + session);
-                }
-            } else if (debug != null && Debug.isOn("session")) {
-                System.out.println(
-                    "%% Didn't cache non-resumable client session: "
-                    + session);
-            }
-        }
-    }
-
-
-    /*
-     * Send my change-cipher-spec and Finished message ... done as the
-     * last handshake act in either the short or long sequences.  In
-     * the short one, we've already seen the server's Finished; in the
-     * long one, we wait for it now.
-     */
-    private void sendChangeCipherAndFinish(boolean finishedTag)
-            throws IOException {
-        Finished mesg = new Finished(protocolVersion, handshakeHash,
-            Finished.CLIENT, session.getMasterSecret(), cipherSuite);
-
-        /*
-         * Send the change_cipher_spec message, then the Finished message
-         * which we just calculated (and protected using the keys we just
-         * calculated).  Server responds with its Finished message, except
-         * in the "fast handshake" (resume session) case.
-         */
-        sendChangeCipherSpec(mesg, finishedTag);
-
-        /*
-         * save client verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            clientVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * Update state machine so server MUST send 'finished' next.
-         * (In "long" handshake case; in short case, we're responding
-         * to its message.)
-         */
-        state = HandshakeMessage.ht_finished - 1;
-    }
-
-
-    /*
-     * Returns a ClientHello message to kickstart renegotiations
-     */
-    HandshakeMessage getKickstartMessage() throws SSLException {
-        // session ID of the ClientHello message
-        SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
-
-        // a list of cipher suites sent by the client
-        CipherSuiteList cipherSuites = getActiveCipherSuites();
-
-        // set the max protocol version this client is supporting.
-        maxProtocolVersion = protocolVersion;
-
-        //
-        // Try to resume an existing session.  This might be mandatory,
-        // given certain API options.
-        //
-        session = ((SSLSessionContextImpl)sslContext
-                        .engineGetClientSessionContext())
-                        .get(getHostSE(), getPortSE());
-        if (debug != null && Debug.isOn("session")) {
-            if (session != null) {
-                System.out.println("%% Client cached "
-                    + session
-                    + (session.isRejoinable() ? "" : " (not rejoinable)"));
-            } else {
-                System.out.println("%% No cached client session");
-            }
-        }
-        if ((session != null) && (session.isRejoinable() == false)) {
-            session = null;
-        }
-
-        if (session != null) {
-            CipherSuite sessionSuite = session.getSuite();
-            ProtocolVersion sessionVersion = session.getProtocolVersion();
-            if (isNegotiable(sessionSuite) == false) {
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% can't resume, unavailable cipher");
-                }
-                session = null;
-            }
-
-            if ((session != null) && !isNegotiable(sessionVersion)) {
-                if (debug != null && Debug.isOn("session")) {
-                    System.out.println("%% can't resume, protocol disabled");
-                }
-                session = null;
-            }
-
-            if (session != null) {
-                if (debug != null) {
-                    if (Debug.isOn("handshake") || Debug.isOn("session")) {
-                        System.out.println("%% Try resuming " + session
-                            + " from port " + getLocalPortSE());
-                    }
-                }
-
-                sessionId = session.getSessionId();
-                maxProtocolVersion = sessionVersion;
-
-                // Update SSL version number in underlying SSL socket and
-                // handshake output stream, so that the output records (at the
-                // record layer) have the correct version
-                setVersion(sessionVersion);
-            }
-
-            /*
-             * Force use of the previous session ciphersuite, and
-             * add the SCSV if enabled.
-             */
-            if (!enableNewSession) {
-                if (session == null) {
-                    throw new SSLHandshakeException(
-                        "Can't reuse existing SSL client session");
-                }
-
-                Collection<CipherSuite> cipherList = new ArrayList<>(2);
-                cipherList.add(sessionSuite);
-                if (!secureRenegotiation &&
-                        cipherSuites.contains(CipherSuite.C_SCSV)) {
-                    cipherList.add(CipherSuite.C_SCSV);
-                }   // otherwise, renegotiation_info extension will be used
-
-                cipherSuites = new CipherSuiteList(cipherList);
-            }
-        }
-
-        if (session == null && !enableNewSession) {
-            throw new SSLHandshakeException("No existing session to resume");
-        }
-
-        // exclude SCSV for secure renegotiation
-        if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
-            Collection<CipherSuite> cipherList =
-                        new ArrayList<>(cipherSuites.size() - 1);
-            for (CipherSuite suite : cipherSuites.collection()) {
-                if (suite != CipherSuite.C_SCSV) {
-                    cipherList.add(suite);
-                }
-            }
-
-            cipherSuites = new CipherSuiteList(cipherList);
-        }
-
-        // make sure there is a negotiable cipher suite.
-        boolean negotiable = false;
-        for (CipherSuite suite : cipherSuites.collection()) {
-            if (isNegotiable(suite)) {
-                negotiable = true;
-                break;
-            }
-        }
-
-        if (!negotiable) {
-            throw new SSLHandshakeException("No negotiable cipher suite");
-        }
-
-        // Not a TLS1.2+ handshake
-        // For SSLv2Hello, HandshakeHash.reset() will be called, so we
-        // cannot call HandshakeHash.protocolDetermined() here. As it does
-        // not follow the spec that HandshakeHash.reset() can be only be
-        // called before protocolDetermined.
-        // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
-        //     handshakeHash.protocolDetermined(maxProtocolVersion);
-        // }
-
-        // create the ClientHello message
-        ClientHello clientHelloMessage = new ClientHello(
-                sslContext.getSecureRandom(), maxProtocolVersion,
-                sessionId, cipherSuites);
-
-        // add signature_algorithm extension
-        if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
-            // we will always send the signature_algorithm extension
-            Collection<SignatureAndHashAlgorithm> localSignAlgs =
-                                                getLocalSupportedSignAlgs();
-            if (localSignAlgs.isEmpty()) {
-                throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-            }
-
-            clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
-        }
-
-        // add server_name extension
-        if (enableSNIExtension) {
-            // We cannot use the hostname resolved from name services.  For
-            // virtual hosting, multiple hostnames may be bound to the same IP
-            // address, so the hostname resolved from name services is not
-            // reliable.
-            String hostname = getRawHostnameSE();
-
-            // we only allow FQDN
-            if (hostname != null && hostname.indexOf('.') > 0 &&
-                    !IPAddressUtil.isIPv4LiteralAddress(hostname) &&
-                    !IPAddressUtil.isIPv6LiteralAddress(hostname)) {
-                clientHelloMessage.addServerNameIndicationExtension(hostname);
-            }
-        }
-
-        // reset the client random cookie
-        clnt_random = clientHelloMessage.clnt_random;
-
-        /*
-         * need to set the renegotiation_info extension for:
-         * 1: secure renegotiation
-         * 2: initial handshake and no SCSV in the ClientHello
-         * 3: insecure renegotiation and no SCSV in the ClientHello
-         */
-        if (secureRenegotiation ||
-                !cipherSuites.contains(CipherSuite.C_SCSV)) {
-            clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
-        }
-
-        return clientHelloMessage;
-    }
-
-    /*
-     * Fault detected during handshake.
-     */
-    void handshakeAlert(byte description) throws SSLProtocolException {
-        String message = Alerts.alertDescription(description);
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("SSL - handshake alert: " + message);
-        }
-        throw new SSLProtocolException("handshake alert:  " + message);
-    }
-
-    /*
-     * Unless we are using an anonymous ciphersuite, the server always
-     * sends a certificate message (for the CipherSuites we currently
-     * support). The trust manager verifies the chain for us.
-     */
-    private void serverCertificate(CertificateMsg mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        X509Certificate[] peerCerts = mesg.getCertificateChain();
-        if (peerCerts.length == 0) {
-            fatalSE(Alerts.alert_bad_certificate,
-                "empty certificate chain");
-        }
-        // ask the trust manager to verify the chain
-        X509TrustManager tm = sslContext.getX509TrustManager();
-        try {
-            // find out the key exchange algorithm used
-            // use "RSA" for non-ephemeral "RSA_EXPORT"
-            String keyExchangeString;
-            if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) {
-                keyExchangeString = K_RSA.name;
-            } else {
-                keyExchangeString = keyExchange.name;
-            }
-
-            if (tm instanceof X509ExtendedTrustManager) {
-                if (conn != null) {
-                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        peerCerts.clone(),
-                        keyExchangeString,
-                        conn);
-                } else {
-                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        peerCerts.clone(),
-                        keyExchangeString,
-                        engine);
-                }
-            } else {
-                // Unlikely to happen, because we have wrapped the old
-                // X509TrustManager with the new X509ExtendedTrustManager.
-                throw new CertificateException(
-                    "Improper X509TrustManager implementation");
-            }
-        } catch (CertificateException e) {
-            // This will throw an exception, so include the original error.
-            fatalSE(Alerts.alert_certificate_unknown, e);
-        }
-        session.setPeerCertificates(peerCerts);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java
deleted file mode 100755
index b450098..0000000
--- a/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.math.BigInteger;
-import javax.net.ssl.SSLHandshakeException;
-
-/*
- * Message used by clients to send their Diffie-Hellman public
- * keys to servers.
- *
- * @author David Brownell
- */
-final class DHClientKeyExchange extends HandshakeMessage {
-
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    /*
-     * This value may be empty if it was included in the
-     * client's certificate ...
-     */
-    private byte dh_Yc[];               // 1 to 2^16 -1 bytes
-
-    BigInteger getClientPublicKey() {
-        return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
-    }
-
-    /*
-     * Either pass the client's public key explicitly (because it's
-     * using DHE or DH_anon), or implicitly (the public key was in the
-     * certificate).
-     */
-    DHClientKeyExchange(BigInteger publicKey) {
-        dh_Yc = toByteArray(publicKey);
-    }
-
-    DHClientKeyExchange() {
-        dh_Yc = null;
-    }
-
-    /*
-     * Get the client's public key either explicitly or implicitly.
-     * (It's ugly to have an empty record be sent in the latter case,
-     * but that's what the protocol spec requires.)
-     */
-    DHClientKeyExchange(HandshakeInStream input) throws IOException {
-        if (input.available() >= 2) {
-            dh_Yc = input.getBytes16();
-        } else {
-            // currently, we don't support cipher suites that requires
-            // implicit public key of client.
-            throw new SSLHandshakeException(
-                    "Unsupported implicit client DiffieHellman public key");
-        }
-    }
-
-    int messageLength() {
-        if (dh_Yc == null) {
-            return 0;
-        } else {
-            return dh_Yc.length + 2;
-        }
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        if (dh_Yc != null && dh_Yc.length != 0) {
-            s.putBytes16(dh_Yc);
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** ClientKeyExchange, DH");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "DH Public key", dh_Yc);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/DHCrypt.java b/ojluni/src/main/java/sun/security/ssl/DHCrypt.java
deleted file mode 100755
index ae9118f..0000000
--- a/ojluni/src/main/java/sun/security/ssl/DHCrypt.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.math.BigInteger;
-import java.security.*;
-import java.io.IOException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.*;
-
-import sun.security.util.KeyUtil;
-
-/**
- * This class implements the Diffie-Hellman key exchange algorithm.
- * D-H means combining your private key with your partners public key to
- * generate a number. The peer does the same with its private key and our
- * public key. Through the magic of Diffie-Hellman we both come up with the
- * same number. This number is secret (discounting MITM attacks) and hence
- * called the shared secret. It has the same length as the modulus, e.g. 512
- * or 1024 bit. Man-in-the-middle attacks are typically countered by an
- * independent authentication step using certificates (RSA, DSA, etc.).
- *
- * The thing to note is that the shared secret is constant for two partners
- * with constant private keys. This is often not what we want, which is why
- * it is generally a good idea to create a new private key for each session.
- * Generating a private key involves one modular exponentiation assuming
- * suitable D-H parameters are available.
- *
- * General usage of this class (TLS DHE case):
- *  . if we are server, call DHCrypt(keyLength,random). This generates
- *    an ephemeral keypair of the request length.
- *  . if we are client, call DHCrypt(modulus, base, random). This
- *    generates an ephemeral keypair using the parameters specified by
- *    the server.
- *  . send parameters and public value to remote peer
- *  . receive peers ephemeral public key
- *  . call getAgreedSecret() to calculate the shared secret
- *
- * In TLS the server chooses the parameter values itself, the client must use
- * those sent to it by the server.
- *
- * The use of ephemeral keys as described above also achieves what is called
- * "forward secrecy". This means that even if the authentication keys are
- * broken at a later date, the shared secret remains secure. The session is
- * compromised only if the authentication keys are already broken at the
- * time the key exchange takes place and an active MITM attack is used.
- * This is in contrast to straightforward encrypting RSA key exchanges.
- *
- * @author David Brownell
- */
-final class DHCrypt {
-
-    // group parameters (prime modulus and generator)
-    private BigInteger modulus;                 // P (aka N)
-    private BigInteger base;                    // G (aka alpha)
-
-    // our private key (including private component x)
-    private PrivateKey privateKey;
-
-    // public component of our key, X = (g ^ x) mod p
-    private BigInteger publicValue;             // X (aka y)
-
-    // the times to recove from failure if public key validation
-    private static int MAX_FAILOVER_TIMES = 2;
-
-    /**
-     * Generate a Diffie-Hellman keypair of the specified size.
-     */
-    DHCrypt(int keyLength, SecureRandom random) {
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
-            kpg.initialize(keyLength, random);
-
-            DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
-            if (spec == null) {
-                throw new RuntimeException("Could not generate DH keypair");
-            }
-
-            publicValue = spec.getY();
-            modulus = spec.getP();
-            base = spec.getG();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-
-    /**
-     * Generate a Diffie-Hellman keypair using the specified parameters.
-     *
-     * @param modulus the Diffie-Hellman modulus P
-     * @param base the Diffie-Hellman base G
-     */
-    DHCrypt(BigInteger modulus, BigInteger base, SecureRandom random) {
-        this.modulus = modulus;
-        this.base = base;
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
-            DHParameterSpec params = new DHParameterSpec(modulus, base);
-            kpg.initialize(params, random);
-
-            DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
-            if (spec == null) {
-                throw new RuntimeException("Could not generate DH keypair");
-            }
-
-            publicValue = spec.getY();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-
-    static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
-        if (key instanceof DHPublicKey) {
-            DHPublicKey dhKey = (DHPublicKey)key;
-            DHParameterSpec params = dhKey.getParams();
-            return new DHPublicKeySpec(dhKey.getY(),
-                                    params.getP(), params.getG());
-        }
-        try {
-            KeyFactory factory = JsseJce.getKeyFactory("DH");
-            return factory.getKeySpec(key, DHPublicKeySpec.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    /** Returns the Diffie-Hellman modulus. */
-    BigInteger getModulus() {
-        return modulus;
-    }
-
-    /** Returns the Diffie-Hellman base (generator).  */
-    BigInteger getBase() {
-        return base;
-    }
-
-    /**
-     * Gets the public key of this end of the key exchange.
-     */
-    BigInteger getPublicKey() {
-        return publicValue;
-    }
-
-    /**
-     * Get the secret data that has been agreed on through Diffie-Hellman
-     * key agreement protocol.  Note that in the two party protocol, if
-     * the peer keys are already known, no other data needs to be sent in
-     * order to agree on a secret.  That is, a secured message may be
-     * sent without any mandatory round-trip overheads.
-     *
-     * <P>It is illegal to call this member function if the private key
-     * has not been set (or generated).
-     *
-     * @param  peerPublicKey the peer's public key.
-     * @param  keyIsValidated whether the {@code peerPublicKey} has beed
-     *         validated
-     * @return the secret, which is an unsigned big-endian integer
-     *         the same size as the Diffie-Hellman modulus.
-     */
-    SecretKey getAgreedSecret(BigInteger peerPublicValue,
-            boolean keyIsValidated) throws IOException {
-        try {
-            KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
-            DHPublicKeySpec spec =
-                        new DHPublicKeySpec(peerPublicValue, modulus, base);
-            PublicKey publicKey = kf.generatePublic(spec);
-            KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-
-            // validate the Diffie-Hellman public key
-            if (!keyIsValidated &&
-                    !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
-                try {
-                    KeyUtil.validate(spec);
-                } catch (InvalidKeyException ike) {
-                    // prefer handshake_failure alert to internal_error alert
-                    throw new SSLHandshakeException(ike.getMessage());
-                }
-            }
-
-            ka.init(privateKey);
-            ka.doPhase(publicKey, true);
-            return ka.generateSecret("TlsPremasterSecret");
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate secret", e);
-        }
-    }
-
-    // Generate and validate DHPublicKeySpec
-    private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
-            throws GeneralSecurityException {
-
-        boolean doExtraValiadtion =
-                    (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
-        for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-
-            // validate the Diffie-Hellman public key
-            if (doExtraValiadtion) {
-                try {
-                    KeyUtil.validate(spec);
-                } catch (InvalidKeyException ivke) {
-                    if (i == MAX_FAILOVER_TIMES) {
-                        throw ivke;
-                    }
-                    // otherwise, ignore the exception and try the next one
-                    continue;
-                }
-            }
-
-            return spec;
-        }
-
-        return null;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Debug.java b/ojluni/src/main/java/sun/security/ssl/Debug.java
deleted file mode 100755
index a270816..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Debug.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.PrintStream;
-import java.security.AccessController;
-import java.util.Locale;
-
-import sun.security.action.GetPropertyAction;
-
-/**
- * This class has be shamefully lifted from sun.security.util.Debug
- *
- * @author Gary Ellison
- */
-public class Debug {
-
-    private String prefix;
-
-    private static String args;
-
-    static {
-        args = java.security.AccessController.doPrivileged(
-            new GetPropertyAction("javax.net.debug", ""));
-        args = args.toLowerCase(Locale.ENGLISH);
-        if (args.equals("help")) {
-            Help();
-        }
-    }
-
-    public static void Help()
-    {
-        System.err.println();
-        System.err.println("all            turn on all debugging");
-        System.err.println("ssl            turn on ssl debugging");
-        System.err.println();
-        System.err.println("The following can be used with ssl:");
-        System.err.println("\trecord       enable per-record tracing");
-        System.err.println("\thandshake    print each handshake message");
-        System.err.println("\tkeygen       print key generation data");
-        System.err.println("\tsession      print session activity");
-        System.err.println("\tdefaultctx   print default SSL initialization");
-        System.err.println("\tsslctx       print SSLContext tracing");
-        System.err.println("\tsessioncache print session cache tracing");
-        System.err.println("\tkeymanager   print key manager tracing");
-        System.err.println("\ttrustmanager print trust manager tracing");
-        System.err.println("\tpluggability print pluggability tracing");
-        System.err.println();
-        System.err.println("\thandshake debugging can be widened with:");
-        System.err.println("\tdata         hex dump of each handshake message");
-        System.err.println("\tverbose      verbose handshake message printing");
-        System.err.println();
-        System.err.println("\trecord debugging can be widened with:");
-        System.err.println("\tplaintext    hex dump of record plaintext");
-        System.err.println("\tpacket       print raw SSL/TLS packets");
-        System.err.println();
-        System.exit(0);
-    }
-
-    /**
-     * Get a Debug object corresponding to whether or not the given
-     * option is set. Set the prefix to be the same as option.
-     */
-
-    public static Debug getInstance(String option)
-    {
-        return getInstance(option, option);
-    }
-
-    /**
-     * Get a Debug object corresponding to whether or not the given
-     * option is set. Set the prefix to be prefix.
-     */
-    public static Debug getInstance(String option, String prefix)
-    {
-        if (isOn(option)) {
-            Debug d = new Debug();
-            d.prefix = prefix;
-            return d;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * True if the property "javax.net.debug" contains the
-     * string "option".
-     */
-    public static boolean isOn(String option)
-    {
-        if (args == null) {
-            return false;
-        } else {
-            int n = 0;
-            option = option.toLowerCase(Locale.ENGLISH);
-
-            if (args.indexOf("all") != -1) {
-                return true;
-            } else if ((n = args.indexOf("ssl")) != -1) {
-                if (args.indexOf("sslctx", n) == -1) {
-                    // don't enable data and plaintext options by default
-                    if (!(option.equals("data")
-                        || option.equals("packet")
-                        || option.equals("plaintext"))) {
-                        return true;
-                    }
-                }
-            }
-            return (args.indexOf(option) != -1);
-        }
-    }
-
-    /**
-     * print a message to stderr that is prefixed with the prefix
-     * created from the call to getInstance.
-     */
-
-    public void println(String message)
-    {
-        System.err.println(prefix + ": "+message);
-    }
-
-    /**
-     * print a blank line to stderr that is prefixed with the prefix.
-     */
-
-    public void println()
-    {
-        System.err.println(prefix + ":");
-    }
-
-    /**
-     * print a message to stderr that is prefixed with the prefix.
-     */
-
-    public static void println(String prefix, String message)
-    {
-        System.err.println(prefix + ": "+message);
-    }
-
-    public static void println(PrintStream s, String name, byte[] data) {
-        s.print(name + ":  { ");
-        if (data == null) {
-            s.print("null");
-        } else {
-            for (int i = 0; i < data.length; i++) {
-                if (i != 0) s.print(", ");
-                s.print(data[i] & 0x0ff);
-            }
-        }
-        s.println(" }");
-    }
-
-    /**
-     * Return the value of the boolean System property propName.
-     *
-     * Note use of doPrivileged(). Do make accessible to applications.
-     */
-    static boolean getBooleanProperty(String propName, boolean defaultValue) {
-        // if set, require value of either true or false
-        String b = AccessController.doPrivileged(
-                new GetPropertyAction(propName));
-        if (b == null) {
-            return defaultValue;
-        } else if (b.equalsIgnoreCase("false")) {
-            return false;
-        } else if (b.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            throw new RuntimeException("Value of " + propName
-                + " must either be 'true' or 'false'");
-        }
-    }
-
-    static String toString(byte[] b) {
-        return sun.security.util.Debug.toString(b);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java
deleted file mode 100755
index d89945c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-
-import java.security.PublicKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-/**
- * ClientKeyExchange message for all ECDH based key exchange methods. It
- * contains the client's ephemeral public value.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class ECDHClientKeyExchange extends HandshakeMessage {
-
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    private byte[] encodedPoint;
-
-    byte[] getEncodedPoint() {
-        return encodedPoint;
-    }
-
-    // Called by the client with its ephemeral public key.
-    ECDHClientKeyExchange(PublicKey publicKey) {
-        ECPublicKey ecKey = (ECPublicKey)publicKey;
-        ECPoint point = ecKey.getW();
-        ECParameterSpec params = ecKey.getParams();
-        encodedPoint = JsseJce.encodePoint(point, params.getCurve());
-    }
-
-    ECDHClientKeyExchange(HandshakeInStream input) throws IOException {
-        encodedPoint = input.getBytes8();
-    }
-
-    int messageLength() {
-        return encodedPoint.length + 1;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes8(encodedPoint);
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** ECDHClientKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "ECDH Public value", encodedPoint);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java b/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java
deleted file mode 100755
index 84dc467..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.*;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.crypto.spec.*;
-
-/**
- * Helper class for the ECDH key exchange. It generates the appropriate
- * ephemeral keys as necessary and performs the actual shared secret derivation.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class ECDHCrypt {
-
-    // our private key
-    private PrivateKey privateKey;
-
-    // our public key
-    private ECPublicKey publicKey;
-
-    // Called by ServerHandshaker for static ECDH
-    ECDHCrypt(PrivateKey privateKey, PublicKey publicKey) {
-        this.privateKey = privateKey;
-        this.publicKey = (ECPublicKey)publicKey;
-    }
-
-    // Called by ServerHandshaker for ephemeral ECDH
-    ECDHCrypt(String curveName, SecureRandom random) {
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
-            ECGenParameterSpec params = new ECGenParameterSpec(curveName);
-            kpg.initialize(params, random);
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            publicKey = (ECPublicKey)kp.getPublic();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-    // Called by ClientHandshaker with params it received from the server
-    ECDHCrypt(ECParameterSpec params, SecureRandom random) {
-        try {
-            KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
-            kpg.initialize(params, random);
-            KeyPair kp = kpg.generateKeyPair();
-            privateKey = kp.getPrivate();
-            publicKey = (ECPublicKey)kp.getPublic();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate DH keypair", e);
-        }
-    }
-
-    /**
-     * Gets the public key of this end of the key exchange.
-     */
-    PublicKey getPublicKey() {
-        return publicKey;
-    }
-
-    // called by ClientHandshaker with either the server's static or ephemeral public key
-    SecretKey getAgreedSecret(PublicKey peerPublicKey) {
-        try {
-            KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
-            ka.init(privateKey);
-            ka.doPhase(peerPublicKey, true);
-            return ka.generateSecret("TlsPremasterSecret");
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate secret", e);
-        }
-    }
-
-    // called by ServerHandshaker
-    SecretKey getAgreedSecret(byte[] encodedPoint) {
-        try {
-            ECParameterSpec params = publicKey.getParams();
-            ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve());
-            KeyFactory kf = JsseJce.getKeyFactory("EC");
-            ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-            PublicKey peerPublicKey = kf.generatePublic(spec);
-            return getAgreedSecret(peerPublicKey);
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate secret", e);
-        } catch (java.io.IOException e) {
-            throw new RuntimeException("Could not generate secret", e);
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineArgs.java b/ojluni/src/main/java/sun/security/ssl/EngineArgs.java
deleted file mode 100755
index 5f89d0c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineArgs.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.nio.*;
-
-/*
- * A multi-purpose class which handles all of the SSLEngine arguments.
- * It validates arguments, checks for RO conditions, does space
- * calculations, performs scatter/gather, etc.
- *
- * @author Brad R. Wetmore
- */
-class EngineArgs {
-
-    /*
-     * Keep track of the input parameters.
-     */
-    ByteBuffer netData;
-    ByteBuffer [] appData;
-
-    private int offset;         // offset/len for the appData array.
-    private int len;
-
-    /*
-     * The initial pos/limit conditions.  This is useful because we can
-     * quickly calculate the amount consumed/produced in successful
-     * operations, or easily return the buffers to their pre-error
-     * conditions.
-     */
-    private int netPos;
-    private int netLim;
-
-    private int [] appPoss;
-    private int [] appLims;
-
-    /*
-     * Sum total of the space remaining in all of the appData buffers
-     */
-    private int appRemaining = 0;
-
-    private boolean wrapMethod;
-
-    /*
-     * Called by the SSLEngine.wrap() method.
-     */
-    EngineArgs(ByteBuffer [] appData, int offset, int len,
-            ByteBuffer netData) {
-        this.wrapMethod = true;
-        init(netData, appData, offset, len);
-    }
-
-    /*
-     * Called by the SSLEngine.unwrap() method.
-     */
-    EngineArgs(ByteBuffer netData, ByteBuffer [] appData, int offset,
-            int len) {
-        this.wrapMethod = false;
-        init(netData, appData, offset, len);
-    }
-
-    /*
-     * The main initialization method for the arguments.  Most
-     * of them are pretty obvious as to what they do.
-     *
-     * Since we're already iterating over appData array for validity
-     * checking, we also keep track of how much remainging space is
-     * available.  Info is used in both unwrap (to see if there is
-     * enough space available in the destination), and in wrap (to
-     * determine how much more we can copy into the outgoing data
-     * buffer.
-     */
-    private void init(ByteBuffer netData, ByteBuffer [] appData,
-            int offset, int len) {
-
-        if ((netData == null) || (appData == null)) {
-            throw new IllegalArgumentException("src/dst is null");
-        }
-
-        if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (wrapMethod && netData.isReadOnly()) {
-            throw new ReadOnlyBufferException();
-        }
-
-        netPos = netData.position();
-        netLim = netData.limit();
-
-        appPoss = new int [appData.length];
-        appLims = new int [appData.length];
-
-        for (int i = offset; i < offset + len; i++) {
-            if (appData[i] == null) {
-                throw new IllegalArgumentException(
-                    "appData[" + i + "] == null");
-            }
-
-            /*
-             * If we're unwrapping, then check to make sure our
-             * destination bufffers are writable.
-             */
-            if (!wrapMethod && appData[i].isReadOnly()) {
-                throw new ReadOnlyBufferException();
-            }
-
-            appRemaining += appData[i].remaining();
-
-            appPoss[i] = appData[i].position();
-            appLims[i] = appData[i].limit();
-        }
-
-        /*
-         * Ok, looks like we have a good set of args, let's
-         * store the rest of this stuff.
-         */
-        this.netData = netData;
-        this.appData = appData;
-        this.offset = offset;
-        this.len = len;
-    }
-
-    /*
-     * Given spaceLeft bytes to transfer, gather up that much data
-     * from the appData buffers (starting at offset in the array),
-     * and transfer it into the netData buffer.
-     *
-     * The user has already ensured there is enough room.
-     */
-    void gather(int spaceLeft) {
-        for (int i = offset; (i < (offset + len)) && (spaceLeft > 0); i++) {
-            int amount = Math.min(appData[i].remaining(), spaceLeft);
-            appData[i].limit(appData[i].position() + amount);
-            netData.put(appData[i]);
-            appRemaining -= amount;
-            spaceLeft -= amount;
-        }
-    }
-
-    /*
-     * Using the supplied buffer, scatter the data into the appData buffers
-     * (starting at offset in the array).
-     *
-     * The user has already ensured there is enough room.
-     */
-    void scatter(ByteBuffer readyData) {
-        int amountLeft = readyData.remaining();
-
-        for (int i = offset; (i < (offset + len)) && (amountLeft > 0);
-                i++) {
-            int amount = Math.min(appData[i].remaining(), amountLeft);
-            readyData.limit(readyData.position() + amount);
-            appData[i].put(readyData);
-            amountLeft -= amount;
-        }
-        assert(readyData.remaining() == 0);
-    }
-
-    int getAppRemaining() {
-        return appRemaining;
-    }
-
-    /*
-     * Calculate the bytesConsumed/byteProduced.  Aren't you glad
-     * we saved this off earlier?
-     */
-    int deltaNet() {
-        return (netData.position() - netPos);
-    }
-
-    /*
-     * Calculate the bytesConsumed/byteProduced.  Aren't you glad
-     * we saved this off earlier?
-     */
-    int deltaApp() {
-        int sum = 0;    // Only calculating 2^14 here, don't need a long.
-
-        for (int i = offset; i < offset + len; i++) {
-            sum += appData[i].position() - appPoss[i];
-        }
-
-        return sum;
-    }
-
-    /*
-     * In the case of Exception, we want to reset the positions
-     * to appear as though no data has been consumed or produced.
-     *
-     * Currently, this method is only called as we are preparing to
-     * fail out, and thus we don't need to actually recalculate
-     * appRemaining.  If that assumption changes, that variable should
-     * be updated here.
-     */
-    void resetPos() {
-        netData.position(netPos);
-        for (int i = offset; i < offset + len; i++) {
-            // See comment above about recalculating appRemaining.
-            appData[i].position(appPoss[i]);
-        }
-    }
-
-    /*
-     * We are doing lots of ByteBuffer manipulations, in which case
-     * we need to make sure that the limits get set back correctly.
-     * This is one of the last things to get done before returning to
-     * the user.
-     */
-    void resetLim() {
-        netData.limit(netLim);
-        for (int i = offset; i < offset + len; i++) {
-            appData[i].limit(appLims[i]);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java b/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java
deleted file mode 100755
index fb7b133..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import javax.net.ssl.*;
-import javax.crypto.BadPaddingException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * Wrapper class around InputRecord.
- *
- * Application data is kept external to the InputRecord,
- * but handshake data (alert/change_cipher_spec/handshake) will
- * be kept internally in the ByteArrayInputStream.
- *
- * @author Brad Wetmore
- */
-final class EngineInputRecord extends InputRecord {
-
-    private SSLEngineImpl engine;
-
-    /*
-     * A dummy ByteBuffer we'll pass back even when the data
-     * is stored internally.  It'll never actually be used.
-     */
-    static private ByteBuffer tmpBB = ByteBuffer.allocate(0);
-
-    /*
-     * Flag to tell whether the last read/parsed data resides
-     * internal in the ByteArrayInputStream, or in the external
-     * buffers.
-     */
-    private boolean internalData;
-
-    EngineInputRecord(SSLEngineImpl engine) {
-        super();
-        this.engine = engine;
-    }
-
-    byte contentType() {
-        if (internalData) {
-            return super.contentType();
-        } else {
-            return ct_application_data;
-        }
-    }
-
-    /*
-     * Check if there is enough inbound data in the ByteBuffer
-     * to make a inbound packet.  Look for both SSLv2 and SSLv3.
-     *
-     * @return -1 if there are not enough bytes to tell (small header),
-     */
-    int bytesInCompletePacket(ByteBuffer buf) throws SSLException {
-
-        /*
-         * SSLv2 length field is in bytes 0/1
-         * SSLv3/TLS length field is in bytes 3/4
-         */
-        if (buf.remaining() < 5) {
-            return -1;
-        }
-
-        int pos = buf.position();
-        byte byteZero = buf.get(pos);
-
-        int len = 0;
-
-        /*
-         * If we have already verified previous packets, we can
-         * ignore the verifications steps, and jump right to the
-         * determination.  Otherwise, try one last hueristic to
-         * see if it's SSL/TLS.
-         */
-        if (formatVerified ||
-                (byteZero == ct_handshake) ||
-                (byteZero == ct_alert)) {
-            /*
-             * Last sanity check that it's not a wild record
-             */
-            ProtocolVersion recordVersion =
-                ProtocolVersion.valueOf(buf.get(pos + 1), buf.get(pos + 2));
-
-            // Check if too old (currently not possible)
-            // or if the major version does not match.
-            // The actual version negotiation is in the handshaker classes
-            if ((recordVersion.v < ProtocolVersion.MIN.v)
-                    || (recordVersion.major > ProtocolVersion.MAX.major)) {
-                throw new SSLException(
-                    "Unsupported record version " + recordVersion);
-            }
-
-            /*
-             * Reasonably sure this is a V3, disable further checks.
-             * We can't do the same in the v2 check below, because
-             * read still needs to parse/handle the v2 clientHello.
-             */
-            formatVerified = true;
-
-            /*
-             * One of the SSLv3/TLS message types.
-             */
-            len = ((buf.get(pos + 3) & 0xff) << 8) +
-                (buf.get(pos + 4) & 0xff) + headerSize;
-
-        } else {
-            /*
-             * Must be SSLv2 or something unknown.
-             * Check if it's short (2 bytes) or
-             * long (3) header.
-             *
-             * Internals can warn about unsupported SSLv2
-             */
-            boolean isShort = ((byteZero & 0x80) != 0);
-
-            if (isShort &&
-                    ((buf.get(pos + 2) == 1) || buf.get(pos + 2) == 4)) {
-
-                ProtocolVersion recordVersion =
-                    ProtocolVersion.valueOf(buf.get(pos + 3), buf.get(pos + 4));
-
-                // Check if too old (currently not possible)
-                // or if the major version does not match.
-                // The actual version negotiation is in the handshaker classes
-                if ((recordVersion.v < ProtocolVersion.MIN.v)
-                        || (recordVersion.major > ProtocolVersion.MAX.major)) {
-
-                    // if it's not SSLv2, we're out of here.
-                    if (recordVersion.v != ProtocolVersion.SSL20Hello.v) {
-                        throw new SSLException(
-                            "Unsupported record version " + recordVersion);
-                    }
-                }
-
-                /*
-                 * Client or Server Hello
-                 */
-                int mask = (isShort ? 0x7f : 0x3f);
-                len = ((byteZero & mask) << 8) + (buf.get(pos + 1) & 0xff) +
-                    (isShort ? 2 : 3);
-
-            } else {
-                // Gobblygook!
-                throw new SSLException(
-                    "Unrecognized SSL message, plaintext connection?");
-            }
-        }
-
-        return len;
-    }
-
-    /*
-     * Pass the data down if it's internally cached, otherwise
-     * do it here.
-     *
-     * If internal data, data is decrypted internally.
-     *
-     * If external data(app), return a new ByteBuffer with data to
-     * process.
-     */
-    ByteBuffer decrypt(MAC signer,
-            CipherBox box, ByteBuffer bb) throws BadPaddingException {
-
-        if (internalData) {
-            decrypt(signer, box);   // MAC is checked during decryption
-            return tmpBB;
-        }
-
-        BadPaddingException reservedBPE = null;
-        int tagLen = signer.MAClen();
-        int cipheredLength = bb.remaining();
-
-        if (!box.isNullCipher()) {
-            // sanity check length of the ciphertext
-            if (!box.sanityCheck(tagLen, cipheredLength)) {
-                throw new BadPaddingException(
-                    "ciphertext sanity check failed");
-            }
-
-            try {
-                // Note that the CipherBox.decrypt() does not change
-                // the capacity of the buffer.
-                box.decrypt(bb, tagLen);
-            } catch (BadPaddingException bpe) {
-                // RFC 2246 states that decryption_failed should be used
-                // for this purpose. However, that allows certain attacks,
-                // so we just send bad record MAC. We also need to make
-                // sure to always check the MAC to avoid a timing attack
-                // for the same issue. See paper by Vaudenay et al and the
-                // update in RFC 4346/5246.
-                //
-                // Failover to message authentication code checking.
-                reservedBPE = bpe;
-            } finally {
-                bb.rewind();
-            }
-        }
-
-        if (tagLen != 0) {
-            int macOffset = bb.limit() - tagLen;
-
-            // Note that although it is not necessary, we run the same MAC
-            // computation and comparison on the payload for both stream
-            // cipher and CBC block cipher.
-            if (bb.remaining() < tagLen) {
-                // negative data length, something is wrong
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record");
-                }
-
-                // set offset of the dummy MAC
-                macOffset = cipheredLength - tagLen;
-                bb.limit(cipheredLength);
-            }
-
-            // Run MAC computation and comparison on the payload.
-            if (checkMacTags(contentType(), bb, signer, false)) {
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record MAC");
-                }
-            }
-
-            // Run MAC computation and comparison on the remainder.
-            //
-            // It is only necessary for CBC block cipher.  It is used to get a
-            // constant time of MAC computation and comparison on each record.
-            if (box.isCBCMode()) {
-                int remainingLen = calculateRemainingLen(
-                                        signer, cipheredLength, macOffset);
-
-                // NOTE: here we use the InputRecord.buf because I did not find
-                // an effective way to work on ByteBuffer when its capacity is
-                // less than remainingLen.
-
-                // NOTE: remainingLen may be bigger (less than 1 block of the
-                // hash algorithm of the MAC) than the cipheredLength. However,
-                // We won't need to worry about it because we always use a
-                // maximum buffer for every record.  We need a change here if
-                // we use small buffer size in the future.
-                if (remainingLen > buf.length) {
-                    // unlikely to happen, just a placehold
-                    throw new RuntimeException(
-                        "Internal buffer capacity error");
-                }
-
-                // Won't need to worry about the result on the remainder. And
-                // then we won't need to worry about what's actual data to
-                // check MAC tag on.  We start the check from the header of the
-                // buffer so that we don't need to construct a new byte buffer.
-                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
-            }
-
-            bb.limit(macOffset);
-        }
-
-        // Is it a failover?
-        if (reservedBPE != null) {
-            throw reservedBPE;
-        }
-
-        return bb.slice();
-    }
-
-    /*
-     * Run MAC computation and comparison
-     *
-     * Please DON'T change the content of the ByteBuffer parameter!
-     */
-    private static boolean checkMacTags(byte contentType, ByteBuffer bb,
-            MAC signer, boolean isSimulated) {
-
-        int tagLen = signer.MAClen();
-        int lim = bb.limit();
-        int macData = lim - tagLen;
-
-        bb.limit(macData);
-        byte[] hash = signer.compute(contentType, bb, isSimulated);
-        if (hash == null || tagLen != hash.length) {
-            // Something is wrong with MAC implementation.
-            throw new RuntimeException("Internal MAC error");
-        }
-
-        bb.position(macData);
-        bb.limit(lim);
-        try {
-            int[] results = compareMacTags(bb, hash);
-            return (results[0] != 0);
-        } finally {
-            bb.rewind();
-            bb.limit(macData);
-        }
-    }
-
-    /*
-     * A constant-time comparison of the MAC tags.
-     *
-     * Please DON'T change the content of the ByteBuffer parameter!
-     */
-    private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};     // {missed #, matched #}
-
-        // The caller ensures there are enough bytes available in the buffer.
-        // So we won't need to check the remaining of the buffer.
-        for (int i = 0; i < tag.length; i++) {
-            if (bb.get() != tag[i]) {
-                results[0]++;       // mismatched bytes
-            } else {
-                results[1]++;       // matched bytes
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Override the actual write below.  We do things this way to be
-     * consistent with InputRecord.  InputRecord may try to write out
-     * data to the peer, and *then* throw an Exception.  This forces
-     * data to be generated/output before the exception is ever
-     * generated.
-     */
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len)
-            throws IOException {
-        /*
-         * Copy data out of buffer, it's ready to go.
-         */
-        ByteBuffer netBB = (ByteBuffer)
-            (ByteBuffer.allocate(len).put(buf, 0, len).flip());
-        engine.writer.putOutboundDataSync(netBB);
-    }
-
-    /*
-     * Delineate or read a complete packet from src.
-     *
-     * If internal data (hs, alert, ccs), the data is read and
-     * stored internally.
-     *
-     * If external data (app), return a new ByteBuffer which points
-     * to the data to process.
-     */
-    ByteBuffer read(ByteBuffer srcBB) throws IOException {
-        /*
-         * Could have a src == null/dst == null check here,
-         * but that was already checked by SSLEngine.unwrap before
-         * ever attempting to read.
-         */
-
-        /*
-         * If we have anything besides application data,
-         * or if we haven't even done the initial v2 verification,
-         * we send this down to be processed by the underlying
-         * internal cache.
-         */
-        if (!formatVerified ||
-                (srcBB.get(srcBB.position()) != ct_application_data)) {
-            internalData = true;
-            read(new ByteBufferInputStream(srcBB), (OutputStream) null);
-            return tmpBB;
-        }
-
-        internalData = false;
-
-        int srcPos = srcBB.position();
-        int srcLim = srcBB.limit();
-
-        ProtocolVersion recordVersion = ProtocolVersion.valueOf(
-                srcBB.get(srcPos + 1), srcBB.get(srcPos + 2));
-        // Check if too old (currently not possible)
-        // or if the major version does not match.
-        // The actual version negotiation is in the handshaker classes
-        if ((recordVersion.v < ProtocolVersion.MIN.v)
-                || (recordVersion.major > ProtocolVersion.MAX.major)) {
-            throw new SSLException(
-                "Unsupported record version " + recordVersion);
-        }
-
-        /*
-         * It's really application data.  How much to consume?
-         * Jump over the header.
-         */
-        int len = bytesInCompletePacket(srcBB);
-        assert(len > 0);
-
-        if (debug != null && Debug.isOn("packet")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-                srcBB.limit(srcPos + len);
-                ByteBuffer bb = srcBB.duplicate();  // Use copy of BB
-
-                System.out.println("[Raw read (bb)]: length = " + len);
-                hd.encodeBuffer(bb, System.out);
-            } catch (IOException e) { }
-        }
-
-        // Demarcate past header to end of packet.
-        srcBB.position(srcPos + headerSize);
-        srcBB.limit(srcPos + len);
-
-        // Protect remainder of buffer, create slice to actually
-        // operate on.
-        ByteBuffer bb = srcBB.slice();
-
-        srcBB.position(srcBB.limit());
-        srcBB.limit(srcLim);
-
-        return bb;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java b/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java
deleted file mode 100755
index c7605fd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-
-import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * A OutputRecord class extension which uses external ByteBuffers
- * or the internal ByteArrayOutputStream for data manipulations.
- * <P>
- * Instead of rewriting this entire class
- * to use ByteBuffers, we leave things intact, so handshake, CCS,
- * and alerts will continue to use the internal buffers, but application
- * data will use external buffers.
- *
- * @author Brad Wetmore
- */
-final class EngineOutputRecord extends OutputRecord {
-
-    private SSLEngineImpl engine;
-    private EngineWriter writer;
-
-    private boolean finishedMsg = false;
-
-    /*
-     * All handshake hashing is done by the superclass
-     */
-
-    /*
-     * Default constructor makes a record supporting the maximum
-     * SSL record size.  It allocates the header bytes directly.
-     *
-     * @param type the content type for the record
-     */
-    EngineOutputRecord(byte type, SSLEngineImpl engine) {
-        super(type, recordSize(type));
-        this.engine = engine;
-        writer = engine.writer;
-    }
-
-    /**
-     * Get the size of the buffer we need for records of the specified
-     * type.
-     * <P>
-     * Application data buffers will provide their own byte buffers,
-     * and will not use the internal byte caching.
-     */
-    private static int recordSize(byte type) {
-        switch (type) {
-
-        case ct_change_cipher_spec:
-        case ct_alert:
-            return maxAlertRecordSize;
-
-        case ct_handshake:
-            return maxRecordSize;
-
-        case ct_application_data:
-            return 0;
-        }
-
-        throw new RuntimeException("Unknown record type: " + type);
-    }
-
-    void setFinishedMsg() {
-        finishedMsg = true;
-    }
-
-    public void flush() throws IOException {
-        finishedMsg = false;
-    }
-
-    boolean isFinishedMsg() {
-        return finishedMsg;
-    }
-
-
-    /**
-     * Calculate the MAC value, storing the result either in
-     * the internal buffer, or at the end of the destination
-     * ByteBuffer.
-     * <P>
-     * We assume that the higher levels have assured us enough
-     * room, otherwise we'll indirectly throw a
-     * BufferOverFlowException runtime exception.
-     *
-     * position should equal limit, and points to the next
-     * free spot.
-     */
-    private void addMAC(MAC signer, ByteBuffer bb)
-            throws IOException {
-
-        if (signer.MAClen() != 0) {
-            byte[] hash = signer.compute(contentType(), bb, false);
-
-            /*
-             * position was advanced to limit in compute above.
-             *
-             * Mark next area as writable (above layers should have
-             * established that we have plenty of room), then write
-             * out the hash.
-             */
-            bb.limit(bb.limit() + hash.length);
-            bb.put(hash);
-        }
-    }
-
-    /*
-     * Encrypt a ByteBuffer.
-     *
-     * We assume that the higher levels have assured us enough
-     * room for the encryption (plus padding), otherwise we'll
-     * indirectly throw a BufferOverFlowException runtime exception.
-     *
-     * position and limit will be the same, and points to the
-     * next free spot.
-     */
-    void encrypt(CipherBox box, ByteBuffer bb) {
-        box.encrypt(bb);
-    }
-
-    /*
-     * Override the actual write below.  We do things this way to be
-     * consistent with InputRecord.  InputRecord may try to write out
-     * data to the peer, and *then* throw an Exception.  This forces
-     * data to be generated/output before the exception is ever
-     * generated.
-     */
-    @Override
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len,
-            int debugOffset) throws IOException {
-        /*
-         * Copy data out of buffer, it's ready to go.
-         */
-        ByteBuffer netBB = (ByteBuffer)
-            ByteBuffer.allocate(len).put(buf, 0, len).flip();
-        writer.putOutboundData(netBB);
-    }
-
-    /*
-     * Main method for writing non-application data.
-     * We MAC/encrypt, then send down for processing.
-     */
-    void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
-        /*
-         * Sanity check.
-         */
-        switch (contentType()) {
-        case ct_change_cipher_spec:
-        case ct_alert:
-        case ct_handshake:
-            break;
-        default:
-            throw new RuntimeException("unexpected byte buffers");
-        }
-
-        /*
-         * Don't bother to really write empty records.  We went this
-         * far to drive the handshake machinery, for correctness; not
-         * writing empty records improves performance by cutting CPU
-         * time and network resource usage.  Also, some protocol
-         * implementations are fragile and don't like to see empty
-         * records, so this increases robustness.
-         *
-         * (Even change cipher spec messages have a byte of data!)
-         */
-        if (!isEmpty()) {
-            // compress();              // eventually
-            addMAC(writeMAC);
-            encrypt(writeCipher);
-            write((OutputStream)null, false,   // send down for processing
-                (ByteArrayOutputStream)null);
-        }
-        return;
-    }
-
-    /**
-     * Main wrap/write driver.
-     */
-    void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
-            throws IOException {
-        /*
-         * sanity check to make sure someone didn't inadvertantly
-         * send us an impossible combination we don't know how
-         * to process.
-         */
-        assert(contentType() == ct_application_data);
-
-        /*
-         * Have we set the MAC's yet?  If not, we're not ready
-         * to process application data yet.
-         */
-        if (writeMAC == MAC.NULL) {
-            return;
-        }
-
-        /*
-         * Don't bother to really write empty records.  We went this
-         * far to drive the handshake machinery, for correctness; not
-         * writing empty records improves performance by cutting CPU
-         * time and network resource usage.  Also, some protocol
-         * implementations are fragile and don't like to see empty
-         * records, so this increases robustness.
-         */
-        if (ea.getAppRemaining() == 0) {
-            return;
-        }
-
-        /*
-         * By default, we counter chosen plaintext issues on CBC mode
-         * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
-         * data in the first record of every payload, and the rest in
-         * subsequent record(s). Note that the issues have been solved in
-         * TLS 1.1 or later.
-         *
-         * It is not necessary to split the very first application record of
-         * a freshly negotiated TLS session, as there is no previous
-         * application data to guess.  To improve compatibility, we will not
-         * split such records.
-         *
-         * Because of the compatibility, we'd better produce no more than
-         * SSLSession.getPacketBufferSize() net data for each wrap. As we
-         * need a one-byte record at first, the 2nd record size should be
-         * equal to or less than Record.maxDataSizeMinusOneByteRecord.
-         *
-         * This avoids issues in the outbound direction.  For a full fix,
-         * the peer must have similar protections.
-         */
-        int length;
-        if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
-            write(ea, writeMAC, writeCipher, 0x01);
-            ea.resetLim();      // reset application data buffer limit
-            length = Math.min(ea.getAppRemaining(),
-                        maxDataSizeMinusOneByteRecord);
-        } else {
-            length = Math.min(ea.getAppRemaining(), maxDataSize);
-        }
-
-        // Don't bother to really write empty records.
-        if (length > 0) {
-            write(ea, writeMAC, writeCipher, length);
-        }
-
-        return;
-    }
-
-    void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher,
-            int length) throws IOException {
-        /*
-         * Copy out existing buffer values.
-         */
-        ByteBuffer dstBB = ea.netData;
-        int dstPos = dstBB.position();
-        int dstLim = dstBB.limit();
-
-        /*
-         * Where to put the data.  Jump over the header.
-         *
-         * Don't need to worry about SSLv2 rewrites, if we're here,
-         * that's long since done.
-         */
-        int dstData = dstPos + headerSize;
-        dstBB.position(dstData);
-
-        ea.gather(length);
-
-        /*
-         * "flip" but skip over header again, add MAC & encrypt
-         * addMAC will expand the limit to reflect the new
-         * data.
-         */
-        dstBB.limit(dstBB.position());
-        dstBB.position(dstData);
-        addMAC(writeMAC, dstBB);
-
-        /*
-         * Encrypt may pad, so again the limit may have changed.
-         */
-        dstBB.limit(dstBB.position());
-        dstBB.position(dstData);
-        encrypt(writeCipher, dstBB);
-
-        if (debug != null
-                && (Debug.isOn("record") || Debug.isOn("handshake"))) {
-            if ((debug != null && Debug.isOn("record"))
-                    || contentType() == ct_change_cipher_spec)
-                System.out.println(Thread.currentThread().getName()
-                    // v3.0/v3.1 ...
-                    + ", WRITE: " + protocolVersion
-                    + " " + InputRecord.contentName(contentType())
-                    + ", length = " + length);
-        }
-
-        int packetLength = dstBB.limit() - dstData;
-
-        /*
-         * Finish out the record header.
-         */
-        dstBB.put(dstPos, contentType());
-        dstBB.put(dstPos + 1, protocolVersion.major);
-        dstBB.put(dstPos + 2, protocolVersion.minor);
-        dstBB.put(dstPos + 3, (byte)(packetLength >> 8));
-        dstBB.put(dstPos + 4, (byte)packetLength);
-
-        /*
-         * Position was already set by encrypt() above.
-         */
-        dstBB.limit(dstLim);
-
-        return;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineWriter.java b/ojluni/src/main/java/sun/security/ssl/EngineWriter.java
deleted file mode 100755
index c930af7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineWriter.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import sun.misc.HexDumpEncoder;
-
-/**
- * A class to help abstract away SSLEngine writing synchronization.
- */
-final class EngineWriter {
-
-    /*
-     * Outgoing handshake Data waiting for a ride is stored here.
-     * Normal application data is written directly into the outbound
-     * buffer, but handshake data can be written out at any time,
-     * so we have buffer it somewhere.
-     *
-     * When wrap is called, we first check to see if there is
-     * any data waiting, then if we're in a data transfer state,
-     * we try to write app data.
-     *
-     * This will contain either ByteBuffers, or the marker
-     * HandshakeStatus.FINISHED to signify that a handshake just completed.
-     */
-    private LinkedList<Object> outboundList;
-
-    private boolean outboundClosed = false;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    EngineWriter() {
-        outboundList = new LinkedList<Object>();
-    }
-
-    /*
-     * Upper levels assured us we had room for at least one packet of data.
-     * As per the SSLEngine spec, we only return one SSL packets worth of
-     * data.
-     */
-    private HandshakeStatus getOutboundData(ByteBuffer dstBB) {
-
-        Object msg = outboundList.removeFirst();
-        assert(msg instanceof ByteBuffer);
-
-        ByteBuffer bbIn = (ByteBuffer) msg;
-        assert(dstBB.remaining() >= bbIn.remaining());
-
-        dstBB.put(bbIn);
-
-        /*
-         * If we have more data in the queue, it's either
-         * a finished message, or an indication that we need
-         * to call wrap again.
-         */
-        if (hasOutboundDataInternal()) {
-            msg = outboundList.getFirst();
-            if (msg == HandshakeStatus.FINISHED) {
-                outboundList.removeFirst();     // consume the message
-                return HandshakeStatus.FINISHED;
-            } else {
-                return HandshakeStatus.NEED_WRAP;
-            }
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * Properly orders the output of the data written to the wrap call.
-     * This is only handshake data, application data goes through the
-     * other writeRecord.
-     */
-    synchronized void writeRecord(EngineOutputRecord outputRecord,
-            MAC writeMAC, CipherBox writeCipher) throws IOException {
-
-        /*
-         * Only output if we're still open.
-         */
-        if (outboundClosed) {
-            throw new IOException("writer side was already closed.");
-        }
-
-        outputRecord.write(writeMAC, writeCipher);
-
-        /*
-         * Did our handshakers notify that we just sent the
-         * Finished message?
-         *
-         * Add an "I'm finished" message to the queue.
-         */
-        if (outputRecord.isFinishedMsg()) {
-            outboundList.addLast(HandshakeStatus.FINISHED);
-        }
-    }
-
-    /*
-     * Output the packet info.
-     */
-    private void dumpPacket(EngineArgs ea, boolean hsData) {
-        try {
-            HexDumpEncoder hd = new HexDumpEncoder();
-
-            ByteBuffer bb = ea.netData.duplicate();
-
-            int pos = bb.position();
-            bb.position(pos - ea.deltaNet());
-            bb.limit(pos);
-
-            System.out.println("[Raw write" +
-                (hsData ? "" : " (bb)") + "]: length = " +
-                bb.remaining());
-            hd.encodeBuffer(bb, System.out);
-        } catch (IOException e) { }
-    }
-
-    /*
-     * Properly orders the output of the data written to the wrap call.
-     * Only app data goes through here, handshake data goes through
-     * the other writeRecord.
-     *
-     * Shouldn't expect to have an IOException here.
-     *
-     * Return any determined status.
-     */
-    synchronized HandshakeStatus writeRecord(
-            EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC,
-            CipherBox writeCipher) throws IOException {
-
-        /*
-         * If we have data ready to go, output this first before
-         * trying to consume app data.
-         */
-        if (hasOutboundDataInternal()) {
-            HandshakeStatus hss = getOutboundData(ea.netData);
-
-            if (debug != null && Debug.isOn("packet")) {
-                /*
-                 * We could have put the dump in
-                 * OutputRecord.write(OutputStream), but let's actually
-                 * output when it's actually output by the SSLEngine.
-                 */
-                dumpPacket(ea, true);
-            }
-
-            return hss;
-        }
-
-        /*
-         * If we are closed, no more app data can be output.
-         * Only existing handshake data (above) can be obtained.
-         */
-        if (outboundClosed) {
-            throw new IOException("The write side was already closed");
-        }
-
-        outputRecord.write(ea, writeMAC, writeCipher);
-
-        if (debug != null && Debug.isOn("packet")) {
-            dumpPacket(ea, false);
-        }
-
-        /*
-         * No way new outbound handshake data got here if we're
-         * locked properly.
-         *
-         * We don't have any status we can return.
-         */
-        return null;
-    }
-
-    /*
-     * We already hold "this" lock, this is the callback from the
-     * outputRecord.write() above.  We already know this
-     * writer can accept more data (outboundClosed == false),
-     * and the closure is sync'd.
-     */
-    void putOutboundData(ByteBuffer bytes) {
-        outboundList.addLast(bytes);
-    }
-
-    /*
-     * This is for the really rare case that someone is writing from
-     * the *InputRecord* before we know what to do with it.
-     */
-    synchronized void putOutboundDataSync(ByteBuffer bytes)
-            throws IOException {
-
-        if (outboundClosed) {
-            throw new IOException("Write side already closed");
-        }
-
-        outboundList.addLast(bytes);
-    }
-
-    /*
-     * Non-synch'd version of this method, called by internals
-     */
-    private boolean hasOutboundDataInternal() {
-        return (outboundList.size() != 0);
-    }
-
-    synchronized boolean hasOutboundData() {
-        return hasOutboundDataInternal();
-    }
-
-    synchronized boolean isOutboundDone() {
-        return outboundClosed && !hasOutboundDataInternal();
-    }
-
-    synchronized void closeOutbound() {
-        outboundClosed = true;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java b/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java
deleted file mode 100755
index 47dba95..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.*;
-
-/**
- * The "KeyManager" for ephemeral RSA keys. Ephemeral DH and ECDH keys
- * are handled by the DHCrypt and ECDHCrypt classes, respectively.
- *
- * @author  Andreas Sterbenz
- */
-final class EphemeralKeyManager {
-
-    // indices for the keys array below
-    private final static int INDEX_RSA512 = 0;
-    private final static int INDEX_RSA1024 = 1;
-
-    /*
-     * Current cached RSA KeyPairs. Elements are never null.
-     * Indexed via the the constants above.
-     */
-    private final EphemeralKeyPair[] keys = new EphemeralKeyPair[] {
-        new EphemeralKeyPair(null),
-        new EphemeralKeyPair(null),
-    };
-
-    EphemeralKeyManager() {
-        // empty
-    }
-
-    /*
-     * Get a temporary RSA KeyPair.
-     */
-    KeyPair getRSAKeyPair(boolean export, SecureRandom random) {
-        int length, index;
-        if (export) {
-            length = 512;
-            index = INDEX_RSA512;
-        } else {
-            length = 1024;
-            index = INDEX_RSA1024;
-        }
-
-        synchronized (keys) {
-            KeyPair kp = keys[index].getKeyPair();
-            if (kp == null) {
-                try {
-                    KeyPairGenerator kgen = JsseJce.getKeyPairGenerator("RSA");
-                    kgen.initialize(length, random);
-                    keys[index] = new EphemeralKeyPair(kgen.genKeyPair());
-                    kp = keys[index].getKeyPair();
-                } catch (Exception e) {
-                    // ignore
-                }
-            }
-            return kp;
-        }
-    }
-
-    /**
-     * Inner class to handle storage of ephemeral KeyPairs.
-     */
-    private static class EphemeralKeyPair {
-
-        // maximum number of times a KeyPair is used
-        private final static int MAX_USE = 200;
-
-        // maximum time interval in which the keypair is used (1 hour in ms)
-        private final static long USE_INTERVAL = 3600*1000;
-
-        private KeyPair keyPair;
-        private int uses;
-        private long expirationTime;
-
-        private EphemeralKeyPair(KeyPair keyPair) {
-            this.keyPair = keyPair;
-            expirationTime = System.currentTimeMillis() + USE_INTERVAL;
-        }
-
-        /*
-         * Check if the KeyPair can still be used.
-         */
-        private boolean isValid() {
-            return (keyPair != null) && (uses < MAX_USE)
-                   && (System.currentTimeMillis() < expirationTime);
-        }
-
-        /*
-         * Return the KeyPair or null if it is invalid.
-         */
-        private KeyPair getKeyPair() {
-            if (isValid() == false) {
-                keyPair = null;
-                return null;
-            }
-            uses++;
-            return keyPair;
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java b/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java
deleted file mode 100755
index ffb8f32..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.ByteArrayOutputStream;
-import java.security.*;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Abstraction for the SSL/TLS hash of all handshake messages that is
- * maintained to verify the integrity of the negotiation. Internally,
- * it consists of an MD5 and an SHA1 digest. They are used in the client
- * and server finished messages and in certificate verify messages (if sent).
- *
- * This class transparently deals with cloneable and non-cloneable digests.
- *
- * This class now supports TLS 1.2 also. The key difference for TLS 1.2
- * is that you cannot determine the hash algorithms for CertificateVerify
- * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
- * that there is no messy MD5+SHA1 digests.
- *
- * You need to obey these conventions when using this class:
- *
- * 1. protocolDetermined(version) should be called when the negotiated
- * protocol version is determined.
- *
- * 2. Before protocolDetermined() is called, only update(), reset(),
- * restrictCertificateVerifyAlgs(), setFinishedAlg(), and
- * setCertificateVerifyAlg() can be called.
- *
- * 3. After protocolDetermined() is called, reset() cannot be called.
- *
- * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2,
- * getFinishedHash() and getCertificateVerifyHash() cannot be called. Otherwise,
- * getMD5Clone() and getSHAClone() cannot be called.
- *
- * 5. getMD5Clone() and getSHAClone() can only be called after
- * protocolDetermined() is called and version is pre-TLS 1.2.
- *
- * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
- * all protocolDetermined(), setCertificateVerifyAlg() and setFinishedAlg()
- * have been called and the version is TLS 1.2. If a CertificateVerify message
- * is to be used, call setCertificateVerifyAlg() with the hash algorithm as the
- * argument. Otherwise, you still must call setCertificateVerifyAlg(null) before
- * calculating any hash value.
- *
- * Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
- * setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
- *
- * Example:
- * <pre>
- * HandshakeHash hh = new HandshakeHash(...)
- * hh.protocolDetermined(ProtocolVersion.TLS12);
- * hh.update(clientHelloBytes);
- * hh.setFinishedAlg("SHA-256");
- * hh.update(serverHelloBytes);
- * ...
- * hh.setCertificateVerifyAlg("SHA-384");
- * hh.update(CertificateVerifyBytes);
- * byte[] cvDigest = hh.getCertificateVerifyHash();
- * ...
- * hh.update(finished1);
- * byte[] finDigest1 = hh.getFinishedHash();
- * hh.update(finished2);
- * byte[] finDigest2 = hh.getFinishedHash();
- * </pre>
- * If no CertificateVerify message is to be used, call
- * <pre>
- * hh.setCertificateVerifyAlg(null);
- * </pre>
- * This call can be made once you are certain that this message
- * will never be used.
- */
-final class HandshakeHash {
-
-    // Common
-
-    // -1:  unknown
-    //  1:  <=TLS 1.1
-    //  2:  TLS 1.2
-    private int version = -1;
-    private ByteArrayOutputStream data = new ByteArrayOutputStream();
-    private final boolean isServer;
-
-    // For TLS 1.1
-    private MessageDigest md5, sha;
-    private final int clonesNeeded;    // needs to be saved for later use
-
-    // For TLS 1.2
-    // cvAlgDetermined == true means setCertificateVerifyAlg() is called
-    private boolean cvAlgDetermined = false;
-    private String cvAlg;
-    private MessageDigest finMD;
-
-    /**
-     * Create a new HandshakeHash. needCertificateVerify indicates whether
-     * a hash for the certificate verify message is required. The argument
-     * algs is a set of all possible hash algorithms that might be used in
-     * TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
-     * CertificateVerify message will be used, leave it null or empty.
-     */
-    HandshakeHash(boolean isServer, boolean needCertificateVerify,
-            Set<String> algs) {
-        this.isServer = isServer;
-        clonesNeeded = needCertificateVerify ? 3 : 2;
-    }
-
-    void update(byte[] b, int offset, int len) {
-        switch (version) {
-            case 1:
-                md5.update(b, offset, len);
-                sha.update(b, offset, len);
-                break;
-            default:
-                if (finMD != null) {
-                    finMD.update(b, offset, len);
-                }
-                data.write(b, offset, len);
-                break;
-        }
-    }
-
-    /**
-     * Reset the remaining digests. Note this does *not* reset the number of
-     * digest clones that can be obtained. Digests that have already been
-     * cloned and are gone remain gone.
-     */
-    void reset() {
-        if (version != -1) {
-            throw new RuntimeException(
-                    "reset() can be only be called before protocolDetermined");
-        }
-        data.reset();
-    }
-
-
-    void protocolDetermined(ProtocolVersion pv) {
-
-        // Do not set again, will ignore
-        if (version != -1) return;
-
-        version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1;
-        switch (version) {
-            case 1:
-                // initiate md5, sha and call update on saved array
-                try {
-                    md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
-                    sha = CloneableDigest.getDigest("SHA", clonesNeeded);
-                } catch (NoSuchAlgorithmException e) {
-                    throw new RuntimeException
-                                ("Algorithm MD5 or SHA not available", e);
-                }
-                byte[] bytes = data.toByteArray();
-                update(bytes, 0, bytes.length);
-                break;
-            case 2:
-                break;
-        }
-    }
-
-    /////////////////////////////////////////////////////////////
-    // Below are old methods for pre-TLS 1.1
-    /////////////////////////////////////////////////////////////
-
-    /**
-     * Return a new MD5 digest updated with all data hashed so far.
-     */
-    MessageDigest getMD5Clone() {
-        if (version != 1) {
-            throw new RuntimeException(
-                    "getMD5Clone() can be only be called for TLS 1.1");
-        }
-        return cloneDigest(md5);
-    }
-
-    /**
-     * Return a new SHA digest updated with all data hashed so far.
-     */
-    MessageDigest getSHAClone() {
-        if (version != 1) {
-            throw new RuntimeException(
-                    "getSHAClone() can be only be called for TLS 1.1");
-        }
-        return cloneDigest(sha);
-    }
-
-    private static MessageDigest cloneDigest(MessageDigest digest) {
-        try {
-            return (MessageDigest)digest.clone();
-        } catch (CloneNotSupportedException e) {
-            // cannot occur for digests generated via CloneableDigest
-            throw new RuntimeException("Could not clone digest", e);
-        }
-    }
-
-    /////////////////////////////////////////////////////////////
-    // Below are new methods for TLS 1.2
-    /////////////////////////////////////////////////////////////
-
-    private static String normalizeAlgName(String alg) {
-        alg = alg.toUpperCase(Locale.US);
-        if (alg.startsWith("SHA")) {
-            if (alg.length() == 3) {
-                return "SHA-1";
-            }
-            if (alg.charAt(3) != '-') {
-                return "SHA-" + alg.substring(3);
-            }
-        }
-        return alg;
-    }
-    /**
-     * Specifies the hash algorithm used in Finished. This should be called
-     * based in info in ServerHello.
-     * Can be called multiple times.
-     */
-    void setFinishedAlg(String s) {
-        if (s == null) {
-            throw new RuntimeException(
-                    "setFinishedAlg's argument cannot be null");
-        }
-
-        // Can be called multiple times, but only set once
-        if (finMD != null) return;
-
-        try {
-            finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
-        } catch (NoSuchAlgorithmException e) {
-            throw new Error(e);
-        }
-        finMD.update(data.toByteArray());
-    }
-
-    /**
-     * Restricts the possible algorithms for the CertificateVerify. Called by
-     * the server based on info in CertRequest. The argument must be a subset
-     * of the argument with the same name in the constructor. The method can be
-     * called multiple times. If the caller is sure that no CertificateVerify
-     * message will be used, leave this argument null or empty.
-     */
-    void restrictCertificateVerifyAlgs(Set<String> algs) {
-        if (version == 1) {
-            throw new RuntimeException(
-                    "setCertificateVerifyAlg() cannot be called for TLS 1.1");
-        }
-        // Not used yet
-    }
-
-    /**
-     * Specifies the hash algorithm used in CertificateVerify.
-     * Can be called multiple times.
-     */
-    void setCertificateVerifyAlg(String s) {
-
-        // Can be called multiple times, but only set once
-        if (cvAlgDetermined) return;
-
-        cvAlg = s == null ? null : normalizeAlgName(s);
-        cvAlgDetermined = true;
-    }
-
-    byte[] getAllHandshakeMessages() {
-        return data.toByteArray();
-    }
-
-    /**
-     * Calculates the hash in the CertificateVerify. Must be called right
-     * after setCertificateVerifyAlg()
-     */
-    /*byte[] getCertificateVerifyHash() {
-        throw new Error("Do not call getCertificateVerifyHash()");
-    }*/
-
-    /**
-     * Calculates the hash in Finished. Must be called after setFinishedAlg().
-     * This method can be called twice, for Finished messages of the server
-     * side and client side respectively.
-     */
-    byte[] getFinishedHash() {
-        try {
-            return cloneDigest(finMD).digest();
-        } catch (Exception e) {
-            throw new Error("BAD");
-        }
-    }
-}
-
-/**
- * A wrapper for MessageDigests that simulates cloning of non-cloneable
- * digests. It uses the standard MessageDigest API and therefore can be used
- * transparently in place of a regular digest.
- *
- * Note that we extend the MessageDigest class directly rather than
- * MessageDigestSpi. This works because MessageDigest was originally designed
- * this way in the JDK 1.1 days which allows us to avoid creating an internal
- * provider.
- *
- * It can be "cloned" a limited number of times, which is specified at
- * construction time. This is achieved by internally maintaining n digests
- * in parallel. Consequently, it is only 1/n-th times as fast as the original
- * digest.
- *
- * Example:
- *   MessageDigest md = CloneableDigest.getDigest("SHA", 2);
- *   md.update(data1);
- *   MessageDigest md2 = (MessageDigest)md.clone();
- *   md2.update(data2);
- *   byte[] d1 = md2.digest(); // digest of data1 || data2
- *   md.update(data3);
- *   byte[] d2 = md.digest();  // digest of data1 || data3
- *
- * This class is not thread safe.
- *
- */
-final class CloneableDigest extends MessageDigest implements Cloneable {
-
-    /**
-     * The individual MessageDigests. Initially, all elements are non-null.
-     * When clone() is called, the non-null element with the maximum index is
-     * returned and the array element set to null.
-     *
-     * All non-null element are always in the same state.
-     */
-    private final MessageDigest[] digests;
-
-    private CloneableDigest(MessageDigest digest, int n, String algorithm)
-            throws NoSuchAlgorithmException {
-        super(algorithm);
-        digests = new MessageDigest[n];
-        digests[0] = digest;
-        for (int i = 1; i < n; i++) {
-            digests[i] = JsseJce.getMessageDigest(algorithm);
-        }
-    }
-
-    /**
-     * Return a MessageDigest for the given algorithm that can be cloned the
-     * specified number of times. If the default implementation supports
-     * cloning, it is returned. Otherwise, an instance of this class is
-     * returned.
-     */
-    static MessageDigest getDigest(String algorithm, int n)
-            throws NoSuchAlgorithmException {
-        MessageDigest digest = JsseJce.getMessageDigest(algorithm);
-        try {
-            digest.clone();
-            // already cloneable, use it
-            return digest;
-        } catch (CloneNotSupportedException e) {
-            return new CloneableDigest(digest, n, algorithm);
-        }
-    }
-
-    /**
-     * Check if this object is still usable. If it has already been cloned the
-     * maximum number of times, there are no digests left and this object can no
-     * longer be used.
-     */
-    private void checkState() {
-        // XXX handshaking currently doesn't stop updating hashes...
-        // if (digests[0] == null) {
-        //     throw new IllegalStateException("no digests left");
-        // }
-    }
-
-    protected int engineGetDigestLength() {
-        checkState();
-        return digests[0].getDigestLength();
-    }
-
-    protected void engineUpdate(byte b) {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].update(b);
-        }
-    }
-
-    protected void engineUpdate(byte[] b, int offset, int len) {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].update(b, offset, len);
-        }
-    }
-
-    protected byte[] engineDigest() {
-        checkState();
-        byte[] digest = digests[0].digest();
-        digestReset();
-        return digest;
-    }
-
-    protected int engineDigest(byte[] buf, int offset, int len)
-            throws DigestException {
-        checkState();
-        int n = digests[0].digest(buf, offset, len);
-        digestReset();
-        return n;
-    }
-
-    /**
-     * Reset all digests after a digest() call. digests[0] has already been
-     * implicitly reset by the digest() call and does not need to be reset
-     * again.
-     */
-    private void digestReset() {
-        for (int i = 1; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].reset();
-        }
-    }
-
-    protected void engineReset() {
-        checkState();
-        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
-            digests[i].reset();
-        }
-    }
-
-    public Object clone() {
-        checkState();
-        for (int i = digests.length - 1; i >= 0; i--) {
-            if (digests[i] != null) {
-                MessageDigest digest = digests[i];
-                digests[i] = null;
-                return digest;
-            }
-        }
-        // cannot occur
-        throw new InternalError();
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java b/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java
deleted file mode 100755
index 81c8464..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-
-import javax.net.ssl.SSLException;
-
-/**
- * InputStream for handshake data, used internally only. Contains the
- * handshake message buffer and methods to parse them.
- *
- * Once a new handshake record arrives, it is buffered in this class until
- * processed by the Handshaker. The buffer may also contain incomplete
- * handshake messages in case the message is split across multiple records.
- * Handshaker.process_record deals with all that. It may also contain
- * handshake messages larger than the default buffer size (e.g. large
- * certificate messages). The buffer is grown dynamically to handle that
- * (see InputRecord.queueHandshake()).
- *
- * Note that the InputRecord used as a buffer here is separate from the
- * AppInStream.r, which is where data from the socket is initially read
- * into. This is because once the initial handshake has been completed,
- * handshake and application data messages may be interleaved arbitrarily
- * and must be processed independently.
- *
- * @author David Brownell
- */
-public class HandshakeInStream extends InputStream {
-
-    InputRecord r;
-
-    /*
-     * Construct the stream; we'll be accumulating hashes of the
-     * input records using two sets of digests.
-     */
-    HandshakeInStream(HandshakeHash handshakeHash) {
-        r = new InputRecord();
-        r.setHandshakeHash(handshakeHash);
-    }
-
-
-    // overridden InputStream methods
-
-    /*
-     * Return the number of bytes available for read().
-     *
-     * Note that this returns the bytes remaining in the buffer, not
-     * the bytes remaining in the current handshake message.
-     */
-    public int available() {
-        return r.available();
-    }
-
-    /*
-     * Get a byte of handshake data.
-     */
-    public int read() throws IOException {
-        int n = r.read();
-        if (n == -1) {
-            throw new SSLException("Unexpected end of handshake data");
-        }
-        return n;
-    }
-
-    /*
-     * Get a bunch of bytes of handshake data.
-     */
-    public int read(byte b [], int off, int len) throws IOException {
-        // we read from a ByteArrayInputStream, it always returns the
-        // data in a single read if enough is available
-        int n = r.read(b, off, len);
-        if (n != len) {
-            throw new SSLException("Unexpected end of handshake data");
-        }
-        return n;
-    }
-
-    /*
-     * Skip some handshake data.
-     */
-    public long skip(long n) throws IOException {
-        return r.skip(n);
-    }
-
-    /*
-     * Mark/ reset code, implemented using InputRecord mark/ reset.
-     *
-     * Note that it currently provides only a limited mark functionality
-     * and should be used with care (once a new handshake record has been
-     * read, data that has already been consumed is lost even if marked).
-     */
-
-    public void mark(int readlimit) {
-        r.mark(readlimit);
-    }
-
-    public void reset() {
-        r.reset();
-    }
-
-    public boolean markSupported() {
-        return true;
-    }
-
-
-    // handshake management functions
-
-    /*
-     * Here's an incoming record with handshake data.  Queue the contents;
-     * it might be one or more entire messages, complete a message that's
-     * partly queued, or both.
-     */
-    void incomingRecord(InputRecord in) throws IOException {
-        r.queueHandshake(in);
-    }
-
-    /*
-     * Hash any data we've consumed but not yet hashed.  Useful mostly
-     * for processing client certificate messages (so we can check the
-     * immediately following cert verify message) and finished messages
-     * (so we can compute our own finished message).
-     */
-    void digestNow() {
-        r.doHashes();
-    }
-
-    /*
-     * Do more than skip that handshake data ... totally ignore it.
-     * The difference is that the data does not get hashed.
-     */
-    void ignore(int n) {
-        r.ignore(n);
-    }
-
-
-    // Message parsing methods
-
-    /*
-     * Read 8, 16, 24, and 32 bit SSL integer data types, encoded
-     * in standard big-endian form.
-     */
-
-    int getInt8() throws IOException {
-        return read();
-    }
-
-    int getInt16() throws IOException {
-        return (getInt8() << 8) | getInt8();
-    }
-
-    int getInt24() throws IOException {
-        return (getInt8() << 16) | (getInt8() << 8) | getInt8();
-    }
-
-    int getInt32() throws IOException {
-        return (getInt8() << 24) | (getInt8() << 16)
-             | (getInt8() << 8) | getInt8();
-    }
-
-    /*
-     * Read byte vectors with 8, 16, and 24 bit length encodings.
-     */
-
-    byte[] getBytes8() throws IOException {
-        int len = getInt8();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    public byte[] getBytes16() throws IOException {
-        int len = getInt16();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    byte[] getBytes24() throws IOException {
-        int len = getInt24();
-        verifyLength(len);
-        byte b[] = new byte[len];
-
-        read(b, 0, len);
-        return b;
-    }
-
-    // Is a length greater than available bytes in the record?
-    private void verifyLength(int len) throws SSLException {
-        if (len > available()) {
-            throw new SSLException(
-                        "Not enough data to fill declared vector size");
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java b/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java
deleted file mode 100755
index 1c85a03..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java
+++ /dev/null
@@ -1,2018 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.security.interfaces.*;
-import java.security.spec.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-import java.lang.reflect.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.DHPublicKeySpec;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsPrfParameterSpec;
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import sun.security.util.KeyUtil;
-
-/**
- * Many data structures are involved in the handshake messages.  These
- * classes are used as structures, with public data members.  They are
- * not visible outside the SSL package.
- *
- * Handshake messages all have a common header format, and they are all
- * encoded in a "handshake data" SSL record substream.  The base class
- * here (HandshakeMessage) provides a common framework and records the
- * SSL record type of the particular handshake message.
- *
- * This file contains subclasses for all the basic handshake messages.
- * All handshake messages know how to encode and decode themselves on
- * SSL streams; this facilitates using the same code on SSL client and
- * server sides, although they don't send and receive the same messages.
- *
- * Messages also know how to print themselves, which is quite handy
- * for debugging.  They always identify their type, and can optionally
- * dump all of their content.
- *
- * @author David Brownell
- */
-public abstract class HandshakeMessage {
-
-    HandshakeMessage() { }
-
-    // enum HandshakeType:
-    static final byte   ht_hello_request = 0;
-    static final byte   ht_client_hello = 1;
-    static final byte   ht_server_hello = 2;
-
-    static final byte   ht_certificate = 11;
-    static final byte   ht_server_key_exchange = 12;
-    static final byte   ht_certificate_request = 13;
-    static final byte   ht_server_hello_done = 14;
-    static final byte   ht_certificate_verify = 15;
-    static final byte   ht_client_key_exchange = 16;
-
-    static final byte   ht_finished = 20;
-
-    /* Class and subclass dynamic debugging support */
-    public static final Debug debug = Debug.getInstance("ssl");
-
-    /**
-     * Utility method to convert a BigInteger to a byte array in unsigned
-     * format as needed in the handshake messages. BigInteger uses
-     * 2's complement format, i.e. it prepends an extra zero if the MSB
-     * is set. We remove that.
-     */
-    static byte[] toByteArray(BigInteger bi) {
-        byte[] b = bi.toByteArray();
-        if ((b.length > 1) && (b[0] == 0)) {
-            int n = b.length - 1;
-            byte[] newarray = new byte[n];
-            System.arraycopy(b, 1, newarray, 0, n);
-            b = newarray;
-        }
-        return b;
-    }
-
-    /*
-     * SSL 3.0 MAC padding constants.
-     * Also used by CertificateVerify and Finished during the handshake.
-     */
-    static final byte[] MD5_pad1 = genPad(0x36, 48);
-    static final byte[] MD5_pad2 = genPad(0x5c, 48);
-
-    static final byte[] SHA_pad1 = genPad(0x36, 40);
-    static final byte[] SHA_pad2 = genPad(0x5c, 40);
-
-    private static byte[] genPad(int b, int count) {
-        byte[] padding = new byte[count];
-        Arrays.fill(padding, (byte)b);
-        return padding;
-    }
-
-    /*
-     * Write a handshake message on the (handshake) output stream.
-     * This is just a four byte header followed by the data.
-     *
-     * NOTE that huge messages -- notably, ones with huge cert
-     * chains -- are handled correctly.
-     */
-    final void write(HandshakeOutStream s) throws IOException {
-        int len = messageLength();
-        if (len >= Record.OVERFLOW_OF_INT24) {
-            throw new SSLException("Handshake message too big"
-                + ", type = " + messageType() + ", len = " + len);
-        }
-        s.write(messageType());
-        s.putInt24(len);
-        send(s);
-    }
-
-    /*
-     * Subclasses implement these methods so those kinds of
-     * messages can be emitted.  Base class delegates to subclass.
-     */
-    abstract int  messageType();
-    abstract int  messageLength();
-    abstract void send(HandshakeOutStream s) throws IOException;
-
-    /*
-     * Write a descriptive message on the output stream; for debugging.
-     */
-    abstract void print(PrintStream p) throws IOException;
-
-//
-// NOTE:  the rest of these classes are nested within this one, and are
-// imported by other classes in this package.  There are a few other
-// handshake message classes, not neatly nested here because of current
-// licensing requirement for native (RSA) methods.  They belong here,
-// but those native methods complicate things a lot!
-//
-
-
-/*
- * HelloRequest ... SERVER --> CLIENT
- *
- * Server can ask the client to initiate a new handshake, e.g. to change
- * session parameters after a connection has been (re)established.
- */
-static final class HelloRequest extends HandshakeMessage {
-    int messageType() { return ht_hello_request; }
-
-    HelloRequest() { }
-
-    HelloRequest(HandshakeInStream in) throws IOException
-    {
-        // nothing in this message
-    }
-
-    int messageLength() { return 0; }
-
-    void send(HandshakeOutStream out) throws IOException
-    {
-        // nothing in this messaage
-    }
-
-    void print(PrintStream out) throws IOException
-    {
-        out.println("*** HelloRequest (empty)");
-    }
-
-}
-
-
-/*
- * ClientHello ... CLIENT --> SERVER
- *
- * Client initiates handshake by telling server what it wants, and what it
- * can support (prioritized by what's first in the ciphe suite list).
- *
- * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
- * will have more data added at the end ... e.g. what CAs the client trusts.
- * Until we know how to parse it, we will just read what we know
- * about, and let our caller handle the jumps over unknown data.
- */
-static final class ClientHello extends HandshakeMessage {
-
-    ProtocolVersion     protocolVersion;
-    RandomCookie        clnt_random;
-    SessionId           sessionId;
-    private CipherSuiteList    cipherSuites;
-    byte[]              compression_methods;
-
-    HelloExtensions extensions = new HelloExtensions();
-
-    private final static byte[]  NULL_COMPRESSION = new byte[] {0};
-
-    ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
-            SessionId sessionId, CipherSuiteList cipherSuites) {
-
-        this.protocolVersion = protocolVersion;
-        this.sessionId = sessionId;
-        this.cipherSuites = cipherSuites;
-
-        if (cipherSuites.containsEC()) {
-            extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
-            extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
-        }
-
-        clnt_random = new RandomCookie(generator);
-        compression_methods = NULL_COMPRESSION;
-    }
-
-    ClientHello(HandshakeInStream s, int messageLength) throws IOException {
-        protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
-        clnt_random = new RandomCookie(s);
-        sessionId = new SessionId(s.getBytes8());
-        cipherSuites = new CipherSuiteList(s);
-        compression_methods = s.getBytes8();
-        if (messageLength() != messageLength) {
-            extensions = new HelloExtensions(s);
-        }
-    }
-
-    CipherSuiteList getCipherSuites() {
-        return cipherSuites;
-    }
-
-    // add renegotiation_info extension
-    void addRenegotiationInfoExtension(byte[] clientVerifyData) {
-        HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
-                    clientVerifyData, new byte[0]);
-        extensions.add(renegotiationInfo);
-    }
-
-    // add server_name extension
-    void addServerNameIndicationExtension(String hostname) {
-        // We would have checked that the hostname ia a FQDN.
-        ArrayList<String> hostnames = new ArrayList<>(1);
-        hostnames.add(hostname);
-
-        try {
-            extensions.add(new ServerNameExtension(hostnames));
-        } catch (IOException ioe) {
-            // ignore the exception and return
-        }
-    }
-
-    // add signature_algorithm extension
-    void addSignatureAlgorithmsExtension(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        HelloExtension signatureAlgorithm =
-                new SignatureAlgorithmsExtension(algorithms);
-        extensions.add(signatureAlgorithm);
-    }
-
-    @Override
-    int messageType() { return ht_client_hello; }
-
-    @Override
-    int messageLength() {
-        /*
-         * Add fixed size parts of each field...
-         * version + random + session + cipher + compress
-         */
-        return (2 + 32 + 1 + 2 + 1
-            + sessionId.length()                /* ... + variable parts */
-            + (cipherSuites.size() * 2)
-            + compression_methods.length)
-            + extensions.length();
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt8(protocolVersion.major);
-        s.putInt8(protocolVersion.minor);
-        clnt_random.send(s);
-        s.putBytes8(sessionId.getId());
-        cipherSuites.send(s);
-        s.putBytes8(compression_methods);
-        extensions.send(s);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ClientHello, " + protocolVersion);
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("RandomCookie:  ");
-            clnt_random.print(s);
-
-            s.print("Session ID:  ");
-            s.println(sessionId);
-
-            s.println("Cipher Suites: " + cipherSuites);
-
-            Debug.println(s, "Compression Methods", compression_methods);
-            extensions.print(s);
-            s.println("***");
-        }
-    }
-}
-
-/*
- * ServerHello ... SERVER --> CLIENT
- *
- * Server chooses protocol options from among those it supports and the
- * client supports.  Then it sends the basic session descriptive parameters
- * back to the client.
- */
-static final
-class ServerHello extends HandshakeMessage
-{
-    int messageType() { return ht_server_hello; }
-
-    ProtocolVersion     protocolVersion;
-    RandomCookie        svr_random;
-    SessionId           sessionId;
-    CipherSuite         cipherSuite;
-    byte                compression_method;
-    HelloExtensions extensions = new HelloExtensions();
-
-    ServerHello() {
-        // empty
-    }
-
-    ServerHello(HandshakeInStream input, int messageLength)
-            throws IOException {
-        protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
-                                                  input.getInt8());
-        svr_random = new RandomCookie(input);
-        sessionId = new SessionId(input.getBytes8());
-        cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
-        compression_method = (byte)input.getInt8();
-        if (messageLength() != messageLength) {
-            extensions = new HelloExtensions(input);
-        }
-    }
-
-    int messageLength()
-    {
-        // almost fixed size, except session ID and extensions:
-        //      major + minor = 2
-        //      random = 32
-        //      session ID len field = 1
-        //      cipher suite + compression = 3
-        //      extensions: if present, 2 + length of extensions
-        return 38 + sessionId.length() + extensions.length();
-    }
-
-    void send(HandshakeOutStream s) throws IOException
-    {
-        s.putInt8(protocolVersion.major);
-        s.putInt8(protocolVersion.minor);
-        svr_random.send(s);
-        s.putBytes8(sessionId.getId());
-        s.putInt8(cipherSuite.id >> 8);
-        s.putInt8(cipherSuite.id & 0xff);
-        s.putInt8(compression_method);
-        extensions.send(s);
-    }
-
-    void print(PrintStream s) throws IOException
-    {
-        s.println("*** ServerHello, " + protocolVersion);
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("RandomCookie:  ");
-            svr_random.print(s);
-
-            int i;
-
-            s.print("Session ID:  ");
-            s.println(sessionId);
-
-            s.println("Cipher Suite: " + cipherSuite);
-            s.println("Compression Method: " + compression_method);
-            extensions.print(s);
-            s.println("***");
-        }
-    }
-}
-
-
-/*
- * CertificateMsg ... send by both CLIENT and SERVER
- *
- * Each end of a connection may need to pass its certificate chain to
- * the other end.  Such chains are intended to validate an identity with
- * reference to some certifying authority.  Examples include companies
- * like Verisign, or financial institutions.  There's some control over
- * the certifying authorities which are sent.
- *
- * NOTE: that these messages might be huge, taking many handshake records.
- * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
- * bytes each ... up to 2^32 records sent on the output stream.
- */
-static final
-class CertificateMsg extends HandshakeMessage
-{
-    int messageType() { return ht_certificate; }
-
-    private X509Certificate[] chain;
-
-    private List<byte[]> encodedChain;
-
-    private int messageLength;
-
-    CertificateMsg(X509Certificate[] certs) {
-        chain = certs;
-    }
-
-    CertificateMsg(HandshakeInStream input) throws IOException {
-        int chainLen = input.getInt24();
-        List<Certificate> v = new ArrayList<>(4);
-
-        CertificateFactory cf = null;
-        while (chainLen > 0) {
-            byte[] cert = input.getBytes24();
-            chainLen -= (3 + cert.length);
-            try {
-                if (cf == null) {
-                    cf = CertificateFactory.getInstance("X.509");
-                }
-                v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
-            } catch (CertificateException e) {
-                throw (SSLProtocolException)new SSLProtocolException(
-                    e.getMessage()).initCause(e);
-            }
-        }
-
-        chain = v.toArray(new X509Certificate[v.size()]);
-    }
-
-    int messageLength() {
-        if (encodedChain == null) {
-            messageLength = 3;
-            encodedChain = new ArrayList<byte[]>(chain.length);
-            try {
-                for (X509Certificate cert : chain) {
-                    byte[] b = cert.getEncoded();
-                    encodedChain.add(b);
-                    messageLength += b.length + 3;
-                }
-            } catch (CertificateEncodingException e) {
-                encodedChain = null;
-                throw new RuntimeException("Could not encode certificates", e);
-            }
-        }
-        return messageLength;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt24(messageLength() - 3);
-        for (byte[] b : encodedChain) {
-            s.putBytes24(b);
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** Certificate chain");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            for (int i = 0; i < chain.length; i++)
-                s.println("chain [" + i + "] = " + chain[i]);
-            s.println("***");
-        }
-    }
-
-    X509Certificate[] getCertificateChain() {
-        return chain.clone();
-    }
-}
-
-/*
- * ServerKeyExchange ... SERVER --> CLIENT
- *
- * The cipher suite selected, when combined with the certificate exchanged,
- * implies one of several different kinds of key exchange.  Most current
- * cipher suites require the server to send more than its certificate.
- *
- * The primary exceptions are when a server sends an encryption-capable
- * RSA public key in its cert, to be used with RSA (or RSA_export) key
- * exchange; and when a server sends its Diffie-Hellman cert.  Those kinds
- * of key exchange do not require a ServerKeyExchange message.
- *
- * Key exchange can be viewed as having three modes, which are explicit
- * for the Diffie-Hellman flavors and poorly specified for RSA ones:
- *
- *      - "Ephemeral" keys.  Here, a "temporary" key is allocated by the
- *        server, and signed.  Diffie-Hellman keys signed using RSA or
- *        DSS are ephemeral (DHE flavor).  RSA keys get used to do the same
- *        thing, to cut the key size down to 512 bits (export restrictions)
- *        or for signing-only RSA certificates.
- *
- *      - Anonymity.  Here no server certificate is sent, only the public
- *        key of the server.  This case is subject to man-in-the-middle
- *        attacks.  This can be done with Diffie-Hellman keys (DH_anon) or
- *        with RSA keys, but is only used in SSLv3 for DH_anon.
- *
- *      - "Normal" case.  Here a server certificate is sent, and the public
- *        key there is used directly in exchanging the premaster secret.
- *        For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
- *        only 512 bit keys.
- *
- * If a server certificate is sent, there is no anonymity.  However,
- * when a certificate is sent, ephemeral keys may still be used to
- * exchange the premaster secret.  That's how RSA_EXPORT often works,
- * as well as how the DHE_* flavors work.
- */
-static abstract class ServerKeyExchange extends HandshakeMessage
-{
-    int messageType() { return ht_server_key_exchange; }
-}
-
-
-/*
- * Using RSA for Key Exchange:  exchange a session key that's not as big
- * as the signing-only key.  Used for export applications, since exported
- * RSA encryption keys can't be bigger than 512 bytes.
- *
- * This is never used when keys are 512 bits or smaller, and isn't used
- * on "US Domestic" ciphers in any case.
- */
-static final
-class RSA_ServerKeyExchange extends ServerKeyExchange
-{
-    private byte rsa_modulus[];     // 1 to 2^16 - 1 bytes
-    private byte rsa_exponent[];    // 1 to 2^16 - 1 bytes
-
-    private Signature signature;
-    private byte[] signatureBytes;
-
-    /*
-     * Hash the nonces and the ephemeral RSA public key.
-     */
-    private void updateSignature(byte clntNonce[], byte svrNonce[])
-            throws SignatureException {
-        int tmp;
-
-        signature.update(clntNonce);
-        signature.update(svrNonce);
-
-        tmp = rsa_modulus.length;
-        signature.update((byte)(tmp >> 8));
-        signature.update((byte)(tmp & 0x0ff));
-        signature.update(rsa_modulus);
-
-        tmp = rsa_exponent.length;
-        signature.update((byte)(tmp >> 8));
-        signature.update((byte)(tmp & 0x0ff));
-        signature.update(rsa_exponent);
-    }
-
-
-    /*
-     * Construct an RSA server key exchange message, using data
-     * known _only_ to the server.
-     *
-     * The client knows the public key corresponding to this private
-     * key, from the Certificate message sent previously.  To comply
-     * with US export regulations we use short RSA keys ... either
-     * long term ones in the server's X509 cert, or else ephemeral
-     * ones sent using this message.
-     */
-    RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
-            RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
-            throws GeneralSecurityException {
-        RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
-        rsa_modulus = toByteArray(rsaKey.getModulus());
-        rsa_exponent = toByteArray(rsaKey.getPublicExponent());
-        signature = RSASignature.getInstance();
-        signature.initSign(privateKey, sr);
-        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
-        signatureBytes = signature.sign();
-    }
-
-
-    /*
-     * Parse an RSA server key exchange message, using data known
-     * to the client (and, in some situations, eavesdroppers).
-     */
-    RSA_ServerKeyExchange(HandshakeInStream input)
-            throws IOException, NoSuchAlgorithmException {
-        signature = RSASignature.getInstance();
-        rsa_modulus = input.getBytes16();
-        rsa_exponent = input.getBytes16();
-        signatureBytes = input.getBytes16();
-    }
-
-    /*
-     * Get the ephemeral RSA public key that will be used in this
-     * SSL connection.
-     */
-    PublicKey getPublicKey() {
-        try {
-            KeyFactory kfac = JsseJce.getKeyFactory("RSA");
-            // modulus and exponent are always positive
-            RSAPublicKeySpec kspec = new RSAPublicKeySpec(
-                new BigInteger(1, rsa_modulus),
-                new BigInteger(1, rsa_exponent));
-            return kfac.generatePublic(kspec);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /*
-     * Verify the signed temporary key using the hashes computed
-     * from it and the two nonces.  This is called by clients
-     * with "exportable" RSA flavors.
-     */
-    boolean verify(PublicKey certifiedKey, RandomCookie clntNonce,
-            RandomCookie svrNonce) throws GeneralSecurityException {
-        signature.initVerify(certifiedKey);
-        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
-        return signature.verify(signatureBytes);
-    }
-
-    int messageLength() {
-        return 6 + rsa_modulus.length + rsa_exponent.length
-               + signatureBytes.length;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes16(rsa_modulus);
-        s.putBytes16(rsa_exponent);
-        s.putBytes16(signatureBytes);
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** RSA ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "RSA Modulus", rsa_modulus);
-            Debug.println(s, "RSA Public Exponent", rsa_exponent);
-        }
-    }
-}
-
-
-/*
- * Using Diffie-Hellman algorithm for key exchange.  All we really need to
- * do is securely get Diffie-Hellman keys (using the same P, G parameters)
- * to our peer, then we automatically have a shared secret without need
- * to exchange any more data.  (D-H only solutions, such as SKIP, could
- * eliminate key exchange negotiations and get faster connection setup.
- * But they still need a signature algorithm like DSS/DSA to support the
- * trusted distribution of keys without relying on unscalable physical
- * key distribution systems.)
- *
- * This class supports several DH-based key exchange algorithms, though
- * perhaps eventually each deserves its own class.  Notably, this has
- * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
- */
-static final
-class DH_ServerKeyExchange extends ServerKeyExchange
-{
-    // Fix message encoding, see 4348279
-    private final static boolean dhKeyExchangeFix =
-        Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
-
-    private byte                dh_p [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_g [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_Ys [];       // 1 to 2^16 - 1 bytes
-
-    private byte                signature [];
-
-    // protocol version being established using this ServerKeyExchange message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this ServerKeyExchange message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    /*
-     * Construct from initialized DH key object, for DH_anon
-     * key exchange.
-     */
-    DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        this.preferableSignatureAlgorithm = null;
-
-        // The DH key has been validated in the constructor of DHCrypt.
-        setValues(obj);
-        signature = null;
-    }
-
-    /*
-     * Construct from initialized DH key object and the key associated
-     * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
-     * key exchange.  (Constructor called by server.)
-     */
-    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
-            byte svrNonce[], SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm,
-            ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // The DH key has been validated in the constructor of DHCrypt.
-        setValues(obj);
-
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            this.preferableSignatureAlgorithm = null;
-            if (key.getAlgorithm().equals("DSA")) {
-                sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-            } else {
-                sig = RSASignature.getInstance();
-            }
-        }
-
-        sig.initSign(key, sr);
-        updateSignature(sig, clntNonce, svrNonce);
-        signature = sig.sign();
-    }
-
-    /*
-     * Construct a DH_ServerKeyExchange message from an input
-     * stream, as if sent from server to client for use with
-     * DH_anon key exchange
-     */
-    DH_ServerKeyExchange(HandshakeInStream input,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-        this.preferableSignatureAlgorithm = null;
-
-        dh_p = input.getBytes16();
-        dh_g = input.getBytes16();
-        dh_Ys = input.getBytes16();
-        KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-                                             new BigInteger(1, dh_p),
-                                             new BigInteger(1, dh_g)));
-
-        signature = null;
-    }
-
-    /*
-     * Construct a DH_ServerKeyExchange message from an input stream
-     * and a certificate, as if sent from server to client for use with
-     * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
-     */
-    DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
-            byte clntNonce[], byte svrNonce[], int messageSize,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // read params: ServerDHParams
-        dh_p = input.getBytes16();
-        dh_g = input.getBytes16();
-        dh_Ys = input.getBytes16();
-        KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-                                             new BigInteger(1, dh_p),
-                                             new BigInteger(1, dh_g)));
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hash = input.getInt8();         // hash algorithm
-            int signature = input.getInt8();    // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message");
-            }
-        } else {
-            this.preferableSignatureAlgorithm = null;
-        }
-
-        // read the signature
-        byte signature[];
-        if (dhKeyExchangeFix) {
-            signature = input.getBytes16();
-        } else {
-            messageSize -= (dh_p.length + 2);
-            messageSize -= (dh_g.length + 2);
-            messageSize -= (dh_Ys.length + 2);
-
-            signature = new byte[messageSize];
-            input.read(signature);
-        }
-
-        Signature sig;
-        String algorithm = publicKey.getAlgorithm();
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-            if (algorithm.equals("DSA")) {
-                sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-            } else if (algorithm.equals("RSA")) {
-                sig = RSASignature.getInstance();
-            } else {
-                throw new SSLKeyException("neither an RSA or a DSA key");
-            }
-        }
-
-        sig.initVerify(publicKey);
-        updateSignature(sig, clntNonce, svrNonce);
-
-        if (sig.verify(signature) == false ) {
-            throw new SSLKeyException("Server D-H key verification failed");
-        }
-    }
-
-    /* Return the Diffie-Hellman modulus */
-    BigInteger getModulus() {
-        return new BigInteger(1, dh_p);
-    }
-
-    /* Return the Diffie-Hellman base/generator */
-    BigInteger getBase() {
-        return new BigInteger(1, dh_g);
-    }
-
-    /* Return the server's Diffie-Hellman public key */
-    BigInteger getServerPublicKey() {
-        return new BigInteger(1, dh_Ys);
-    }
-
-    /*
-     * Update sig with nonces and Diffie-Hellman public key.
-     */
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
-        int tmp;
-
-        sig.update(clntNonce);
-        sig.update(svrNonce);
-
-        tmp = dh_p.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_p);
-
-        tmp = dh_g.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_g);
-
-        tmp = dh_Ys.length;
-        sig.update((byte)(tmp >> 8));
-        sig.update((byte)(tmp & 0x0ff));
-        sig.update(dh_Ys);
-    }
-
-    private void setValues(DHCrypt obj) {
-        dh_p = toByteArray(obj.getModulus());
-        dh_g = toByteArray(obj.getBase());
-        dh_Ys = toByteArray(obj.getPublicKey());
-    }
-
-    int messageLength() {
-        int temp = 6;   // overhead for p, g, y(s) values.
-
-        temp += dh_p.length;
-        temp += dh_g.length;
-        temp += dh_Ys.length;
-
-        if (signature != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                temp += SignatureAndHashAlgorithm.sizeInRecord();
-            }
-
-            temp += signature.length;
-            if (dhKeyExchangeFix) {
-                temp += 2;
-            }
-        }
-
-        return temp;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putBytes16(dh_p);
-        s.putBytes16(dh_g);
-        s.putBytes16(dh_Ys);
-
-        if (signature != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.putInt8(preferableSignatureAlgorithm.getHashValue());
-                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-            }
-
-            if (dhKeyExchangeFix) {
-                s.putBytes16(signature);
-            } else {
-                s.write(signature);
-            }
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** Diffie-Hellman ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "DH Modulus", dh_p);
-            Debug.println(s, "DH Base", dh_g);
-            Debug.println(s, "Server DH Public Key", dh_Ys);
-
-            if (signature == null) {
-                s.println("Anonymous");
-            } else {
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    s.println("Signature Algorithm " +
-                        preferableSignatureAlgorithm.getAlgorithmName());
-                }
-
-                s.println("Signed with a DSA or RSA public key");
-            }
-        }
-    }
-}
-
-/*
- * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
- * ciphersuites to communicate its ephemeral public key (including the
- * EC domain parameters).
- *
- * We support named curves only, no explicitly encoded curves.
- */
-static final
-class ECDH_ServerKeyExchange extends ServerKeyExchange {
-
-    // constants for ECCurveType
-    private final static int CURVE_EXPLICIT_PRIME = 1;
-    private final static int CURVE_EXPLICIT_CHAR2 = 2;
-    private final static int CURVE_NAMED_CURVE    = 3;
-
-    // id of the curve we are using
-    private int curveId;
-    // encoded public point
-    private byte[] pointBytes;
-
-    // signature bytes (or null if anonymous)
-    private byte[] signatureBytes;
-
-    // public key object encapsulated in this message
-    private ECPublicKey publicKey;
-
-    // protocol version being established using this ServerKeyExchange message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this ServerKeyExchange message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
-            byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm,
-            ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        publicKey = (ECPublicKey)obj.getPublicKey();
-        ECParameterSpec params = publicKey.getParams();
-        ECPoint point = publicKey.getW();
-        pointBytes = JsseJce.encodePoint(point, params.getCurve());
-        curveId = SupportedEllipticCurvesExtension.getCurveIndex(params);
-
-        if (privateKey == null) {
-            // ECDH_anon
-            return;
-        }
-
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(privateKey.getAlgorithm());
-        }
-        sig.initSign(privateKey);  // where is the SecureRandom?
-
-        updateSignature(sig, clntNonce, svrNonce);
-        signatureBytes = sig.sign();
-    }
-
-    /*
-     * Parse an ECDH server key exchange message.
-     */
-    ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
-            byte[] clntNonce, byte[] svrNonce,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion)
-            throws IOException, GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        // read params: ServerECDHParams
-        int curveType = input.getInt8();
-        ECParameterSpec parameters;
-        // These parsing errors should never occur as we negotiated
-        // the supported curves during the exchange of the Hello messages.
-        if (curveType == CURVE_NAMED_CURVE) {
-            curveId = input.getInt16();
-            if (SupportedEllipticCurvesExtension.isSupported(curveId)
-                    == false) {
-                throw new SSLHandshakeException(
-                    "Unsupported curveId: " + curveId);
-            }
-            String curveOid =
-                SupportedEllipticCurvesExtension.getCurveOid(curveId);
-            if (curveOid == null) {
-                throw new SSLHandshakeException(
-                    "Unknown named curve: " + curveId);
-            }
-            parameters = JsseJce.getECParameterSpec(curveOid);
-            if (parameters == null) {
-                throw new SSLHandshakeException(
-                    "Unsupported curve: " + curveOid);
-            }
-        } else {
-            throw new SSLHandshakeException(
-                "Unsupported ECCurveType: " + curveType);
-        }
-        pointBytes = input.getBytes8();
-
-        ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
-        KeyFactory factory = JsseJce.getKeyFactory("EC");
-        publicKey = (ECPublicKey)factory.generatePublic(
-            new ECPublicKeySpec(point, parameters));
-
-        if (signingKey == null) {
-            // ECDH_anon
-            return;
-        }
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hash = input.getInt8();         // hash algorithm
-            int signature = input.getInt8();    // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message");
-            }
-        }
-
-        // read the signature
-        signatureBytes = input.getBytes16();
-
-        // verify the signature
-        Signature sig;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(signingKey.getAlgorithm());
-        }
-        sig.initVerify(signingKey);
-
-        updateSignature(sig, clntNonce, svrNonce);
-
-        if (sig.verify(signatureBytes) == false ) {
-            throw new SSLKeyException(
-                "Invalid signature on ECDH server key exchange message");
-        }
-    }
-
-    /*
-     * Get the ephemeral EC public key encapsulated in this message.
-     */
-    ECPublicKey getPublicKey() {
-        return publicKey;
-    }
-
-    private static Signature getSignature(String keyAlgorithm)
-            throws NoSuchAlgorithmException {
-        if (keyAlgorithm.equals("EC")) {
-            return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
-        } else if (keyAlgorithm.equals("RSA")) {
-            return RSASignature.getInstance();
-        } else {
-            throw new NoSuchAlgorithmException("neither an RSA or a EC key");
-        }
-    }
-
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
-        sig.update(clntNonce);
-        sig.update(svrNonce);
-
-        sig.update((byte)CURVE_NAMED_CURVE);
-        sig.update((byte)(curveId >> 8));
-        sig.update((byte)curveId);
-        sig.update((byte)pointBytes.length);
-        sig.update(pointBytes);
-    }
-
-    int messageLength() {
-        int sigLen = 0;
-        if (signatureBytes != null) {
-            sigLen = 2 + signatureBytes.length;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                sigLen += SignatureAndHashAlgorithm.sizeInRecord();
-            }
-        }
-
-        return 4 + pointBytes.length + sigLen;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt8(CURVE_NAMED_CURVE);
-        s.putInt16(curveId);
-        s.putBytes8(pointBytes);
-
-        if (signatureBytes != null) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.putInt8(preferableSignatureAlgorithm.getHashValue());
-                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-            }
-
-            s.putBytes16(signatureBytes);
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        s.println("*** ECDH ServerKeyExchange");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            if (signatureBytes == null) {
-                s.println("Anonymous");
-            } else {
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    s.println("Signature Algorithm " +
-                            preferableSignatureAlgorithm.getAlgorithmName());
-                }
-            }
-
-            s.println("Server key: " + publicKey);
-        }
-    }
-}
-
-static final class DistinguishedName {
-
-    /*
-     * DER encoded distinguished name.
-     * TLS requires that its not longer than 65535 bytes.
-     */
-    byte name[];
-
-    DistinguishedName(HandshakeInStream input) throws IOException {
-        name = input.getBytes16();
-    }
-
-    DistinguishedName(X500Principal dn) {
-        name = dn.getEncoded();
-    }
-
-    X500Principal getX500Principal() throws IOException {
-        try {
-            return new X500Principal(name);
-        } catch (IllegalArgumentException e) {
-            throw (SSLProtocolException)new SSLProtocolException(
-                e.getMessage()).initCause(e);
-        }
-    }
-
-    int length() {
-        return 2 + name.length;
-    }
-
-    void send(HandshakeOutStream output) throws IOException {
-        output.putBytes16(name);
-    }
-
-    void print(PrintStream output) throws IOException {
-        X500Principal principal = new X500Principal(name);
-        output.println("<" + principal.toString() + ">");
-    }
-}
-
-/*
- * CertificateRequest ... SERVER --> CLIENT
- *
- * Authenticated servers may ask clients to authenticate themselves
- * in turn, using this message.
- *
- * Prior to TLS 1.2, the structure of the message is defined as:
- *     struct {
- *         ClientCertificateType certificate_types<1..2^8-1>;
- *         DistinguishedName certificate_authorities<0..2^16-1>;
- *     } CertificateRequest;
- *
- * In TLS 1.2, the structure is changed to:
- *     struct {
- *         ClientCertificateType certificate_types<1..2^8-1>;
- *         SignatureAndHashAlgorithm
- *           supported_signature_algorithms<2^16-1>;
- *         DistinguishedName certificate_authorities<0..2^16-1>;
- *     } CertificateRequest;
- *
- */
-static final
-class CertificateRequest extends HandshakeMessage
-{
-    // enum ClientCertificateType
-    static final int   cct_rsa_sign = 1;
-    static final int   cct_dss_sign = 2;
-    static final int   cct_rsa_fixed_dh = 3;
-    static final int   cct_dss_fixed_dh = 4;
-
-    // The existance of these two values is a bug in the SSL specification.
-    // They are never used in the protocol.
-    static final int   cct_rsa_ephemeral_dh = 5;
-    static final int   cct_dss_ephemeral_dh = 6;
-
-    // From RFC 4492 (ECC)
-    static final int    cct_ecdsa_sign       = 64;
-    static final int    cct_rsa_fixed_ecdh   = 65;
-    static final int    cct_ecdsa_fixed_ecdh = 66;
-
-    private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
-    private final static byte[] TYPES_ECC =
-        { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
-
-    byte                types [];               // 1 to 255 types
-    DistinguishedName   authorities [];         // 3 to 2^16 - 1
-        // ... "3" because that's the smallest DER-encoded X500 DN
-
-    // protocol version being established using this CertificateRequest message
-    ProtocolVersion protocolVersion;
-
-    // supported_signature_algorithms for TLS 1.2 or later
-    private Collection<SignatureAndHashAlgorithm> algorithms;
-
-    // length of supported_signature_algorithms
-    private int algorithmsLen;
-
-    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
-            Collection<SignatureAndHashAlgorithm> signAlgs,
-            ProtocolVersion protocolVersion) throws IOException {
-
-        this.protocolVersion = protocolVersion;
-
-        // always use X500Principal
-        authorities = new DistinguishedName[ca.length];
-        for (int i = 0; i < ca.length; i++) {
-            X500Principal x500Principal = ca[i].getSubjectX500Principal();
-            authorities[i] = new DistinguishedName(x500Principal);
-        }
-        // we support RSA, DSS, and ECDSA client authentication and they
-        // can be used with all ciphersuites. If this changes, the code
-        // needs to be adapted to take keyExchange into account.
-        // We only request ECDSA client auth if we have ECC crypto available.
-        this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
-
-        // Use supported_signature_algorithms for TLS 1.2 or later.
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (signAlgs == null || signAlgs.isEmpty()) {
-                throw new SSLProtocolException(
-                        "No supported signature algorithms");
-            }
-
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
-            algorithmsLen =
-                SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
-        } else {
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            algorithmsLen = 0;
-        }
-    }
-
-    CertificateRequest(HandshakeInStream input,
-            ProtocolVersion protocolVersion) throws IOException {
-
-        this.protocolVersion = protocolVersion;
-
-        // Read the certificate_types.
-        types = input.getBytes8();
-
-        // Read the supported_signature_algorithms for TLS 1.2 or later.
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            algorithmsLen = input.getInt16();
-            if (algorithmsLen < 2) {
-                throw new SSLProtocolException(
-                        "Invalid supported_signature_algorithms field");
-            }
-
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            int remains = algorithmsLen;
-            int sequence = 0;
-            while (remains > 1) {    // needs at least two bytes
-                int hash = input.getInt8();         // hash algorithm
-                int signature = input.getInt8();    // signature algorithm
-
-                SignatureAndHashAlgorithm algorithm =
-                    SignatureAndHashAlgorithm.valueOf(hash, signature,
-                                                                ++sequence);
-                algorithms.add(algorithm);
-                remains -= 2;  // one byte for hash, one byte for signature
-            }
-
-            if (remains != 0) {
-                throw new SSLProtocolException(
-                        "Invalid supported_signature_algorithms field");
-            }
-        } else {
-            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-            algorithmsLen = 0;
-        }
-
-        // read the certificate_authorities
-        int len = input.getInt16();
-        ArrayList<DistinguishedName> v = new ArrayList<>();
-        while (len >= 3) {
-            DistinguishedName dn = new DistinguishedName(input);
-            v.add(dn);
-            len -= dn.length();
-        }
-
-        if (len != 0) {
-            throw new SSLProtocolException("Bad CertificateRequest DN length");
-        }
-
-        authorities = v.toArray(new DistinguishedName[v.size()]);
-    }
-
-    X500Principal[] getAuthorities() throws IOException {
-        X500Principal[] ret = new X500Principal[authorities.length];
-        for (int i = 0; i < authorities.length; i++) {
-            ret[i] = authorities[i].getX500Principal();
-        }
-        return ret;
-    }
-
-    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
-        return algorithms;
-    }
-
-    @Override
-    int messageType() {
-        return ht_certificate_request;
-    }
-
-    @Override
-    int messageLength() {
-        int len = 1 + types.length + 2;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            len += algorithmsLen + 2;
-        }
-
-        for (int i = 0; i < authorities.length; i++) {
-            len += authorities[i].length();
-        }
-
-        return len;
-    }
-
-    @Override
-    void send(HandshakeOutStream output) throws IOException {
-        // put certificate_types
-        output.putBytes8(types);
-
-        // put supported_signature_algorithms
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            output.putInt16(algorithmsLen);
-            for (SignatureAndHashAlgorithm algorithm : algorithms) {
-                output.putInt8(algorithm.getHashValue());      // hash
-                output.putInt8(algorithm.getSignatureValue()); // signature
-            }
-        }
-
-        // put certificate_authorities
-        int len = 0;
-        for (int i = 0; i < authorities.length; i++) {
-            len += authorities[i].length();
-        }
-
-        output.putInt16(len);
-        for (int i = 0; i < authorities.length; i++) {
-            authorities[i].send(output);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** CertificateRequest");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            s.print("Cert Types: ");
-            for (int i = 0; i < types.length; i++) {
-                switch (types[i]) {
-                  case cct_rsa_sign:
-                    s.print("RSA"); break;
-                  case cct_dss_sign:
-                    s.print("DSS"); break;
-                  case cct_rsa_fixed_dh:
-                    s.print("Fixed DH (RSA sig)"); break;
-                  case cct_dss_fixed_dh:
-                    s.print("Fixed DH (DSS sig)"); break;
-                  case cct_rsa_ephemeral_dh:
-                    s.print("Ephemeral DH (RSA sig)"); break;
-                  case cct_dss_ephemeral_dh:
-                    s.print("Ephemeral DH (DSS sig)"); break;
-                  case cct_ecdsa_sign:
-                    s.print("ECDSA"); break;
-                  case cct_rsa_fixed_ecdh:
-                    s.print("Fixed ECDH (RSA sig)"); break;
-                  case cct_ecdsa_fixed_ecdh:
-                    s.print("Fixed ECDH (ECDSA sig)"); break;
-                  default:
-                    s.print("Type-" + (types[i] & 0xff)); break;
-                }
-                if (i != types.length - 1) {
-                    s.print(", ");
-                }
-            }
-            s.println();
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                StringBuffer buffer = new StringBuffer();
-                boolean opened = false;
-                for (SignatureAndHashAlgorithm signAlg : algorithms) {
-                    if (opened) {
-                        buffer.append(", " + signAlg.getAlgorithmName());
-                    } else {
-                        buffer.append(signAlg.getAlgorithmName());
-                        opened = true;
-                    }
-                }
-                s.println("Supported Signature Algorithms: " + buffer);
-            }
-
-            s.println("Cert Authorities:");
-            if (authorities.length == 0) {
-                s.println("<Empty>");
-            } else {
-                for (int i = 0; i < authorities.length; i++) {
-                    authorities[i].print(s);
-                }
-            }
-        }
-    }
-}
-
-
-/*
- * ServerHelloDone ... SERVER --> CLIENT
- *
- * When server's done sending its messages in response to the client's
- * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
- * client certificate request) it sends this message to flag that it's
- * done that part of the handshake.
- */
-static final
-class ServerHelloDone extends HandshakeMessage
-{
-    int messageType() { return ht_server_hello_done; }
-
-    ServerHelloDone() { }
-
-    ServerHelloDone(HandshakeInStream input)
-    {
-        // nothing to do
-    }
-
-    int messageLength()
-    {
-        return 0;
-    }
-
-    void send(HandshakeOutStream s) throws IOException
-    {
-        // nothing to send
-    }
-
-    void print(PrintStream s) throws IOException
-    {
-        s.println("*** ServerHelloDone");
-    }
-}
-
-
-/*
- * CertificateVerify ... CLIENT --> SERVER
- *
- * Sent after client sends signature-capable certificates (e.g. not
- * Diffie-Hellman) to verify.
- */
-static final class CertificateVerify extends HandshakeMessage {
-
-    // the signature bytes
-    private byte[] signature;
-
-    // protocol version being established using this ServerKeyExchange message
-    ProtocolVersion protocolVersion;
-
-    // the preferable signature algorithm used by this CertificateVerify message
-    private SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-
-    /*
-     * Create an RSA or DSA signed certificate verify message.
-     */
-    CertificateVerify(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, PrivateKey privateKey,
-            SecretKey masterSecret, SecureRandom sr,
-            SignatureAndHashAlgorithm signAlgorithm)
-            throws GeneralSecurityException {
-
-        this.protocolVersion = protocolVersion;
-
-        String algorithm = privateKey.getAlgorithm();
-        Signature sig = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            this.preferableSignatureAlgorithm = signAlgorithm;
-            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(protocolVersion, algorithm);
-        }
-        sig.initSign(privateKey, sr);
-        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
-                        masterSecret);
-        signature = sig.sign();
-    }
-
-    //
-    // Unmarshal the signed data from the input stream.
-    //
-    CertificateVerify(HandshakeInStream input,
-            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
-            ProtocolVersion protocolVersion) throws IOException  {
-
-        this.protocolVersion = protocolVersion;
-
-        // read the signature and hash algorithm
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            int hashAlg = input.getInt8();         // hash algorithm
-            int signAlg = input.getInt8();         // signature algorithm
-
-            preferableSignatureAlgorithm =
-                SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
-
-            // Is it a local supported signature algorithm?
-            if (!localSupportedSignAlgs.contains(
-                    preferableSignatureAlgorithm)) {
-                throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message");
-            }
-        }
-
-        // read the signature
-        signature = input.getBytes16();
-    }
-
-    /*
-     * Get the preferable signature algorithm used by this message
-     */
-    SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
-        return preferableSignatureAlgorithm;
-    }
-
-    /*
-     * Verify a certificate verify message. Return the result of verification,
-     * if there is a problem throw a GeneralSecurityException.
-     */
-    boolean verify(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, PublicKey publicKey,
-            SecretKey masterSecret) throws GeneralSecurityException {
-        String algorithm = publicKey.getAlgorithm();
-        Signature sig = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            sig = JsseJce.getSignature(
-                        preferableSignatureAlgorithm.getAlgorithmName());
-        } else {
-            sig = getSignature(protocolVersion, algorithm);
-        }
-        sig.initVerify(publicKey);
-        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
-                        masterSecret);
-        return sig.verify(signature);
-    }
-
-    /*
-     * Get the Signature object appropriate for verification using the
-     * given signature algorithm and protocol version.
-     */
-    private static Signature getSignature(ProtocolVersion protocolVersion,
-            String algorithm) throws GeneralSecurityException {
-        if (algorithm.equals("RSA")) {
-            return RSASignature.getInternalInstance();
-        } else if (algorithm.equals("DSA")) {
-            return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
-        } else if (algorithm.equals("EC")) {
-            return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
-        } else {
-            throw new SignatureException("Unrecognized algorithm: "
-                + algorithm);
-        }
-    }
-
-    /*
-     * Update the Signature with the data appropriate for the given
-     * signature algorithm and protocol version so that the object is
-     * ready for signing or verifying.
-     */
-    private static void updateSignature(Signature sig,
-            ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
-            throws SignatureException {
-
-        if (algorithm.equals("RSA")) {
-            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
-                MessageDigest md5Clone = handshakeHash.getMD5Clone();
-                MessageDigest shaClone = handshakeHash.getSHAClone();
-
-                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
-                    updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
-                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
-                }
-
-                // The signature must be an instance of RSASignature, need
-                // to use these hashes directly.
-                RSASignature.setHashes(sig, md5Clone, shaClone);
-            } else {  // TLS1.2+
-                sig.update(handshakeHash.getAllHandshakeMessages());
-            }
-        } else { // DSA, ECDSA
-            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
-                MessageDigest shaClone = handshakeHash.getSHAClone();
-
-                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
-                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
-                }
-
-                sig.update(shaClone.digest());
-            } else {  // TLS1.2+
-                sig.update(handshakeHash.getAllHandshakeMessages());
-            }
-        }
-    }
-
-    /*
-     * Update the MessageDigest for SSLv3 certificate verify or finished
-     * message calculation. The digest must already have been updated with
-     * all preceding handshake messages.
-     * Used by the Finished class as well.
-     */
-    private static void updateDigest(MessageDigest md,
-            byte[] pad1, byte[] pad2,
-            SecretKey masterSecret) {
-        // Digest the key bytes if available.
-        // Otherwise (sensitive key), try digesting the key directly.
-        // That is currently only implemented in SunPKCS11 using a private
-        // reflection API, so we avoid that if possible.
-        byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
-                        ? masterSecret.getEncoded() : null;
-        if (keyBytes != null) {
-            md.update(keyBytes);
-        } else {
-            digestKey(md, masterSecret);
-        }
-        md.update(pad1);
-        byte[] temp = md.digest();
-
-        if (keyBytes != null) {
-            md.update(keyBytes);
-        } else {
-            digestKey(md, masterSecret);
-        }
-        md.update(pad2);
-        md.update(temp);
-    }
-
-    private final static Class delegate;
-    private final static Field spiField;
-
-    static {
-        try {
-            delegate = Class.forName("java.security.MessageDigest$Delegate");
-            spiField = delegate.getDeclaredField("digestSpi");
-        } catch (Exception e) {
-            throw new RuntimeException("Reflection failed", e);
-        }
-        makeAccessible(spiField);
-    }
-
-    private static void makeAccessible(final AccessibleObject o) {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                o.setAccessible(true);
-                return null;
-            }
-        });
-    }
-
-    // ConcurrentHashMap does not allow null values, use this marker object
-    private final static Object NULL_OBJECT = new Object();
-
-    // cache Method objects per Spi class
-    // Note that this will prevent the Spi classes from being GC'd. We assume
-    // that is not a problem.
-    private final static Map<Class,Object> methodCache =
-                                        new ConcurrentHashMap<>();
-
-    private static void digestKey(MessageDigest md, SecretKey key) {
-        try {
-            // Verify that md is implemented via MessageDigestSpi, not
-            // via JDK 1.1 style MessageDigest subclassing.
-            if (md.getClass() != delegate) {
-                throw new Exception("Digest is not a MessageDigestSpi");
-            }
-            MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
-            Class<?> clazz = spi.getClass();
-            Object r = methodCache.get(clazz);
-            if (r == null) {
-                try {
-                    r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
-                    makeAccessible((Method)r);
-                } catch (NoSuchMethodException e) {
-                    r = NULL_OBJECT;
-                }
-                methodCache.put(clazz, r);
-            }
-            if (r == NULL_OBJECT) {
-                throw new Exception(
-                    "Digest does not support implUpdate(SecretKey)");
-            }
-            Method update = (Method)r;
-            update.invoke(spi, key);
-        } catch (Exception e) {
-            throw new RuntimeException(
-                "Could not obtain encoded key and "
-                + "MessageDigest cannot digest key", e);
-        }
-    }
-
-    @Override
-    int messageType() {
-        return ht_certificate_verify;
-    }
-
-    @Override
-    int messageLength() {
-        int temp = 2;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            temp += SignatureAndHashAlgorithm.sizeInRecord();
-        }
-
-        return temp + signature.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            s.putInt8(preferableSignatureAlgorithm.getHashValue());
-            s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
-        }
-
-        s.putBytes16(signature);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** CertificateVerify");
-
-        if (debug != null && Debug.isOn("verbose")) {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                s.println("Signature Algorithm " +
-                        preferableSignatureAlgorithm.getAlgorithmName());
-            }
-        }
-    }
-}
-
-
-/*
- * FINISHED ... sent by both CLIENT and SERVER
- *
- * This is the FINISHED message as defined in the SSL and TLS protocols.
- * Both protocols define this handshake message slightly differently.
- * This class supports both formats.
- *
- * When handshaking is finished, each side sends a "change_cipher_spec"
- * record, then immediately sends a "finished" handshake message prepared
- * according to the newly adopted cipher spec.
- *
- * NOTE that until this is sent, no application data may be passed, unless
- * some non-default cipher suite has already been set up on this connection
- * connection (e.g. a previous handshake arranged one).
- */
-static final class Finished extends HandshakeMessage {
-
-    // constant for a Finished message sent by the client
-    final static int CLIENT = 1;
-
-    // constant for a Finished message sent by the server
-    final static int SERVER = 2;
-
-    // enum Sender:  "CLNT" and "SRVR"
-    private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
-    private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
-
-    /*
-     * Contents of the finished message ("checksum"). For TLS, it
-     * is 12 bytes long, for SSLv3 36 bytes.
-     */
-    private byte[] verifyData;
-
-    /*
-     * Current cipher suite we are negotiating.  TLS 1.2 has
-     * ciphersuite-defined PRF algorithms.
-     */
-    private ProtocolVersion protocolVersion;
-    private CipherSuite cipherSuite;
-
-    /*
-     * Create a finished message to send to the remote peer.
-     */
-    Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
-            int sender, SecretKey master, CipherSuite cipherSuite) {
-        this.protocolVersion = protocolVersion;
-        this.cipherSuite = cipherSuite;
-        verifyData = getFinished(handshakeHash, sender, master);
-    }
-
-    /*
-     * Constructor that reads FINISHED message from stream.
-     */
-    Finished(ProtocolVersion protocolVersion, HandshakeInStream input,
-            CipherSuite cipherSuite) throws IOException {
-        this.protocolVersion = protocolVersion;
-        this.cipherSuite = cipherSuite;
-        int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
-        verifyData = new byte[msgLen];
-        input.read(verifyData);
-    }
-
-    /*
-     * Verify that the hashes here are what would have been produced
-     * according to a given set of inputs.  This is used to ensure that
-     * both client and server are fully in sync, and that the handshake
-     * computations have been successful.
-     */
-    boolean verify(HandshakeHash handshakeHash, int sender, SecretKey master) {
-        byte[] myFinished = getFinished(handshakeHash, sender, master);
-        return Arrays.equals(myFinished, verifyData);
-    }
-
-    /*
-     * Perform the actual finished message calculation.
-     */
-    private byte[] getFinished(HandshakeHash handshakeHash,
-            int sender, SecretKey masterKey) {
-        byte[] sslLabel;
-        String tlsLabel;
-        if (sender == CLIENT) {
-            sslLabel = SSL_CLIENT;
-            tlsLabel = "client finished";
-        } else if (sender == SERVER) {
-            sslLabel = SSL_SERVER;
-            tlsLabel = "server finished";
-        } else {
-            throw new RuntimeException("Invalid sender: " + sender);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            // TLS 1.0+
-            try {
-                byte [] seed;
-                String prfAlg;
-                PRF prf;
-
-                // Get the KeyGenerator alg and calculate the seed.
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    // TLS 1.2
-                    seed = handshakeHash.getFinishedHash();
-
-                    prfAlg = "SunTls12Prf";
-                    prf = cipherSuite.prfAlg;
-                } else {
-                    // TLS 1.0/1.1
-                    MessageDigest md5Clone = handshakeHash.getMD5Clone();
-                    MessageDigest shaClone = handshakeHash.getSHAClone();
-                    seed = new byte[36];
-                    md5Clone.digest(seed, 0, 16);
-                    shaClone.digest(seed, 16, 20);
-
-                    prfAlg = "SunTlsPrf";
-                    prf = P_NONE;
-                }
-
-                String prfHashAlg = prf.getPRFHashAlg();
-                int prfHashLength = prf.getPRFHashLength();
-                int prfBlockSize = prf.getPRFBlockSize();
-
-                /*
-                 * RFC 5246/7.4.9 says that finished messages can
-                 * be ciphersuite-specific in both length/PRF hash
-                 * algorithm.  If we ever run across a different
-                 * length, this call will need to be updated.
-                 */
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
-                    masterKey, tlsLabel, seed, 12,
-                    prfHashAlg, prfHashLength, prfBlockSize);
-
-                KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
-                kg.init(spec);
-                SecretKey prfKey = kg.generateKey();
-                if ("RAW".equals(prfKey.getFormat()) == false) {
-                    throw new ProviderException(
-                        "Invalid PRF output, format must be RAW");
-                }
-                byte[] finished = prfKey.getEncoded();
-                return finished;
-            } catch (GeneralSecurityException e) {
-                throw new RuntimeException("PRF failed", e);
-            }
-        } else {
-            // SSLv3
-            MessageDigest md5Clone = handshakeHash.getMD5Clone();
-            MessageDigest shaClone = handshakeHash.getSHAClone();
-            updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
-            updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
-            byte[] finished = new byte[36];
-            try {
-                md5Clone.digest(finished, 0, 16);
-                shaClone.digest(finished, 16, 20);
-            } catch (DigestException e) {
-                // cannot occur
-                throw new RuntimeException("Digest failed", e);
-            }
-            return finished;
-        }
-    }
-
-    /*
-     * Update the MessageDigest for SSLv3 finished message calculation.
-     * The digest must already have been updated with all preceding handshake
-     * messages. This operation is almost identical to the certificate verify
-     * hash, reuse that code.
-     */
-    private static void updateDigest(MessageDigest md, byte[] sender,
-            byte[] pad1, byte[] pad2, SecretKey masterSecret) {
-        md.update(sender);
-        CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
-    }
-
-    // get the verify_data of the finished message
-    byte[] getVerifyData() {
-        return verifyData;
-    }
-
-    @Override
-    int messageType() { return ht_finished; }
-
-    @Override
-    int messageLength() {
-        return verifyData.length;
-    }
-
-    @Override
-    void send(HandshakeOutStream out) throws IOException {
-        out.write(verifyData);
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** Finished");
-        if (debug != null && Debug.isOn("verbose")) {
-            Debug.println(s, "verify_data", verifyData);
-            s.println("***");
-        }
-    }
-}
-
-//
-// END of nested classes
-//
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java b/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java
deleted file mode 100755
index 25aeed6..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.OutputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-
-/**
- * Output stream for handshake data.  This is used only internally
- * to the SSL classes.
- *
- * MT note:  one thread at a time is presumed be writing handshake
- * messages, but (after initial connection setup) it's possible to
- * have other threads reading/writing application data.  It's the
- * SSLSocketImpl class that synchronizes record writes.
- *
- * @author  David Brownell
- */
-public class HandshakeOutStream extends OutputStream {
-
-    private SSLSocketImpl socket;
-    private SSLEngineImpl engine;
-
-    OutputRecord r;
-
-    HandshakeOutStream(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash,
-            SSLSocketImpl socket) {
-        this.socket = socket;
-        r = new OutputRecord(Record.ct_handshake);
-        init(protocolVersion, helloVersion, handshakeHash);
-    }
-
-    HandshakeOutStream(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash,
-            SSLEngineImpl engine) {
-        this.engine = engine;
-        r = new EngineOutputRecord(Record.ct_handshake, engine);
-        init(protocolVersion, helloVersion, handshakeHash);
-    }
-
-    private void init(ProtocolVersion protocolVersion,
-            ProtocolVersion helloVersion, HandshakeHash handshakeHash) {
-        r.setVersion(protocolVersion);
-        r.setHelloVersion(helloVersion);
-        r.setHandshakeHash(handshakeHash);
-    }
-
-
-    /*
-     * Update the handshake data hashes ... mostly for use after a
-     * client cert has been sent, so the cert verify message can be
-     * constructed correctly yet without forcing extra I/O.  In all
-     * other cases, automatic hash calculation suffices.
-     */
-    void doHashes() {
-        r.doHashes();
-    }
-
-    /*
-     * Write some data out onto the stream ... buffers as much as possible.
-     * Hashes are updated automatically if something gets flushed to the
-     * network (e.g. a big cert message etc).
-     */
-    public void write(byte buf[], int off, int len) throws IOException {
-        while (len > 0) {
-            int howmuch = Math.min(len, r.availableDataBytes());
-
-            if (howmuch == 0) {
-                flush();
-            } else {
-                r.write(buf, off, howmuch);
-                off += howmuch;
-                len -= howmuch;
-            }
-        }
-    }
-
-    /*
-     * write-a-byte
-     */
-    public void write(int i) throws IOException {
-        if (r.availableDataBytes() < 1) {
-            flush();
-        }
-        r.write(i);
-    }
-
-    public void flush() throws IOException {
-        if (socket != null) {
-            try {
-                socket.writeRecord(r);
-            } catch (IOException e) {
-                // Had problems writing; check if there was an
-                // alert from peer. If alert received, waitForClose
-                // will throw an exception for the alert
-                socket.waitForClose(true);
-
-                // No alert was received, just rethrow exception
-                throw e;
-            }
-        } else {  // engine != null
-            /*
-             * Even if record might be empty, flush anyway in case
-             * there is a finished handshake message that we need
-             * to queue.
-             */
-            engine.writeRecord((EngineOutputRecord)r);
-        }
-    }
-
-    /*
-     * Tell the OutputRecord that a finished message was
-     * contained either in this record or the one immeiately
-     * preceeding it.  We need to reliably pass back notifications
-     * that a finish message occured.
-     */
-    void setFinishedMsg() {
-        assert(socket == null);
-
-        ((EngineOutputRecord)r).setFinishedMsg();
-    }
-
-    /*
-     * Put integers encoded in standard 8, 16, 24, and 32 bit
-     * big endian formats. Note that OutputStream.write(int) only
-     * writes the least significant 8 bits and ignores the rest.
-     */
-
-    void putInt8(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT08);
-        r.write(i);
-    }
-
-    void putInt16(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT16);
-        if (r.availableDataBytes() < 2) {
-            flush();
-        }
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    void putInt24(int i) throws IOException {
-        checkOverflow(i, Record.OVERFLOW_OF_INT24);
-        if (r.availableDataBytes() < 3) {
-            flush();
-        }
-        r.write(i >> 16);
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    void putInt32(int i) throws IOException {
-        if (r.availableDataBytes() < 4) {
-            flush();
-        }
-        r.write(i >> 24);
-        r.write(i >> 16);
-        r.write(i >> 8);
-        r.write(i);
-    }
-
-    /*
-     * Put byte arrays with length encoded as 8, 16, 24 bit
-     * integers in big-endian format.
-     */
-    void putBytes8(byte b[]) throws IOException {
-        if (b == null) {
-            putInt8(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT08);
-        }
-        putInt8(b.length);
-        write(b, 0, b.length);
-    }
-
-    public void putBytes16(byte b[]) throws IOException {
-        if (b == null) {
-            putInt16(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT16);
-        }
-        putInt16(b.length);
-        write(b, 0, b.length);
-    }
-
-    void putBytes24(byte b[]) throws IOException {
-        if (b == null) {
-            putInt24(0);
-            return;
-        } else {
-            checkOverflow(b.length, Record.OVERFLOW_OF_INT24);
-        }
-        putInt24(b.length);
-        write(b, 0, b.length);
-    }
-
-    private void checkOverflow(int length, int overflow) {
-        if (length >= overflow) {
-            // internal_error alert will be triggered
-            throw new RuntimeException(
-                    "Field length overflow, the field length (" +
-                    length + ") should be less than " + overflow);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Handshaker.java b/ojluni/src/main/java/sun/security/ssl/Handshaker.java
deleted file mode 100755
index 2f1d01b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Handshaker.java
+++ /dev/null
@@ -1,1384 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.NoSuchAlgorithmException;
-import java.security.AccessController;
-import java.security.AlgorithmConstraints;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
-
-import sun.security.internal.spec.*;
-import sun.security.internal.interfaces.TlsMasterSecret;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-
-import static sun.security.ssl.CipherSuite.PRF.*;
-
-/**
- * Handshaker ... processes handshake records from an SSL V3.0
- * data stream, handling all the details of the handshake protocol.
- *
- * Note that the real protocol work is done in two subclasses, the  base
- * class just provides the control flow and key generation framework.
- *
- * @author David Brownell
- */
-abstract class Handshaker {
-
-    // protocol version being established using this Handshaker
-    ProtocolVersion protocolVersion;
-
-    // the currently active protocol version during a renegotiation
-    ProtocolVersion     activeProtocolVersion;
-
-    // security parameters for secure renegotiation.
-    boolean             secureRenegotiation;
-    byte[]              clientVerifyData;
-    byte[]              serverVerifyData;
-
-    // Is it an initial negotiation  or a renegotiation?
-    boolean                     isInitialHandshake;
-
-    // List of enabled protocols
-    private ProtocolList        enabledProtocols;
-
-    // List of enabled CipherSuites
-    private CipherSuiteList     enabledCipherSuites;
-
-    // The endpoint identification protocol
-    String              identificationProtocol;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
-
-    // Local supported signature and algorithms
-    Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
-
-    // Peer supported signature and algorithms
-    Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
-
-    /*
-
-    /*
-     * List of active protocols
-     *
-     * Active protocols is a subset of enabled protocols, and will
-     * contain only those protocols that have vaild cipher suites
-     * enabled.
-     */
-    private ProtocolList       activeProtocols;
-
-    /*
-     * List of active cipher suites
-     *
-     * Active cipher suites is a subset of enabled cipher suites, and will
-     * contain only those cipher suites available for the active protocols.
-     */
-    private CipherSuiteList    activeCipherSuites;
-
-    private boolean             isClient;
-    private boolean             needCertVerify;
-
-    SSLSocketImpl               conn = null;
-    SSLEngineImpl               engine = null;
-
-    HandshakeHash               handshakeHash;
-    HandshakeInStream           input;
-    HandshakeOutStream          output;
-    int                         state;
-    SSLContextImpl              sslContext;
-    RandomCookie                clnt_random, svr_random;
-    SSLSessionImpl              session;
-
-    // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
-    CipherSuite         cipherSuite;
-
-    // current key exchange. Never null, initially K_NULL
-    KeyExchange         keyExchange;
-
-    /* True if this session is being resumed (fast handshake) */
-    boolean             resumingSession;
-
-    /* True if it's OK to start a new SSL session */
-    boolean             enableNewSession;
-
-    // Temporary storage for the individual keys. Set by
-    // calculateConnectionKeys() and cleared once the ciphers are
-    // activated.
-    private SecretKey clntWriteKey, svrWriteKey;
-    private IvParameterSpec clntWriteIV, svrWriteIV;
-    private SecretKey clntMacSecret, svrMacSecret;
-
-    /*
-     * Delegated task subsystem data structures.
-     *
-     * If thrown is set, we need to propagate this back immediately
-     * on entry into processMessage().
-     *
-     * Data is protected by the SSLEngine.this lock.
-     */
-    private volatile boolean taskDelegated = false;
-    private volatile DelegatedTask delegatedTask = null;
-    private volatile Exception thrown = null;
-
-    // Could probably use a java.util.concurrent.atomic.AtomicReference
-    // here instead of using this lock.  Consider changing.
-    private Object thrownLock = new Object();
-
-    /* Class and subclass dynamic debugging support */
-    static final Debug debug = Debug.getInstance("ssl");
-
-    // By default, disable the unsafe legacy session renegotiation
-    static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty(
-                    "sun.security.ssl.allowUnsafeRenegotiation", false);
-
-    // For maximum interoperability and backward compatibility, RFC 5746
-    // allows server (or client) to accept ClientHello (or ServerHello)
-    // message without the secure renegotiation_info extension or SCSV.
-    //
-    // For maximum security, RFC 5746 also allows server (or client) to
-    // reject such message with a fatal "handshake_failure" alert.
-    //
-    // By default, allow such legacy hello messages.
-    static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty(
-                    "sun.security.ssl.allowLegacyHelloMessages", true);
-
-    // need to dispose the object when it is invalidated
-    boolean invalidated;
-
-    Handshaker(SSLSocketImpl c, SSLContextImpl context,
-            ProtocolList enabledProtocols, boolean needCertVerify,
-            boolean isClient, ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-        this.conn = c;
-        init(context, enabledProtocols, needCertVerify, isClient,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    Handshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols, boolean needCertVerify,
-            boolean isClient, ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-        this.engine = engine;
-        init(context, enabledProtocols, needCertVerify, isClient,
-            activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-            clientVerifyData, serverVerifyData);
-    }
-
-    private void init(SSLContextImpl context, ProtocolList enabledProtocols,
-            boolean needCertVerify, boolean isClient,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println(
-                "Allow unsafe renegotiation: " + allowUnsafeRenegotiation +
-                "\nAllow legacy hello messages: " + allowLegacyHelloMessages +
-                "\nIs initial handshake: " + isInitialHandshake +
-                "\nIs secure renegotiation: " + secureRenegotiation);
-        }
-
-        this.sslContext = context;
-        this.isClient = isClient;
-        this.needCertVerify = needCertVerify;
-        this.activeProtocolVersion = activeProtocolVersion;
-        this.isInitialHandshake = isInitialHandshake;
-        this.secureRenegotiation = secureRenegotiation;
-        this.clientVerifyData = clientVerifyData;
-        this.serverVerifyData = serverVerifyData;
-        enableNewSession = true;
-        invalidated = false;
-
-        setCipherSuite(CipherSuite.C_NULL);
-        setEnabledProtocols(enabledProtocols);
-
-        if (conn != null) {
-            algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
-        } else {        // engine != null
-            algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
-        }
-
-
-        //
-        // In addition to the connection state machine, controlling
-        // how the connection deals with the different sorts of records
-        // that get sent (notably handshake transitions!), there's
-        // also a handshaking state machine that controls message
-        // sequencing.
-        //
-        // It's a convenient artifact of the protocol that this can,
-        // with only a couple of minor exceptions, be driven by the
-        // type constant for the last message seen:  except for the
-        // client's cert verify, those constants are in a convenient
-        // order to drastically simplify state machine checking.
-        //
-        state = -2;  // initialized but not activated
-    }
-
-    /*
-     * Reroutes calls to the SSLSocket or SSLEngine (*SE).
-     *
-     * We could have also done it by extra classes
-     * and letting them override, but this seemed much
-     * less involved.
-     */
-    void fatalSE(byte b, String diagnostic) throws IOException {
-        fatalSE(b, diagnostic, null);
-    }
-
-    void fatalSE(byte b, Throwable cause) throws IOException {
-        fatalSE(b, null, cause);
-    }
-
-    void fatalSE(byte b, String diagnostic, Throwable cause)
-            throws IOException {
-        if (conn != null) {
-            conn.fatal(b, diagnostic, cause);
-        } else {
-            engine.fatal(b, diagnostic, cause);
-        }
-    }
-
-    void warningSE(byte b) {
-        if (conn != null) {
-            conn.warning(b);
-        } else {
-            engine.warning(b);
-        }
-    }
-
-    String getRawHostnameSE() {
-        if (conn != null) {
-            return conn.getRawHostname();
-        } else {
-            return engine.getPeerHost();
-        }
-    }
-
-    String getHostSE() {
-        if (conn != null) {
-            return conn.getHost();
-        } else {
-            return engine.getPeerHost();
-        }
-    }
-
-    String getHostAddressSE() {
-        if (conn != null) {
-            return conn.getInetAddress().getHostAddress();
-        } else {
-            /*
-             * This is for caching only, doesn't matter that's is really
-             * a hostname.  The main thing is that it doesn't do
-             * a reverse DNS lookup, potentially slowing things down.
-             */
-            return engine.getPeerHost();
-        }
-    }
-
-    boolean isLoopbackSE() {
-        if (conn != null) {
-            return conn.getInetAddress().isLoopbackAddress();
-        } else {
-            return false;
-        }
-    }
-
-    int getPortSE() {
-        if (conn != null) {
-            return conn.getPort();
-        } else {
-            return engine.getPeerPort();
-        }
-    }
-
-    int getLocalPortSE() {
-        if (conn != null) {
-            return conn.getLocalPort();
-        } else {
-            return -1;
-        }
-    }
-
-    AccessControlContext getAccSE() {
-        if (conn != null) {
-            return conn.getAcc();
-        } else {
-            return engine.getAcc();
-        }
-    }
-
-    private void setVersionSE(ProtocolVersion protocolVersion) {
-        if (conn != null) {
-            conn.setVersion(protocolVersion);
-        } else {
-            engine.setVersion(protocolVersion);
-        }
-    }
-
-    /**
-     * Set the active protocol version and propagate it to the SSLSocket
-     * and our handshake streams. Called from ClientHandshaker
-     * and ServerHandshaker with the negotiated protocol version.
-     */
-    void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        setVersionSE(protocolVersion);
-
-        output.r.setVersion(protocolVersion);
-    }
-
-    /**
-     * Set the enabled protocols. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
-     * handshake is not yet in progress).
-     */
-    void setEnabledProtocols(ProtocolList enabledProtocols) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-
-        this.enabledProtocols = enabledProtocols;
-    }
-
-    /**
-     * Set the enabled cipher suites. Called from
-     * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
-     * handshake is not yet in progress).
-     */
-    void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-        this.enabledCipherSuites = enabledCipherSuites;
-    }
-
-    /**
-     * Set the algorithm constraints. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the
-     * handshake is not yet in progress).
-     */
-    void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
-        activeCipherSuites = null;
-        activeProtocols = null;
-
-        this.algorithmConstraints =
-            new SSLAlgorithmConstraints(algorithmConstraints);
-        this.localSupportedSignAlgs = null;
-    }
-
-    Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
-        if (localSupportedSignAlgs == null) {
-            localSupportedSignAlgs =
-                SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                                    algorithmConstraints);
-        }
-
-        return localSupportedSignAlgs;
-    }
-
-    void setPeerSupportedSignAlgs(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        peerSupportedSignAlgs =
-            new ArrayList<SignatureAndHashAlgorithm>(algorithms);
-    }
-
-    Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() {
-        return peerSupportedSignAlgs;
-    }
-
-
-    /**
-     * Set the identification protocol. Called from the constructor or
-     * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
-     * handshake is not yet in progress).
-     */
-    void setIdentificationProtocol(String protocol) {
-        this.identificationProtocol = protocol;
-    }
-
-    /**
-     * Prior to handshaking, activate the handshake and initialize the version,
-     * input stream and output stream.
-     */
-    void activate(ProtocolVersion helloVersion) throws IOException {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        if (activeProtocols.collection().isEmpty() ||
-                activeProtocols.max.v == ProtocolVersion.NONE.v) {
-            throw new SSLHandshakeException("No appropriate protocol");
-        }
-
-        if (activeCipherSuites == null) {
-            activeCipherSuites = getActiveCipherSuites();
-        }
-
-        if (activeCipherSuites.collection().isEmpty()) {
-            throw new SSLHandshakeException("No appropriate cipher suite");
-        }
-
-        // temporary protocol version until the actual protocol version
-        // is negotiated in the Hello exchange. This affects the record
-        // version we sent with the ClientHello.
-        if (!isInitialHandshake) {
-            protocolVersion = activeProtocolVersion;
-        } else {
-            protocolVersion = activeProtocols.max;
-        }
-
-        if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
-            helloVersion = activeProtocols.helloVersion;
-        }
-
-        // We accumulate digests of the handshake messages so that
-        // we can read/write CertificateVerify and Finished messages,
-        // getting assurance against some particular active attacks.
-        Set<String> localSupportedHashAlgorithms =
-            SignatureAndHashAlgorithm.getHashAlgorithmNames(
-                getLocalSupportedSignAlgs());
-        handshakeHash = new HandshakeHash(!isClient, needCertVerify,
-            localSupportedHashAlgorithms);
-
-        // Generate handshake input/output stream.
-        input = new HandshakeInStream(handshakeHash);
-        if (conn != null) {
-            output = new HandshakeOutStream(protocolVersion, helloVersion,
-                                        handshakeHash, conn);
-            conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
-            conn.getAppInputStream().r.setHelloVersion(helloVersion);
-            conn.getAppOutputStream().r.setHelloVersion(helloVersion);
-        } else {
-            output = new HandshakeOutStream(protocolVersion, helloVersion,
-                                        handshakeHash, engine);
-            engine.inputRecord.setHandshakeHash(handshakeHash);
-            engine.inputRecord.setHelloVersion(helloVersion);
-            engine.outputRecord.setHelloVersion(helloVersion);
-        }
-
-        // move state to activated
-        state = -1;
-    }
-
-    /**
-     * Set cipherSuite and keyExchange to the given CipherSuite.
-     * Does not perform any verification that this is a valid selection,
-     * this must be done before calling this method.
-     */
-    void setCipherSuite(CipherSuite s) {
-        this.cipherSuite = s;
-        this.keyExchange = s.keyExchange;
-    }
-
-    /**
-     * Check if the given ciphersuite is enabled and available.
-     * Does not check if the required server certificates are available.
-     */
-    boolean isNegotiable(CipherSuite s) {
-        if (activeCipherSuites == null) {
-            activeCipherSuites = getActiveCipherSuites();
-        }
-
-        return activeCipherSuites.contains(s) && s.isNegotiable();
-    }
-
-    /**
-     * Check if the given protocol version is enabled and available.
-     */
-    boolean isNegotiable(ProtocolVersion protocolVersion) {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        return activeProtocols.contains(protocolVersion);
-    }
-
-    /**
-     * Select a protocol version from the list. Called from
-     * ServerHandshaker to negotiate protocol version.
-     *
-     * Return the lower of the protocol version suggested in the
-     * clien hello and the highest supported by the server.
-     */
-    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
-        if (activeProtocols == null) {
-            activeProtocols = getActiveProtocols();
-        }
-
-        return activeProtocols.selectProtocolVersion(protocolVersion);
-    }
-
-    /**
-     * Get the active cipher suites.
-     *
-     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
-     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
-     * negotiate these cipher suites in TLS 1.1 or later mode.
-     *
-     * Therefore, when the active protocols only include TLS 1.1 or later,
-     * the client cannot request to negotiate those obsoleted cipher
-     * suites.  That is, the obsoleted suites should not be included in the
-     * client hello. So we need to create a subset of the enabled cipher
-     * suites, the active cipher suites, which does not contain obsoleted
-     * cipher suites of the minimum active protocol.
-     *
-     * Return empty list instead of null if no active cipher suites.
-     */
-    CipherSuiteList getActiveCipherSuites() {
-        if (activeCipherSuites == null) {
-            if (activeProtocols == null) {
-                activeProtocols = getActiveProtocols();
-            }
-
-            ArrayList<CipherSuite> suites = new ArrayList<>();
-            if (!(activeProtocols.collection().isEmpty()) &&
-                    activeProtocols.min.v != ProtocolVersion.NONE.v) {
-                for (CipherSuite suite : enabledCipherSuites.collection()) {
-                    if (suite.obsoleted > activeProtocols.min.v &&
-                            suite.supported <= activeProtocols.max.v) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-                            suites.add(suite);
-                        }
-                    } else if (debug != null && Debug.isOn("verbose")) {
-                        if (suite.obsoleted <= activeProtocols.min.v) {
-                            System.out.println(
-                                "Ignoring obsoleted cipher suite: " + suite);
-                        } else {
-                            System.out.println(
-                                "Ignoring unsupported cipher suite: " + suite);
-                        }
-                    }
-                }
-            }
-            activeCipherSuites = new CipherSuiteList(suites);
-        }
-
-        return activeCipherSuites;
-    }
-
-    /*
-     * Get the active protocol versions.
-     *
-     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
-     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
-     * negotiate these cipher suites in TLS 1.1 or later mode.
-     *
-     * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
-     * only enabled cipher suite, the client cannot request TLS 1.1 or
-     * later, even though TLS 1.1 or later is enabled.  We need to create a
-     * subset of the enabled protocols, called the active protocols, which
-     * contains protocols appropriate to the list of enabled Ciphersuites.
-     *
-     * Return empty list instead of null if no active protocol versions.
-     */
-    ProtocolList getActiveProtocols() {
-        if (activeProtocols == null) {
-            ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
-            for (ProtocolVersion protocol : enabledProtocols.collection()) {
-                boolean found = false;
-                for (CipherSuite suite : enabledCipherSuites.collection()) {
-                    if (suite.isAvailable() && suite.obsoleted > protocol.v &&
-                                               suite.supported <= protocol.v) {
-                        if (algorithmConstraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                suite.name, null)) {
-                            protocols.add(protocol);
-                            found = true;
-                            break;
-                        } else if (debug != null && Debug.isOn("verbose")) {
-                            System.out.println(
-                                "Ignoring disabled cipher suite: " + suite +
-                                 " for " + protocol);
-                        }
-                    } else if (debug != null && Debug.isOn("verbose")) {
-                        System.out.println(
-                            "Ignoring unsupported cipher suite: " + suite +
-                                 " for " + protocol);
-                    }
-                }
-                if (!found && (debug != null) && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "No available cipher suite for " + protocol);
-                }
-            }
-            activeProtocols = new ProtocolList(protocols);
-        }
-
-        return activeProtocols;
-    }
-
-    /**
-     * As long as handshaking has not activated, we can
-     * change whether session creations are allowed.
-     *
-     * Callers should do their own checking if handshaking
-     * has activated.
-     */
-    void setEnableSessionCreation(boolean newSessions) {
-        enableNewSession = newSessions;
-    }
-
-    /**
-     * Create a new read cipher and return it to caller.
-     */
-    CipherBox newReadCipher() throws NoSuchAlgorithmException {
-        BulkCipher cipher = cipherSuite.cipher;
-        CipherBox box;
-        if (isClient) {
-            box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   sslContext.getSecureRandom(), false);
-            svrWriteKey = null;
-            svrWriteIV = null;
-        } else {
-            box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   sslContext.getSecureRandom(), false);
-            clntWriteKey = null;
-            clntWriteIV = null;
-        }
-        return box;
-    }
-
-    /**
-     * Create a new write cipher and return it to caller.
-     */
-    CipherBox newWriteCipher() throws NoSuchAlgorithmException {
-        BulkCipher cipher = cipherSuite.cipher;
-        CipherBox box;
-        if (isClient) {
-            box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   sslContext.getSecureRandom(), true);
-            clntWriteKey = null;
-            clntWriteIV = null;
-        } else {
-            box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   sslContext.getSecureRandom(), true);
-            svrWriteKey = null;
-            svrWriteIV = null;
-        }
-        return box;
-    }
-
-    /**
-     * Create a new read MAC and return it to caller.
-     */
-    MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException {
-        MacAlg macAlg = cipherSuite.macAlg;
-        MAC mac;
-        if (isClient) {
-            mac = macAlg.newMac(protocolVersion, svrMacSecret);
-            svrMacSecret = null;
-        } else {
-            mac = macAlg.newMac(protocolVersion, clntMacSecret);
-            clntMacSecret = null;
-        }
-        return mac;
-    }
-
-    /**
-     * Create a new write MAC and return it to caller.
-     */
-    MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException {
-        MacAlg macAlg = cipherSuite.macAlg;
-        MAC mac;
-        if (isClient) {
-            mac = macAlg.newMac(protocolVersion, clntMacSecret);
-            clntMacSecret = null;
-        } else {
-            mac = macAlg.newMac(protocolVersion, svrMacSecret);
-            svrMacSecret = null;
-        }
-        return mac;
-    }
-
-    /*
-     * Returns true iff the handshake sequence is done, so that
-     * this freshly created session can become the current one.
-     */
-    boolean isDone() {
-        return state == HandshakeMessage.ht_finished;
-    }
-
-
-    /*
-     * Returns the session which was created through this
-     * handshake sequence ... should be called after isDone()
-     * returns true.
-     */
-    SSLSessionImpl getSession() {
-        return session;
-    }
-
-    /*
-     * Set the handshake session
-     */
-    void setHandshakeSessionSE(SSLSessionImpl handshakeSession) {
-        if (conn != null) {
-            conn.setHandshakeSession(handshakeSession);
-        } else {
-            engine.setHandshakeSession(handshakeSession);
-        }
-    }
-
-    /*
-     * Returns true if renegotiation is in use for this connection.
-     */
-    boolean isSecureRenegotiation() {
-        return secureRenegotiation;
-    }
-
-    /*
-     * Returns the verify_data from the Finished message sent by the client.
-     */
-    byte[] getClientVerifyData() {
-        return clientVerifyData;
-    }
-
-    /*
-     * Returns the verify_data from the Finished message sent by the server.
-     */
-    byte[] getServerVerifyData() {
-        return serverVerifyData;
-    }
-
-    /*
-     * This routine is fed SSL handshake records when they become available,
-     * and processes messages found therein.
-     */
-    void process_record(InputRecord r, boolean expectingFinished)
-            throws IOException {
-
-        checkThrown();
-
-        /*
-         * Store the incoming handshake data, then see if we can
-         * now process any completed handshake messages
-         */
-        input.incomingRecord(r);
-
-        /*
-         * We don't need to create a separate delegatable task
-         * for finished messages.
-         */
-        if ((conn != null) || expectingFinished) {
-            processLoop();
-        } else {
-            delegateTask(new PrivilegedExceptionAction<Void>() {
-                public Void run() throws Exception {
-                    processLoop();
-                    return null;
-                }
-            });
-        }
-    }
-
-    /*
-     * On input, we hash messages one at a time since servers may need
-     * to access an intermediate hash to validate a CertificateVerify
-     * message.
-     *
-     * Note that many handshake messages can come in one record (and often
-     * do, to reduce network resource utilization), and one message can also
-     * require multiple records (e.g. very large Certificate messages).
-     */
-    void processLoop() throws IOException {
-
-        // need to read off 4 bytes at least to get the handshake
-        // message type and length.
-        while (input.available() >= 4) {
-            byte messageType;
-            int messageLen;
-
-            /*
-             * See if we can read the handshake message header, and
-             * then the entire handshake message.  If not, wait till
-             * we can read and process an entire message.
-             */
-            input.mark(4);
-
-            messageType = (byte)input.getInt8();
-            messageLen = input.getInt24();
-
-            if (input.available() < messageLen) {
-                input.reset();
-                return;
-            }
-
-            /*
-             * Process the messsage.  We require
-             * that processMessage() consumes the entire message.  In
-             * lieu of explicit error checks (how?!) we assume that the
-             * data will look like garbage on encoding/processing errors,
-             * and that other protocol code will detect such errors.
-             *
-             * Note that digesting is normally deferred till after the
-             * message has been processed, though to process at least the
-             * client's Finished message (i.e. send the server's) we need
-             * to acccelerate that digesting.
-             *
-             * Also, note that hello request messages are never hashed;
-             * that includes the hello request header, too.
-             */
-            if (messageType == HandshakeMessage.ht_hello_request) {
-                input.reset();
-                processMessage(messageType, messageLen);
-                input.ignore(4 + messageLen);
-            } else {
-                input.mark(messageLen);
-                processMessage(messageType, messageLen);
-                input.digestNow();
-            }
-        }
-    }
-
-
-    /**
-     * Returns true iff the handshaker has been activated.
-     *
-     * In activated state, the handshaker may not send any messages out.
-     */
-    boolean activated() {
-        return state >= -1;
-    }
-
-    /**
-     * Returns true iff the handshaker has sent any messages.
-     */
-    boolean started() {
-        return state >= 0;  // 0: HandshakeMessage.ht_hello_request
-                            // 1: HandshakeMessage.ht_client_hello
-    }
-
-
-    /*
-     * Used to kickstart the negotiation ... either writing a
-     * ClientHello or a HelloRequest as appropriate, whichever
-     * the subclass returns.  NOP if handshaking's already started.
-     */
-    void kickstart() throws IOException {
-        if (state >= 0) {
-            return;
-        }
-
-        HandshakeMessage m = getKickstartMessage();
-
-        if (debug != null && Debug.isOn("handshake")) {
-            m.print(System.out);
-        }
-        m.write(output);
-        output.flush();
-
-        state = m.messageType();
-    }
-
-    /**
-     * Both client and server modes can start handshaking; but the
-     * message they send to do so is different.
-     */
-    abstract HandshakeMessage getKickstartMessage() throws SSLException;
-
-    /*
-     * Client and Server side protocols are each driven though this
-     * call, which processes a single message and drives the appropriate
-     * side of the protocol state machine (depending on the subclass).
-     */
-    abstract void processMessage(byte messageType, int messageLen)
-        throws IOException;
-
-    /*
-     * Most alerts in the protocol relate to handshaking problems.
-     * Alerts are detected as the connection reads data.
-     */
-    abstract void handshakeAlert(byte description) throws SSLProtocolException;
-
-    /*
-     * Sends a change cipher spec message and updates the write side
-     * cipher state so that future messages use the just-negotiated spec.
-     */
-    void sendChangeCipherSpec(Finished mesg, boolean lastMessage)
-            throws IOException {
-
-        output.flush(); // i.e. handshake data
-
-        /*
-         * The write cipher state is protected by the connection write lock
-         * so we must grab it while making the change. We also
-         * make sure no writes occur between sending the ChangeCipherSpec
-         * message, installing the new cipher state, and sending the
-         * Finished message.
-         *
-         * We already hold SSLEngine/SSLSocket "this" by virtue
-         * of this being called from the readRecord code.
-         */
-        OutputRecord r;
-        if (conn != null) {
-            r = new OutputRecord(Record.ct_change_cipher_spec);
-        } else {
-            r = new EngineOutputRecord(Record.ct_change_cipher_spec, engine);
-        }
-
-        r.setVersion(protocolVersion);
-        r.write(1);     // single byte of data
-
-        if (conn != null) {
-            conn.writeLock.lock();
-            try {
-                conn.writeRecord(r);
-                conn.changeWriteCiphers();
-                if (debug != null && Debug.isOn("handshake")) {
-                    mesg.print(System.out);
-                }
-                mesg.write(output);
-                output.flush();
-            } finally {
-                conn.writeLock.unlock();
-            }
-        } else {
-            synchronized (engine.writeLock) {
-                engine.writeRecord((EngineOutputRecord)r);
-                engine.changeWriteCiphers();
-                if (debug != null && Debug.isOn("handshake")) {
-                    mesg.print(System.out);
-                }
-                mesg.write(output);
-
-                if (lastMessage) {
-                    output.setFinishedMsg();
-                }
-                output.flush();
-            }
-        }
-    }
-
-    /*
-     * Single access point to key calculation logic.  Given the
-     * pre-master secret and the nonces from client and server,
-     * produce all the keying material to be used.
-     */
-    void calculateKeys(SecretKey preMasterSecret, ProtocolVersion version) {
-        SecretKey master = calculateMasterSecret(preMasterSecret, version);
-        session.setMasterSecret(master);
-        calculateConnectionKeys(master);
-    }
-
-
-    /*
-     * Calculate the master secret from its various components.  This is
-     * used for key exchange by all cipher suites.
-     *
-     * The master secret is the catenation of three MD5 hashes, each
-     * consisting of the pre-master secret and a SHA1 hash.  Those three
-     * SHA1 hashes are of (different) constant strings, the pre-master
-     * secret, and the nonces provided by the client and the server.
-     */
-    private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
-            ProtocolVersion requestedVersion) {
-
-        if (debug != null && Debug.isOn("keygen")) {
-            HexDumpEncoder      dump = new HexDumpEncoder();
-
-            System.out.println("SESSION KEYGEN:");
-
-            System.out.println("PreMaster Secret:");
-            printHex(dump, preMasterSecret.getEncoded());
-
-            // Nonces are dumped with connection keygen, no
-            // benefit to doing it twice
-        }
-
-        // What algs/params do we need to use?
-        String masterAlg;
-        PRF prf;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            masterAlg = "SunTls12MasterSecret";
-            prf = cipherSuite.prfAlg;
-        } else {
-            masterAlg = "SunTlsMasterSecret";
-            prf = P_NONE;
-        }
-
-        String prfHashAlg = prf.getPRFHashAlg();
-        int prfHashLength = prf.getPRFHashLength();
-        int prfBlockSize = prf.getPRFBlockSize();
-
-        TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
-                preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                clnt_random.random_bytes, svr_random.random_bytes,
-                prfHashAlg, prfHashLength, prfBlockSize);
-
-        SecretKey masterSecret;
-        try {
-            KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
-            kg.init(spec);
-            masterSecret = kg.generateKey();
-        } catch (GeneralSecurityException e) {
-            // For RSA premaster secrets, do not signal a protocol error
-            // due to the Bleichenbacher attack. See comments further down.
-            if (!preMasterSecret.getAlgorithm().equals(
-                    "TlsRsaPremasterSecret")) {
-                throw new ProviderException(e);
-            }
-
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("RSA master secret generation error:");
-                e.printStackTrace(System.out);
-            }
-
-            if (requestedVersion != null) {
-                preMasterSecret =
-                    RSAClientKeyExchange.generateDummySecret(requestedVersion);
-            } else {
-                preMasterSecret =
-                    RSAClientKeyExchange.generateDummySecret(protocolVersion);
-            }
-
-            // recursive call with new premaster secret
-            return calculateMasterSecret(preMasterSecret, null);
-        }
-
-        // if no version check requested (client side handshake), or version
-        // information is not available (not an RSA premaster secret),
-        // return master secret immediately.
-        if ((requestedVersion == null) ||
-                !(masterSecret instanceof TlsMasterSecret)) {
-            return masterSecret;
-        }
-
-        // we have checked the ClientKeyExchange message when reading TLS
-        // record, the following check is necessary to ensure that
-        // JCE provider does not ignore the checking, or the previous
-        // checking process bypassed the premaster secret version checking.
-        TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
-        int major = tlsKey.getMajorVersion();
-        int minor = tlsKey.getMinorVersion();
-        if ((major < 0) || (minor < 0)) {
-            return masterSecret;
-        }
-
-        // check if the premaster secret version is ok
-        // the specification says that it must be the maximum version supported
-        // by the client from its ClientHello message. However, many
-        // implementations send the negotiated version, so accept both
-        // for SSL v3.0 and TLS v1.0.
-        // NOTE that we may be comparing two unsupported version numbers, which
-        // is why we cannot use object reference equality in this special case.
-        ProtocolVersion premasterVersion =
-                                    ProtocolVersion.valueOf(major, minor);
-        boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
-
-        /*
-         * we never checked the client_version in server side
-         * for TLS v1.0 and SSL v3.0. For compatibility, we
-         * maintain this behavior.
-         */
-        if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
-            versionMismatch = (premasterVersion.v != protocolVersion.v);
-        }
-
-        if (versionMismatch == false) {
-            // check passed, return key
-            return masterSecret;
-        }
-
-        // Due to the Bleichenbacher attack, do not signal a protocol error.
-        // Generate a random premaster secret and continue with the handshake,
-        // which will fail when verifying the finished messages.
-        // For more information, see comments in PreMasterSecret.
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("RSA PreMasterSecret version error: expected"
-                + protocolVersion + " or " + requestedVersion + ", decrypted: "
-                + premasterVersion);
-        }
-        preMasterSecret =
-            RSAClientKeyExchange.generateDummySecret(requestedVersion);
-
-        // recursive call with new premaster secret
-        return calculateMasterSecret(preMasterSecret, null);
-    }
-
-    /*
-     * Calculate the keys needed for this connection, once the session's
-     * master secret has been calculated.  Uses the master key and nonces;
-     * the amount of keying material generated is a function of the cipher
-     * suite that's been negotiated.
-     *
-     * This gets called both on the "full handshake" (where we exchanged
-     * a premaster secret and started a new session) as well as on the
-     * "fast handshake" (where we just resumed a pre-existing session).
-     */
-    void calculateConnectionKeys(SecretKey masterKey) {
-        /*
-         * For both the read and write sides of the protocol, we use the
-         * master to generate MAC secrets and cipher keying material.  Block
-         * ciphers need initialization vectors, which we also generate.
-         *
-         * First we figure out how much keying material is needed.
-         */
-        int hashSize = cipherSuite.macAlg.size;
-        boolean is_exportable = cipherSuite.exportable;
-        BulkCipher cipher = cipherSuite.cipher;
-        int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
-
-        // Which algs/params do we need to use?
-        String keyMaterialAlg;
-        PRF prf;
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            keyMaterialAlg = "SunTls12KeyMaterial";
-            prf = cipherSuite.prfAlg;
-        } else {
-            keyMaterialAlg = "SunTlsKeyMaterial";
-            prf = P_NONE;
-        }
-
-        String prfHashAlg = prf.getPRFHashAlg();
-        int prfHashLength = prf.getPRFHashLength();
-        int prfBlockSize = prf.getPRFBlockSize();
-
-        TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
-            masterKey, protocolVersion.major, protocolVersion.minor,
-            clnt_random.random_bytes, svr_random.random_bytes,
-            cipher.algorithm, cipher.keySize, expandedKeySize,
-            cipher.ivSize, hashSize,
-            prfHashAlg, prfHashLength, prfBlockSize);
-
-        try {
-            KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
-            kg.init(spec);
-            TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
-
-            clntWriteKey = keySpec.getClientCipherKey();
-            svrWriteKey = keySpec.getServerCipherKey();
-
-            // Return null if IVs are not supposed to be generated.
-            // e.g. TLS 1.1+.
-            clntWriteIV = keySpec.getClientIv();
-            svrWriteIV = keySpec.getServerIv();
-
-            clntMacSecret = keySpec.getClientMacKey();
-            svrMacSecret = keySpec.getServerMacKey();
-        } catch (GeneralSecurityException e) {
-            throw new ProviderException(e);
-        }
-
-        //
-        // Dump the connection keys as they're generated.
-        //
-        if (debug != null && Debug.isOn("keygen")) {
-            synchronized (System.out) {
-                HexDumpEncoder  dump = new HexDumpEncoder();
-
-                System.out.println("CONNECTION KEYGEN:");
-
-                // Inputs:
-                System.out.println("Client Nonce:");
-                printHex(dump, clnt_random.random_bytes);
-                System.out.println("Server Nonce:");
-                printHex(dump, svr_random.random_bytes);
-                System.out.println("Master Secret:");
-                printHex(dump, masterKey.getEncoded());
-
-                // Outputs:
-                System.out.println("Client MAC write Secret:");
-                printHex(dump, clntMacSecret.getEncoded());
-                System.out.println("Server MAC write Secret:");
-                printHex(dump, svrMacSecret.getEncoded());
-
-                if (clntWriteKey != null) {
-                    System.out.println("Client write key:");
-                    printHex(dump, clntWriteKey.getEncoded());
-                    System.out.println("Server write key:");
-                    printHex(dump, svrWriteKey.getEncoded());
-                } else {
-                    System.out.println("... no encryption keys used");
-                }
-
-                if (clntWriteIV != null) {
-                    System.out.println("Client write IV:");
-                    printHex(dump, clntWriteIV.getIV());
-                    System.out.println("Server write IV:");
-                    printHex(dump, svrWriteIV.getIV());
-                } else {
-                    if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                        System.out.println(
-                                "... no IV derived for this protocol");
-                    } else {
-                        System.out.println("... no IV used for this cipher");
-                    }
-                }
-                System.out.flush();
-            }
-        }
-    }
-
-    private static void printHex(HexDumpEncoder dump, byte[] bytes) {
-        if (bytes == null) {
-            System.out.println("(key bytes not available)");
-        } else {
-            try {
-                dump.encodeBuffer(bytes, System.out);
-            } catch (IOException e) {
-                // just for debugging, ignore this
-            }
-        }
-    }
-
-    /**
-     * Throw an SSLException with the specified message and cause.
-     * Shorthand until a new SSLException constructor is added.
-     * This method never returns.
-     */
-    static void throwSSLException(String msg, Throwable cause)
-            throws SSLException {
-        SSLException e = new SSLException(msg);
-        e.initCause(cause);
-        throw e;
-    }
-
-
-    /*
-     * Implement a simple task delegator.
-     *
-     * We are currently implementing this as a single delegator, may
-     * try for parallel tasks later.  Client Authentication could
-     * benefit from this, where ClientKeyExchange/CertificateVerify
-     * could be carried out in parallel.
-     */
-    class DelegatedTask<E> implements Runnable {
-
-        private PrivilegedExceptionAction<E> pea;
-
-        DelegatedTask(PrivilegedExceptionAction<E> pea) {
-            this.pea = pea;
-        }
-
-        public void run() {
-            synchronized (engine) {
-                try {
-                    AccessController.doPrivileged(pea, engine.getAcc());
-                } catch (PrivilegedActionException pae) {
-                    thrown = pae.getException();
-                } catch (RuntimeException rte) {
-                    thrown = rte;
-                }
-                delegatedTask = null;
-                taskDelegated = false;
-            }
-        }
-    }
-
-    private <T> void delegateTask(PrivilegedExceptionAction<T> pea) {
-        delegatedTask = new DelegatedTask<T>(pea);
-        taskDelegated = false;
-        thrown = null;
-    }
-
-    DelegatedTask getTask() {
-        if (!taskDelegated) {
-            taskDelegated = true;
-            return delegatedTask;
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * See if there are any tasks which need to be delegated
-     *
-     * Locked by SSLEngine.this.
-     */
-    boolean taskOutstanding() {
-        return (delegatedTask != null);
-    }
-
-    /*
-     * The previous caller failed for some reason, report back the
-     * Exception.  We won't worry about Error's.
-     *
-     * Locked by SSLEngine.this.
-     */
-    void checkThrown() throws SSLException {
-        synchronized (thrownLock) {
-            if (thrown != null) {
-
-                String msg = thrown.getMessage();
-
-                if (msg == null) {
-                    msg = "Delegated task threw Exception/Error";
-                }
-
-                /*
-                 * See what the underlying type of exception is.  We should
-                 * throw the same thing.  Chain thrown to the new exception.
-                 */
-                Exception e = thrown;
-                thrown = null;
-
-                if (e instanceof RuntimeException) {
-                    throw (RuntimeException)
-                        new RuntimeException(msg).initCause(e);
-                } else if (e instanceof SSLHandshakeException) {
-                    throw (SSLHandshakeException)
-                        new SSLHandshakeException(msg).initCause(e);
-                } else if (e instanceof SSLKeyException) {
-                    throw (SSLKeyException)
-                        new SSLKeyException(msg).initCause(e);
-                } else if (e instanceof SSLPeerUnverifiedException) {
-                    throw (SSLPeerUnverifiedException)
-                        new SSLPeerUnverifiedException(msg).initCause(e);
-                } else if (e instanceof SSLProtocolException) {
-                    throw (SSLProtocolException)
-                        new SSLProtocolException(msg).initCause(e);
-                } else {
-                    /*
-                     * If it's SSLException or any other Exception,
-                     * we'll wrap it in an SSLException.
-                     */
-                    throw (SSLException)
-                        new SSLException(msg).initCause(e);
-                }
-            }
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java b/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java
deleted file mode 100755
index 9db6927..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * Copyright (c) 2006, 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.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.*;
-
-import java.security.spec.ECParameterSpec;
-
-import javax.net.ssl.SSLProtocolException;
-
-/**
- * This file contains all the classes relevant to TLS Extensions for the
- * ClientHello and ServerHello messages. The extension mechanism and
- * several extensions are defined in RFC 3546. Additional extensions are
- * defined in the ECC RFC 4492.
- *
- * Currently, only the two ECC extensions are fully supported.
- *
- * The classes contained in this file are:
- *  . HelloExtensions: a List of extensions as used in the client hello
- *      and server hello messages.
- *  . ExtensionType: an enum style class for the extension type
- *  . HelloExtension: abstract base class for all extensions. All subclasses
- *      must be immutable.
- *
- *  . UnknownExtension: used to represent all parsed extensions that we do not
- *      explicitly support.
- *  . ServerNameExtension: the server_name extension.
- *  . SignatureAlgorithmsExtension: the signature_algorithms extension.
- *  . SupportedEllipticCurvesExtension: the ECC supported curves extension.
- *  . SupportedEllipticPointFormatsExtension: the ECC supported point formats
- *      (compressed/uncompressed) extension.
- *
- * @since   1.6
- * @author  Andreas Sterbenz
- */
-final class HelloExtensions {
-
-    private List<HelloExtension> extensions;
-    private int encodedLength;
-
-    HelloExtensions() {
-        extensions = Collections.emptyList();
-    }
-
-    HelloExtensions(HandshakeInStream s) throws IOException {
-        int len = s.getInt16();
-        extensions = new ArrayList<HelloExtension>();
-        encodedLength = len + 2;
-        while (len > 0) {
-            int type = s.getInt16();
-            int extlen = s.getInt16();
-            ExtensionType extType = ExtensionType.get(type);
-            HelloExtension extension;
-            if (extType == ExtensionType.EXT_SERVER_NAME) {
-                extension = new ServerNameExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
-                extension = new SignatureAlgorithmsExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
-                extension = new SupportedEllipticCurvesExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
-                extension =
-                        new SupportedEllipticPointFormatsExtension(s, extlen);
-            } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
-                extension = new RenegotiationInfoExtension(s, extlen);
-            } else {
-                extension = new UnknownExtension(s, extlen, extType);
-            }
-            extensions.add(extension);
-            len -= extlen + 4;
-        }
-        if (len != 0) {
-            throw new SSLProtocolException(
-                        "Error parsing extensions: extra data");
-        }
-    }
-
-    // Return the List of extensions. Must not be modified by the caller.
-    List<HelloExtension> list() {
-        return extensions;
-    }
-
-    void add(HelloExtension ext) {
-        if (extensions.isEmpty()) {
-            extensions = new ArrayList<HelloExtension>();
-        }
-        extensions.add(ext);
-        encodedLength = -1;
-    }
-
-    HelloExtension get(ExtensionType type) {
-        for (HelloExtension ext : extensions) {
-            if (ext.type == type) {
-                return ext;
-            }
-        }
-        return null;
-    }
-
-    int length() {
-        if (encodedLength >= 0) {
-            return encodedLength;
-        }
-        if (extensions.isEmpty()) {
-            encodedLength = 0;
-        } else {
-            encodedLength = 2;
-            for (HelloExtension ext : extensions) {
-                encodedLength += ext.length();
-            }
-        }
-        return encodedLength;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        int length = length();
-        if (length == 0) {
-            return;
-        }
-        s.putInt16(length - 2);
-        for (HelloExtension ext : extensions) {
-            ext.send(s);
-        }
-    }
-
-    void print(PrintStream s) throws IOException {
-        for (HelloExtension ext : extensions) {
-            s.println(ext.toString());
-        }
-    }
-}
-
-final class ExtensionType {
-
-    final int id;
-    final String name;
-
-    private ExtensionType(int id, String name) {
-        this.id = id;
-        this.name = name;
-    }
-
-    public String toString() {
-        return name;
-    }
-
-    static List<ExtensionType> knownExtensions = new ArrayList<>(9);
-
-    static ExtensionType get(int id) {
-        for (ExtensionType ext : knownExtensions) {
-            if (ext.id == id) {
-                return ext;
-            }
-        }
-        return new ExtensionType(id, "type_" + id);
-    }
-
-    private static ExtensionType e(int id, String name) {
-        ExtensionType ext = new ExtensionType(id, name);
-        knownExtensions.add(ext);
-        return ext;
-    }
-
-    // extensions defined in RFC 3546
-    final static ExtensionType EXT_SERVER_NAME =
-            e(0x0000, "server_name");            // IANA registry value: 0
-    final static ExtensionType EXT_MAX_FRAGMENT_LENGTH =
-            e(0x0001, "max_fragment_length");    // IANA registry value: 1
-    final static ExtensionType EXT_CLIENT_CERTIFICATE_URL =
-            e(0x0002, "client_certificate_url"); // IANA registry value: 2
-    final static ExtensionType EXT_TRUSTED_CA_KEYS =
-            e(0x0003, "trusted_ca_keys");        // IANA registry value: 3
-    final static ExtensionType EXT_TRUNCATED_HMAC =
-            e(0x0004, "truncated_hmac");         // IANA registry value: 4
-    final static ExtensionType EXT_STATUS_REQUEST =
-            e(0x0005, "status_request");         // IANA registry value: 5
-
-    // extensions defined in RFC 4681
-    final static ExtensionType EXT_USER_MAPPING =
-            e(0x0006, "user_mapping");           // IANA registry value: 6
-
-    // extensions defined in RFC 5081
-    final static ExtensionType EXT_CERT_TYPE =
-            e(0x0009, "cert_type");              // IANA registry value: 9
-
-    // extensions defined in RFC 4492 (ECC)
-    final static ExtensionType EXT_ELLIPTIC_CURVES =
-            e(0x000A, "elliptic_curves");        // IANA registry value: 10
-    final static ExtensionType EXT_EC_POINT_FORMATS =
-            e(0x000B, "ec_point_formats");       // IANA registry value: 11
-
-    // extensions defined in RFC 5054
-    final static ExtensionType EXT_SRP =
-            e(0x000C, "srp");                    // IANA registry value: 12
-
-    // extensions defined in RFC 5246
-    final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
-            e(0x000D, "signature_algorithms");   // IANA registry value: 13
-
-    // extensions defined in RFC 5746
-    final static ExtensionType EXT_RENEGOTIATION_INFO =
-            e(0xff01, "renegotiation_info");     // IANA registry value: 65281
-}
-
-abstract class HelloExtension {
-
-    final ExtensionType type;
-
-    HelloExtension(ExtensionType type) {
-        this.type = type;
-    }
-
-    // Length of the encoded extension, including the type and length fields
-    abstract int length();
-
-    abstract void send(HandshakeOutStream s) throws IOException;
-
-    public abstract String toString();
-
-}
-
-final class UnknownExtension extends HelloExtension {
-
-    private final byte[] data;
-
-    UnknownExtension(HandshakeInStream s, int len, ExtensionType type)
-            throws IOException {
-        super(type);
-        data = new byte[len];
-        // s.read() does not handle 0-length arrays.
-        if (len != 0) {
-            s.read(data);
-        }
-    }
-
-    int length() {
-        return 4 + data.length;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putBytes16(data);
-    }
-
-    public String toString() {
-        return "Unsupported extension " + type + ", data: " +
-            Debug.toString(data);
-    }
-}
-
-/*
- * [RFC4366] To facilitate secure connections to servers that host multiple
- * 'virtual' servers at a single underlying network address, clients MAY
- * include an extension of type "server_name" in the (extended) client hello.
- * The "extension_data" field of this extension SHALL contain "ServerNameList"
- * where:
- *
- *     struct {
- *         NameType name_type;
- *         select (name_type) {
- *             case host_name: HostName;
- *         } name;
- *     } ServerName;
- *
- *     enum {
- *         host_name(0), (255)
- *     } NameType;
- *
- *     opaque HostName<1..2^16-1>;
- *
- *     struct {
- *         ServerName server_name_list<1..2^16-1>
- *     } ServerNameList;
- */
-final class ServerNameExtension extends HelloExtension {
-
-    final static int NAME_HOST_NAME = 0;
-
-    private List<ServerName> names;
-    private int listLength;     // ServerNameList length
-
-    ServerNameExtension(List<String> hostnames) throws IOException {
-        super(ExtensionType.EXT_SERVER_NAME);
-
-        listLength = 0;
-        names = new ArrayList<ServerName>(hostnames.size());
-        for (String hostname : hostnames) {
-            if (hostname != null && hostname.length() != 0) {
-                // we only support DNS hostname now.
-                ServerName serverName =
-                        new ServerName(NAME_HOST_NAME, hostname);
-                names.add(serverName);
-                listLength += serverName.length;
-            }
-        }
-
-        // As we only support DNS hostname now, the hostname list must
-        // not contain more than one hostname
-        if (names.size() > 1) {
-            throw new SSLProtocolException(
-                    "The ServerNameList MUST NOT contain more than " +
-                    "one name of the same name_type");
-        }
-
-        // We only need to add "server_name" extension in ClientHello unless
-        // we support SNI in server side in the future. It is possible that
-        // the SNI is empty in ServerHello. As we don't support SNI in
-        // ServerHello now, we will throw exception for empty list for now.
-        if (listLength == 0) {
-            throw new SSLProtocolException(
-                    "The ServerNameList cannot be empty");
-        }
-    }
-
-    ServerNameExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_SERVER_NAME);
-
-        int remains = len;
-        if (len >= 2) {    // "server_name" extension in ClientHello
-            listLength = s.getInt16();     // ServerNameList length
-            if (listLength == 0 || listLength + 2 != len) {
-                throw new SSLProtocolException(
-                        "Invalid " + type + " extension");
-            }
-
-            remains -= 2;
-            names = new ArrayList<ServerName>();
-            while (remains > 0) {
-                ServerName name = new ServerName(s);
-                names.add(name);
-                remains -= name.length;
-
-                // we may need to check the duplicated ServerName type
-            }
-        } else if (len == 0) {     // "server_name" extension in ServerHello
-            listLength = 0;
-            names = Collections.<ServerName>emptyList();
-        }
-
-        if (remains != 0) {
-            throw new SSLProtocolException("Invalid server_name extension");
-        }
-    }
-
-    static class ServerName {
-        final int length;
-        final int type;
-        final byte[] data;
-        final String hostname;
-
-        ServerName(int type, String hostname) throws IOException {
-            this.type = type;                       // NameType
-            this.hostname = hostname;
-            this.data = hostname.getBytes("UTF8");  // HostName
-            this.length = data.length + 3;          // NameType: 1 byte
-                                                    // HostName length: 2 bytes
-        }
-
-        ServerName(HandshakeInStream s) throws IOException {
-            type = s.getInt8();         // NameType
-            data = s.getBytes16();      // HostName (length read in getBytes16)
-            length = data.length + 3;   // NameType: 1 byte
-                                        // HostName length: 2 bytes
-            if (type == NAME_HOST_NAME) {
-                hostname = new String(data, "UTF8");
-            } else {
-                hostname = null;
-            }
-        }
-
-        public String toString() {
-            if (type == NAME_HOST_NAME) {
-                return "host_name: " + hostname;
-            } else {
-                return "unknown-" + type + ": " + Debug.toString(data);
-            }
-        }
-    }
-
-    int length() {
-        return listLength == 0 ? 4 : 6 + listLength;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(listLength + 2);
-        if (listLength != 0) {
-            s.putInt16(listLength);
-
-            for (ServerName name : names) {
-                s.putInt8(name.type);           // NameType
-                s.putBytes16(name.data);        // HostName
-            }
-        }
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        for (ServerName name : names) {
-            buffer.append("[" + name + "]");
-        }
-
-        return "Extension " + type + ", server_name: " + buffer;
-    }
-}
-
-final class SupportedEllipticCurvesExtension extends HelloExtension {
-
-    // the extension value to send in the ClientHello message
-    static final SupportedEllipticCurvesExtension DEFAULT;
-
-    private static final boolean fips;
-
-    static {
-        int[] ids;
-        fips = SunJSSE.isFIPS();
-        if (fips == false) {
-            ids = new int[] {
-                // NIST curves first
-                // prefer NIST P-256, rest in order of increasing key length
-                23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
-                // non-NIST curves
-                15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
-            };
-        } else {
-            ids = new int[] {
-                // same as above, but allow only NIST curves in FIPS mode
-                23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
-            };
-        }
-        DEFAULT = new SupportedEllipticCurvesExtension(ids);
-    }
-
-    private final int[] curveIds;
-
-    private SupportedEllipticCurvesExtension(int[] curveIds) {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-        this.curveIds = curveIds;
-    }
-
-    SupportedEllipticCurvesExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_ELLIPTIC_CURVES);
-        int k = s.getInt16();
-        if (((len & 1) != 0) || (k + 2 != len)) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-        curveIds = new int[k >> 1];
-        for (int i = 0; i < curveIds.length; i++) {
-            curveIds[i] = s.getInt16();
-        }
-    }
-
-    boolean contains(int index) {
-        for (int curveId : curveIds) {
-            if (index == curveId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Return a reference to the internal curveIds array.
-    // The caller must NOT modify the contents.
-    int[] curveIds() {
-        return curveIds;
-    }
-
-    int length() {
-        return 6 + (curveIds.length << 1);
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        int k = curveIds.length << 1;
-        s.putInt16(k + 2);
-        s.putInt16(k);
-        for (int curveId : curveIds) {
-            s.putInt16(curveId);
-        }
-    }
-
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Extension " + type + ", curve names: {");
-        boolean first = true;
-        for (int curveId : curveIds) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(", ");
-            }
-            // first check if it is a known named curve, then try other cases.
-            String oid = getCurveOid(curveId);
-            if (oid != null) {
-                ECParameterSpec spec = JsseJce.getECParameterSpec(oid);
-                // this toString() output will look nice for the current
-                // implementation of the ECParameterSpec class in the Sun
-                // provider, but may not look good for other implementations.
-                if (spec != null) {
-                    sb.append(spec.toString().split(" ")[0]);
-                } else {
-                    sb.append(oid);
-                }
-            } else if (curveId == ARBITRARY_PRIME) {
-                sb.append("arbitrary_explicit_prime_curves");
-            } else if (curveId == ARBITRARY_CHAR2) {
-                sb.append("arbitrary_explicit_char2_curves");
-            } else {
-                sb.append("unknown curve " + curveId);
-            }
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-
-    // Test whether we support the curve with the given index.
-    static boolean isSupported(int index) {
-        if ((index <= 0) || (index >= NAMED_CURVE_OID_TABLE.length)) {
-            return false;
-        }
-        if (fips == false) {
-            // in non-FIPS mode, we support all valid indices
-            return true;
-        }
-        return DEFAULT.contains(index);
-    }
-
-    static int getCurveIndex(ECParameterSpec params) {
-        String oid = JsseJce.getNamedCurveOid(params);
-        if (oid == null) {
-            return -1;
-        }
-        Integer n = curveIndices.get(oid);
-        return (n == null) ? -1 : n;
-    }
-
-    static String getCurveOid(int index) {
-        if ((index > 0) && (index < NAMED_CURVE_OID_TABLE.length)) {
-            return NAMED_CURVE_OID_TABLE[index];
-        }
-        return null;
-    }
-
-    private final static int ARBITRARY_PRIME = 0xff01;
-    private final static int ARBITRARY_CHAR2 = 0xff02;
-
-    // See sun.security.ec.NamedCurve for the OIDs
-    private final static String[] NAMED_CURVE_OID_TABLE = new String[] {
-        null,                   //  (0) unused
-        "1.3.132.0.1",          //  (1) sect163k1, NIST K-163
-        "1.3.132.0.2",          //  (2) sect163r1
-        "1.3.132.0.15",         //  (3) sect163r2, NIST B-163
-        "1.3.132.0.24",         //  (4) sect193r1
-        "1.3.132.0.25",         //  (5) sect193r2
-        "1.3.132.0.26",         //  (6) sect233k1, NIST K-233
-        "1.3.132.0.27",         //  (7) sect233r1, NIST B-233
-        "1.3.132.0.3",          //  (8) sect239k1
-        "1.3.132.0.16",         //  (9) sect283k1, NIST K-283
-        "1.3.132.0.17",         // (10) sect283r1, NIST B-283
-        "1.3.132.0.36",         // (11) sect409k1, NIST K-409
-        "1.3.132.0.37",         // (12) sect409r1, NIST B-409
-        "1.3.132.0.38",         // (13) sect571k1, NIST K-571
-        "1.3.132.0.39",         // (14) sect571r1, NIST B-571
-        "1.3.132.0.9",          // (15) secp160k1
-        "1.3.132.0.8",          // (16) secp160r1
-        "1.3.132.0.30",         // (17) secp160r2
-        "1.3.132.0.31",         // (18) secp192k1
-        "1.2.840.10045.3.1.1",  // (19) secp192r1, NIST P-192
-        "1.3.132.0.32",         // (20) secp224k1
-        "1.3.132.0.33",         // (21) secp224r1, NIST P-224
-        "1.3.132.0.10",         // (22) secp256k1
-        "1.2.840.10045.3.1.7",  // (23) secp256r1, NIST P-256
-        "1.3.132.0.34",         // (24) secp384r1, NIST P-384
-        "1.3.132.0.35",         // (25) secp521r1, NIST P-521
-    };
-
-    private final static Map<String,Integer> curveIndices;
-
-    static {
-        curveIndices = new HashMap<String,Integer>();
-        for (int i = 1; i < NAMED_CURVE_OID_TABLE.length; i++) {
-            curveIndices.put(NAMED_CURVE_OID_TABLE[i], i);
-        }
-    }
-
-}
-
-final class SupportedEllipticPointFormatsExtension extends HelloExtension {
-
-    final static int FMT_UNCOMPRESSED = 0;
-    final static int FMT_ANSIX962_COMPRESSED_PRIME = 1;
-    final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
-
-    static final HelloExtension DEFAULT =
-        new SupportedEllipticPointFormatsExtension(
-            new byte[] {FMT_UNCOMPRESSED});
-
-    private final byte[] formats;
-
-    private SupportedEllipticPointFormatsExtension(byte[] formats) {
-        super(ExtensionType.EXT_EC_POINT_FORMATS);
-        this.formats = formats;
-    }
-
-    SupportedEllipticPointFormatsExtension(HandshakeInStream s, int len)
-            throws IOException {
-        super(ExtensionType.EXT_EC_POINT_FORMATS);
-        formats = s.getBytes8();
-        // RFC 4492 says uncompressed points must always be supported.
-        // Check just to make sure.
-        boolean uncompressed = false;
-        for (int format : formats) {
-            if (format == FMT_UNCOMPRESSED) {
-                uncompressed = true;
-                break;
-            }
-        }
-        if (uncompressed == false) {
-            throw new SSLProtocolException
-                ("Peer does not support uncompressed points");
-        }
-    }
-
-    int length() {
-        return 5 + formats.length;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(formats.length + 1);
-        s.putBytes8(formats);
-    }
-
-    private static String toString(byte format) {
-        int f = format & 0xff;
-        switch (f) {
-        case FMT_UNCOMPRESSED:
-            return "uncompressed";
-        case FMT_ANSIX962_COMPRESSED_PRIME:
-            return "ansiX962_compressed_prime";
-        case FMT_ANSIX962_COMPRESSED_CHAR2:
-            return "ansiX962_compressed_char2";
-        default:
-            return "unknown-" + f;
-        }
-    }
-
-    public String toString() {
-        List<String> list = new ArrayList<>();
-        for (byte format : formats) {
-            list.add(toString(format));
-        }
-        return "Extension " + type + ", formats: " + list;
-    }
-}
-
-/*
- * For secure renegotiation, RFC5746 defines a new TLS extension,
- * "renegotiation_info" (with extension type 0xff01), which contains a
- * cryptographic binding to the enclosing TLS connection (if any) for
- * which the renegotiation is being performed.  The "extension data"
- * field of this extension contains a "RenegotiationInfo" structure:
- *
- *      struct {
- *          opaque renegotiated_connection<0..255>;
- *      } RenegotiationInfo;
- */
-final class RenegotiationInfoExtension extends HelloExtension {
-    private final byte[] renegotiated_connection;
-
-    RenegotiationInfoExtension(byte[] clientVerifyData,
-                byte[] serverVerifyData) {
-        super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
-        if (clientVerifyData.length != 0) {
-            renegotiated_connection =
-                    new byte[clientVerifyData.length + serverVerifyData.length];
-            System.arraycopy(clientVerifyData, 0, renegotiated_connection,
-                    0, clientVerifyData.length);
-
-            if (serverVerifyData.length != 0) {
-                System.arraycopy(serverVerifyData, 0, renegotiated_connection,
-                        clientVerifyData.length, serverVerifyData.length);
-            }
-        } else {
-            // ignore both the client and server verify data.
-            renegotiated_connection = new byte[0];
-        }
-    }
-
-    RenegotiationInfoExtension(HandshakeInStream s, int len)
-                throws IOException {
-        super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
-        // check the extension length
-        if (len < 1) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        int renegoInfoDataLen = s.getInt8();
-        if (renegoInfoDataLen + 1 != len) {  // + 1 = the byte we just read
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        renegotiated_connection = new byte[renegoInfoDataLen];
-        if (renegoInfoDataLen != 0) {
-            s.read(renegotiated_connection, 0, renegoInfoDataLen);
-        }
-    }
-
-
-    // Length of the encoded extension, including the type and length fields
-    int length() {
-        return 5 + renegotiated_connection.length;
-    }
-
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(renegotiated_connection.length + 1);
-        s.putBytes8(renegotiated_connection);
-    }
-
-    boolean isEmpty() {
-        return renegotiated_connection.length == 0;
-    }
-
-    byte[] getRenegotiatedConnection() {
-        return renegotiated_connection;
-    }
-
-    public String toString() {
-        return "Extension " + type + ", renegotiated_connection: " +
-                    (renegotiated_connection.length == 0 ? "<empty>" :
-                    Debug.toString(renegotiated_connection));
-    }
-
-}
-
-/*
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures.  The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- *     enum {
- *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *         sha512(6), (255)
- *     } HashAlgorithm;
- *
- *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *       SignatureAlgorithm;
- *
- *     struct {
- *           HashAlgorithm hash;
- *           SignatureAlgorithm signature;
- *     } SignatureAndHashAlgorithm;
- *
- *     SignatureAndHashAlgorithm
- *       supported_signature_algorithms<2..2^16-2>;
- */
-final class SignatureAlgorithmsExtension extends HelloExtension {
-
-    private Collection<SignatureAndHashAlgorithm> algorithms;
-    private int algorithmsLen;  // length of supported_signature_algorithms
-
-    SignatureAlgorithmsExtension(
-            Collection<SignatureAndHashAlgorithm> signAlgs) {
-
-        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
-        algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
-        algorithmsLen =
-            SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
-    }
-
-    SignatureAlgorithmsExtension(HandshakeInStream s, int len)
-                throws IOException {
-        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
-        algorithmsLen = s.getInt16();
-        if (algorithmsLen == 0 || algorithmsLen + 2 != len) {
-            throw new SSLProtocolException("Invalid " + type + " extension");
-        }
-
-        algorithms = new ArrayList<SignatureAndHashAlgorithm>();
-        int remains = algorithmsLen;
-        int sequence = 0;
-        while (remains > 1) {   // needs at least two bytes
-            int hash = s.getInt8();         // hash algorithm
-            int signature = s.getInt8();    // signature algorithm
-
-            SignatureAndHashAlgorithm algorithm =
-                SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence);
-            algorithms.add(algorithm);
-            remains -= 2;  // one byte for hash, one byte for signature
-        }
-
-        if (remains != 0) {
-            throw new SSLProtocolException("Invalid server_name extension");
-        }
-    }
-
-    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
-        return algorithms;
-    }
-
-    @Override
-    int length() {
-        return 6 + algorithmsLen;
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        s.putInt16(type.id);
-        s.putInt16(algorithmsLen + 2);
-        s.putInt16(algorithmsLen);
-
-        for (SignatureAndHashAlgorithm algorithm : algorithms) {
-            s.putInt8(algorithm.getHashValue());      // HashAlgorithm
-            s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        boolean opened = false;
-        for (SignatureAndHashAlgorithm signAlg : algorithms) {
-            if (opened) {
-                buffer.append(", " + signAlg.getAlgorithmName());
-            } else {
-                buffer.append(signAlg.getAlgorithmName());
-                opened = true;
-            }
-        }
-
-        return "Extension " + type + ", signature_algorithms: " + buffer;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/InputRecord.java b/ojluni/src/main/java/sun/security/ssl/InputRecord.java
deleted file mode 100755
index f714488..0000000
--- a/ojluni/src/main/java/sun/security/ssl/InputRecord.java
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as pulled off a TCP stream.  Input records are
- * basically buffers tied to a particular input stream ... a layer
- * above this must map these records into the model of a continuous
- * stream of data.
- *
- * Since this returns SSL 3.0 records, it's the layer that needs to
- * map SSL 2.0 style handshake records into SSL 3.0 ones for those
- * "old" clients that interop with both V2 and V3 servers.  Not as
- * pretty as might be desired.
- *
- * NOTE:  During handshaking, each message must be hashed to support
- * verification that the handshake process wasn't compromised.
- *
- * @author David Brownell
- */
-class InputRecord extends ByteArrayInputStream implements Record {
-
-    private HandshakeHash       handshakeHash;
-    private int                 lastHashed;
-    boolean                     formatVerified = true;  // SSLv2 ruled out?
-    private boolean             isClosed;
-    private boolean             appDataValid;
-
-    // The ClientHello version to accept. If set to ProtocolVersion.SSL20Hello
-    // and the first message we read is a ClientHello in V2 format, we convert
-    // it to V3. Otherwise we throw an exception when encountering a V2 hello.
-    private ProtocolVersion     helloVersion;
-
-    /* Class and subclass dynamic debugging support */
-    static final Debug debug = Debug.getInstance("ssl");
-
-    /* The existing record length */
-    private int exlen;
-
-    /* V2 handshake message */
-    private byte v2Buf[];
-
-    /*
-     * Construct the record to hold the maximum sized input record.
-     * Data will be filled in separately.
-     */
-    InputRecord() {
-        super(new byte[maxRecordSize]);
-        setHelloVersion(ProtocolVersion.DEFAULT_HELLO);
-        pos = headerSize;
-        count = headerSize;
-        lastHashed = count;
-        exlen = 0;
-        v2Buf = null;
-    }
-
-    void setHelloVersion(ProtocolVersion helloVersion) {
-        this.helloVersion = helloVersion;
-    }
-
-    ProtocolVersion getHelloVersion() {
-        return helloVersion;
-    }
-
-    /*
-     * Enable format checks if initial handshaking hasn't completed
-     */
-    void enableFormatChecks() {
-        formatVerified = false;
-    }
-
-    // return whether the data in this record is valid, decrypted data
-    boolean isAppDataValid() {
-        return appDataValid;
-    }
-
-    void setAppDataValid(boolean value) {
-        appDataValid = value;
-    }
-
-    /*
-     * Return the content type of the record.
-     */
-    byte contentType() {
-        return buf[0];
-    }
-
-    /*
-     * For handshaking, we need to be able to hash every byte above the
-     * record marking layer.  This is where we're guaranteed to see those
-     * bytes, so this is where we can hash them ... especially in the
-     * case of hashing the initial V2 message!
-     */
-    void setHandshakeHash(HandshakeHash handshakeHash) {
-        this.handshakeHash = handshakeHash;
-    }
-
-    HandshakeHash getHandshakeHash() {
-        return handshakeHash;
-    }
-
-    void decrypt(MAC signer, CipherBox box) throws BadPaddingException {
-
-        BadPaddingException reservedBPE = null;
-        int tagLen = signer.MAClen();
-        int cipheredLength = count - headerSize;
-
-        if (!box.isNullCipher()) {
-            // sanity check length of the ciphertext
-            if (!box.sanityCheck(tagLen, cipheredLength)) {
-                throw new BadPaddingException(
-                    "ciphertext sanity check failed");
-            }
-
-            try {
-                // Note that the CipherBox.decrypt() does not change
-                // the capacity of the buffer.
-                count = headerSize +
-                        box.decrypt(buf, headerSize, cipheredLength, tagLen);
-            } catch (BadPaddingException bpe) {
-                // RFC 2246 states that decryption_failed should be used
-                // for this purpose. However, that allows certain attacks,
-                // so we just send bad record MAC. We also need to make
-                // sure to always check the MAC to avoid a timing attack
-                // for the same issue. See paper by Vaudenay et al and the
-                // update in RFC 4346/5246.
-                //
-                // Failover to message authentication code checking.
-                reservedBPE = bpe;
-            }
-        }
-
-        if (tagLen != 0) {
-            int macOffset = count - tagLen;
-            int contentLen = macOffset - headerSize;
-
-            // Note that although it is not necessary, we run the same MAC
-            // computation and comparison on the payload for both stream
-            // cipher and CBC block cipher.
-            if (contentLen < 0) {
-                // negative data length, something is wrong
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record");
-                }
-
-                // set offset of the dummy MAC
-                macOffset = headerSize + cipheredLength - tagLen;
-                contentLen = macOffset - headerSize;
-            }
-
-            count -= tagLen;  // Set the count before any MAC checking
-                              // exception occurs, so that the following
-                              // process can read the actual decrypted
-                              // content (minus the MAC) in the fragment
-                              // if necessary.
-
-            // Run MAC computation and comparison on the payload.
-            if (checkMacTags(contentType(),
-                    buf, headerSize, contentLen, signer, false)) {
-                if (reservedBPE == null) {
-                    reservedBPE = new BadPaddingException("bad record MAC");
-                }
-            }
-
-            // Run MAC computation and comparison on the remainder.
-            //
-            // It is only necessary for CBC block cipher.  It is used to get a
-            // constant time of MAC computation and comparison on each record.
-            if (box.isCBCMode()) {
-                int remainingLen = calculateRemainingLen(
-                                        signer, cipheredLength, contentLen);
-
-                // NOTE: remainingLen may be bigger (less than 1 block of the
-                // hash algorithm of the MAC) than the cipheredLength. However,
-                // We won't need to worry about it because we always use a
-                // maximum buffer for every record.  We need a change here if
-                // we use small buffer size in the future.
-                if (remainingLen > buf.length) {
-                    // unlikely to happen, just a placehold
-                    throw new RuntimeException(
-                        "Internal buffer capacity error");
-                }
-
-                // Won't need to worry about the result on the remainder. And
-                // then we won't need to worry about what's actual data to
-                // check MAC tag on.  We start the check from the header of the
-                // buffer so that we don't need to construct a new byte buffer.
-                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
-            }
-        }
-
-        // Is it a failover?
-        if (reservedBPE != null) {
-            throw reservedBPE;
-        }
-    }
-
-    /*
-     * Run MAC computation and comparison
-     *
-     * Please DON'T change the content of the byte buffer parameter!
-     */
-    static boolean checkMacTags(byte contentType, byte[] buffer,
-            int offset, int contentLen, MAC signer, boolean isSimulated) {
-
-        int tagLen = signer.MAClen();
-        byte[] hash = signer.compute(
-                contentType, buffer, offset, contentLen, isSimulated);
-        if (hash == null || tagLen != hash.length) {
-            // Something is wrong with MAC implementation.
-            throw new RuntimeException("Internal MAC error");
-        }
-
-        int[] results = compareMacTags(buffer, offset + contentLen, hash);
-        return (results[0] != 0);
-    }
-
-    /*
-     * A constant-time comparison of the MAC tags.
-     *
-     * Please DON'T change the content of the byte buffer parameter!
-     */
-    private static int[] compareMacTags(
-            byte[] buffer, int offset, byte[] tag) {
-
-        // An array of hits is used to prevent Hotspot optimization for
-        // the purpose of a constant-time check.
-        int[] results = {0, 0};    // {missed #, matched #}
-
-        // The caller ensures there are enough bytes available in the buffer.
-        // So we won't need to check the length of the buffer.
-        for (int i = 0; i < tag.length; i++) {
-            if (buffer[offset + i] != tag[i]) {
-                results[0]++;       // mismatched bytes
-            } else {
-                results[1]++;       // matched bytes
-            }
-        }
-
-        return results;
-    }
-
-    /*
-     * Calculate the length of a dummy buffer to run MAC computation
-     * and comparison on the remainder.
-     *
-     * The caller MUST ensure that the fullLen is not less than usedLen.
-     */
-    static int calculateRemainingLen(
-            MAC signer, int fullLen, int usedLen) {
-
-        int blockLen = signer.hashBlockLen();
-        int minimalPaddingLen = signer.minimalPaddingLen();
-
-        // (blockLen - minimalPaddingLen) is the maximum message size of
-        // the last block of hash function operation. See FIPS 180-4, or
-        // MD5 specification.
-        fullLen += 13 - (blockLen - minimalPaddingLen);
-        usedLen += 13 - (blockLen - minimalPaddingLen);
-
-        // Note: fullLen is always not less than usedLen, and blockLen
-        // is always bigger than minimalPaddingLen, so we don't worry
-        // about negative values. 0x01 is added to the result to ensure
-        // that the return value is positive.  The extra one byte does
-        // not impact the overall MAC compression function evaluations.
-        return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
-                Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen();
-    }
-
-    /*
-     * Well ... hello_request messages are _never_ hashed since we can't
-     * know when they'd appear in the sequence.
-     */
-    void ignore(int bytes) {
-        if (bytes > 0) {
-            pos += bytes;
-            lastHashed = pos;
-        }
-    }
-
-    /*
-     * We hash the (plaintext) we've processed, but only on demand.
-     *
-     * There is one place where we want to access the hash in the middle
-     * of a record:  client cert message gets hashed, and part of the
-     * same record is the client cert verify message which uses that hash.
-     * So we track how much we've read and hashed.
-     */
-    void doHashes() {
-        int len = pos - lastHashed;
-
-        if (len > 0) {
-            hashInternal(buf, lastHashed, len);
-            lastHashed = pos;
-        }
-    }
-
-    /*
-     * Need a helper function so we can hash the V2 hello correctly
-     */
-    private void hashInternal(byte databuf [], int offset, int len) {
-        if (debug != null && Debug.isOn("data")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println("[read] MD5 and SHA1 hashes:  len = "
-                    + len);
-                hd.encodeBuffer(new ByteArrayInputStream(databuf, offset, len),
-                    System.out);
-            } catch (IOException e) { }
-        }
-        handshakeHash.update(databuf, offset, len);
-    }
-
-
-    /*
-     * Handshake messages may cross record boundaries.  We "queue"
-     * these in big buffers if we need to cope with this problem.
-     * This is not anticipated to be a common case; if this turns
-     * out to be wrong, this can readily be sped up.
-     */
-    void queueHandshake(InputRecord r) throws IOException {
-        int len;
-
-        /*
-         * Hash any data that's read but unhashed.
-         */
-        doHashes();
-
-        /*
-         * Move any unread data to the front of the buffer,
-         * flagging it all as unhashed.
-         */
-        if (pos > headerSize) {
-            len = count - pos;
-            if (len != 0) {
-                System.arraycopy(buf, pos, buf, headerSize, len);
-            }
-            pos = headerSize;
-            lastHashed = pos;
-            count = headerSize + len;
-        }
-
-        /*
-         * Grow "buf" if needed
-         */
-        len = r.available() + count;
-        if (buf.length < len) {
-            byte        newbuf [];
-
-            newbuf = new byte [len];
-            System.arraycopy(buf, 0, newbuf, 0, count);
-            buf = newbuf;
-        }
-
-        /*
-         * Append the new buffer to this one.
-         */
-        System.arraycopy(r.buf, r.pos, buf, count, len - count);
-        count = len;
-
-        /*
-         * Adjust lastHashed; important for now with clients which
-         * send SSL V2 client hellos.  This will go away eventually,
-         * by buffer code cleanup.
-         */
-        len = r.lastHashed - r.pos;
-        if (pos == headerSize) {
-            lastHashed += len;
-        } else {
-            throw new SSLProtocolException("?? confused buffer hashing ??");
-        }
-        // we've read the record, advance the pointers
-        r.pos = r.count;
-    }
-
-
-    /**
-     * Prevent any more data from being read into this record,
-     * and flag the record as holding no data.
-     */
-    public void close() {
-        appDataValid = false;
-        isClosed = true;
-        mark = 0;
-        pos = 0;
-        count = 0;
-    }
-
-
-    /*
-     * We may need to send this SSL v2 "No Cipher" message back, if we
-     * are faced with an SSLv2 "hello" that's not saying "I talk v3".
-     * It's the only one documented in the V2 spec as a fatal error.
-     */
-    private static final byte[] v2NoCipher = {
-        (byte)0x80, (byte)0x03, // unpadded 3 byte record
-        (byte)0x00,             // ... error message
-        (byte)0x00, (byte)0x01  // ... NO_CIPHER error
-    };
-
-    private int readFully(InputStream s, byte b[], int off, int len)
-            throws IOException {
-        int n = 0;
-        while (n < len) {
-            int readLen = s.read(b, off + n, len - n);
-            if (readLen < 0) {
-                return readLen;
-            }
-
-            if (debug != null && Debug.isOn("packet")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-                    ByteBuffer bb = ByteBuffer.wrap(b, off + n, readLen);
-
-                    System.out.println("[Raw read]: length = " +
-                        bb.remaining());
-                    hd.encodeBuffer(bb, System.out);
-                } catch (IOException e) { }
-            }
-
-            n += readLen;
-            exlen += readLen;
-        }
-
-        return n;
-    }
-
-    /*
-     * Read the SSL V3 record ... first time around, check to see if it
-     * really IS a V3 record.  Handle SSL V2 clients which can talk V3.0,
-     * as well as real V3 record format; otherwise report an error.
-     */
-    void read(InputStream s, OutputStream o) throws IOException {
-        if (isClosed) {
-            return;
-        }
-
-        /*
-         * For SSL it really _is_ an error if the other end went away
-         * so ungracefully as to not shut down cleanly.
-         */
-        if(exlen < headerSize) {
-            int really = readFully(s, buf, exlen, headerSize - exlen);
-            if (really < 0) {
-                throw new EOFException("SSL peer shut down incorrectly");
-            }
-
-            pos = headerSize;
-            count = headerSize;
-            lastHashed = pos;
-        }
-
-        /*
-         * The first record might use some other record marking convention,
-         * typically SSL v2 header.  (PCT could also be detected here.)
-         * This case is currently common -- Navigator 3.0 usually works
-         * this way, as do IE 3.0 and other products.
-         */
-        if (!formatVerified) {
-            formatVerified = true;
-            /*
-             * The first record must either be a handshake record or an
-             * alert message. If it's not, it is either invalid or an
-             * SSLv2 message.
-             */
-            if (buf[0] != ct_handshake && buf[0] != ct_alert) {
-                handleUnknownRecord(s, o);
-            } else {
-                readV3Record(s, o);
-            }
-        } else { // formatVerified == true
-            readV3Record(s, o);
-        }
-    }
-
-    /**
-     * Read a SSL/TLS record. Throw an IOException if the format is invalid.
-     */
-    private void readV3Record(InputStream s, OutputStream o)
-            throws IOException {
-        ProtocolVersion recordVersion = ProtocolVersion.valueOf(buf[1], buf[2]);
-        // Check if too old (currently not possible)
-        // or if the major version does not match.
-        // The actual version negotiation is in the handshaker classes
-        if ((recordVersion.v < ProtocolVersion.MIN.v)
-                || (recordVersion.major > ProtocolVersion.MAX.major)) {
-            throw new SSLException(
-                "Unsupported record version " + recordVersion);
-        }
-
-        /*
-         * Get and check length, then the data.
-         */
-        int contentLen = ((buf[3] & 0x0ff) << 8) + (buf[4] & 0xff);
-
-        /*
-         * Check for upper bound.
-         */
-        if (contentLen < 0 || contentLen > maxLargeRecordSize - headerSize) {
-            throw new SSLProtocolException("Bad InputRecord size"
-                + ", count = " + contentLen
-                + ", buf.length = " + buf.length);
-        }
-
-        /*
-         * Grow "buf" if needed. Since buf is maxRecordSize by default,
-         * this only occurs when we receive records which violate the
-         * SSL specification. This is a workaround for a Microsoft SSL bug.
-         */
-        if (contentLen > buf.length - headerSize) {
-            byte[] newbuf = new byte[contentLen + headerSize];
-            System.arraycopy(buf, 0, newbuf, 0, headerSize);
-            buf = newbuf;
-        }
-
-        if (exlen < contentLen + headerSize) {
-            int really = readFully(
-                s, buf, exlen, contentLen + headerSize - exlen);
-            if (really < 0) {
-                throw new SSLException("SSL peer shut down incorrectly");
-            }
-        }
-
-        // now we've got a complete record.
-        count = contentLen + headerSize;
-        exlen = 0;
-
-        if (debug != null && Debug.isOn("record")) {
-            if (count < 0 || count > (maxRecordSize - headerSize)) {
-                System.out.println(Thread.currentThread().getName()
-                    + ", Bad InputRecord size" + ", count = " + count);
-            }
-            System.out.println(Thread.currentThread().getName()
-                + ", READ: " + recordVersion + " "
-                + contentName(contentType()) + ", length = " + available());
-        }
-        /*
-         * then caller decrypts, verifies, and uncompresses
-         */
-    }
-
-    /**
-     * Deal with unknown records. Called if the first data we read on this
-     * connection does not look like an SSL/TLS record. It could a SSLv2
-     * message, or just garbage.
-     */
-    private void handleUnknownRecord(InputStream s, OutputStream o)
-            throws IOException {
-        /*
-         * No?  Oh well; does it look like a V2 "ClientHello"?
-         * That'd be an unpadded handshake message; we don't
-         * bother checking length just now.
-         */
-        if (((buf[0] & 0x080) != 0) && buf[2] == 1) {
-            /*
-             * if the user has disabled SSLv2Hello (using
-             * setEnabledProtocol) then throw an
-             * exception
-             */
-            if (helloVersion != ProtocolVersion.SSL20Hello) {
-                throw new SSLHandshakeException("SSLv2Hello is disabled");
-            }
-
-            ProtocolVersion recordVersion =
-                                ProtocolVersion.valueOf(buf[3], buf[4]);
-
-            if (recordVersion == ProtocolVersion.SSL20Hello) {
-                /*
-                 * Looks like a V2 client hello, but not one saying
-                 * "let's talk SSLv3".  So we send an SSLv2 error
-                 * message, one that's treated as fatal by clients.
-                 * (Otherwise we'll hang.)
-                 */
-                try {
-                    writeBuffer(o, v2NoCipher, 0, v2NoCipher.length);
-                } catch (Exception e) {
-                    /* NOTHING */
-                }
-                throw new SSLException("Unsupported SSL v2.0 ClientHello");
-            }
-
-            /*
-             * If we can map this into a V3 ClientHello, read and
-             * hash the rest of the V2 handshake, turn it into a
-             * V3 ClientHello message, and pass it up.
-             */
-            int len = ((buf[0] & 0x7f) << 8) +
-                (buf[1] & 0xff) - 3;
-            if (v2Buf == null) {
-                v2Buf = new byte[len];
-            }
-            if (exlen < len + headerSize) {
-                int really = readFully(
-                        s, v2Buf, exlen - headerSize, len + headerSize - exlen);
-                if (really < 0) {
-                    throw new EOFException("SSL peer shut down incorrectly");
-                }
-            }
-
-            // now we've got a complete record.
-            exlen = 0;
-
-            hashInternal(buf, 2, 3);
-            hashInternal(v2Buf, 0, len);
-            V2toV3ClientHello(v2Buf);
-            v2Buf = null;
-            lastHashed = count;
-
-            if (debug != null && Debug.isOn("record"))  {
-                System.out.println(
-                    Thread.currentThread().getName()
-                    + ", READ:  SSL v2, contentType = "
-                    + contentName(contentType())
-                    + ", translated length = " + available());
-            }
-            return;
-
-        } else {
-            /*
-             * Does it look like a V2 "ServerHello"?
-             */
-            if (((buf [0] & 0x080) != 0) && buf [2] == 4) {
-                throw new SSLException(
-                    "SSL V2.0 servers are not supported.");
-            }
-
-            /*
-             * If this is a V2 NoCipher message then this means
-             * the other server doesn't support V3. Otherwise, we just
-             * don't understand what it's saying.
-             */
-            for (int i = 0; i < v2NoCipher.length; i++) {
-                if (buf[i] != v2NoCipher[i]) {
-                    throw new SSLException(
-                        "Unrecognized SSL message, plaintext connection?");
-                }
-            }
-
-            throw new SSLException("SSL V2.0 servers are not supported.");
-        }
-    }
-
-    /*
-     * Actually do the write here.  For SSLEngine's HS data,
-     * we'll override this method and let it take the appropriate
-     * action.
-     */
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len)
-            throws IOException {
-        s.write(buf, 0, len);
-        s.flush();
-    }
-
-    /*
-     * Support "old" clients which are capable of SSL V3.0 protocol ... for
-     * example, Navigator 3.0 clients.  The V2 message is in the header and
-     * the bytes passed as parameter.  This routine translates the V2 message
-     * into an equivalent V3 one.
-     */
-    private void V2toV3ClientHello(byte v2Msg []) throws SSLException
-    {
-        int i;
-
-        /*
-         * Build the first part of the V3 record header from the V2 one
-         * that's now buffered up.  (Lengths are fixed up later).
-         */
-        buf [0] = ct_handshake;
-        buf [1] = buf [3];      // V3.x
-        buf[2] = buf[4];
-        // header [3..4] for handshake message length
-        // count = 5;
-
-        /*
-         * Store the generic V3 handshake header:  4 bytes
-         */
-        buf [5] = 1;    // HandshakeMessage.ht_client_hello
-        // buf [6..8] for length of ClientHello (int24)
-        // count += 4;
-
-        /*
-         * ClientHello header starts with SSL version
-         */
-        buf [9] = buf [1];
-        buf [10] = buf [2];
-        // count += 2;
-        count = 11;
-
-        /*
-         * Start parsing the V2 message ...
-         */
-        int      cipherSpecLen, sessionIdLen, nonceLen;
-
-        cipherSpecLen = ((v2Msg [0] & 0xff) << 8) + (v2Msg [1] & 0xff);
-        sessionIdLen  = ((v2Msg [2] & 0xff) << 8) + (v2Msg [3] & 0xff);
-        nonceLen   = ((v2Msg [4] & 0xff) << 8) + (v2Msg [5] & 0xff);
-
-        /*
-         * Copy Random value/nonce ... if less than the 32 bytes of
-         * a V3 "Random", right justify and zero pad to the left.  Else
-         * just take the last 32 bytes.
-         */
-        int      offset = 6 + cipherSpecLen + sessionIdLen;
-
-        if (nonceLen < 32) {
-            for (i = 0; i < (32 - nonceLen); i++)
-                buf [count++] = 0;
-            System.arraycopy(v2Msg, offset, buf, count, nonceLen);
-            count += nonceLen;
-        } else {
-            System.arraycopy(v2Msg, offset + (nonceLen - 32),
-                    buf, count, 32);
-            count += 32;
-        }
-
-        /*
-         * Copy Session ID (only one byte length!)
-         */
-        offset -= sessionIdLen;
-        buf [count++] = (byte) sessionIdLen;
-
-        System.arraycopy(v2Msg, offset, buf, count, sessionIdLen);
-        count += sessionIdLen;
-
-        /*
-         * Copy and translate cipher suites ... V2 specs with first byte zero
-         * are really V3 specs (in the last 2 bytes), just copy those and drop
-         * the other ones.  Preference order remains unchanged.
-         *
-         * Example:  Netscape Navigator 3.0 (exportable) says:
-         *
-         * 0/3,     SSL_RSA_EXPORT_WITH_RC4_40_MD5
-         * 0/6,     SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
-         *
-         * Microsoft Internet Explorer 3.0 (exportable) supports only
-         *
-         * 0/3,     SSL_RSA_EXPORT_WITH_RC4_40_MD5
-         */
-        int j;
-
-        offset -= cipherSpecLen;
-        j = count + 2;
-
-        for (i = 0; i < cipherSpecLen; i += 3) {
-            if (v2Msg [offset + i] != 0)
-                continue;
-            buf [j++] = v2Msg [offset + i + 1];
-            buf [j++] = v2Msg [offset + i + 2];
-        }
-
-        j -= count + 2;
-        buf [count++] = (byte) (j >>> 8);
-        buf [count++] = (byte) j;
-        count += j;
-
-        /*
-         * Append compression methods (default/null only)
-         */
-        buf [count++] = 1;
-        buf [count++] = 0;      // Session.compression_null
-
-        /*
-         * Fill in lengths of the messages we synthesized (nested:
-         * V3 handshake message within V3 record) and then return
-         */
-        buf [3] = (byte) (count - headerSize);
-        buf [4] = (byte) ((count - headerSize) >>> 8);
-
-        buf [headerSize + 1] = 0;
-        buf [headerSize + 2] = (byte) (((count - headerSize) - 4) >>> 8);
-        buf [headerSize + 3] = (byte) ((count - headerSize) - 4);
-
-        pos = headerSize;
-    }
-
-    /**
-     * Return a description for the given content type. This method should be
-     * in Record, but since that is an interface this is not possible.
-     * Called from InputRecord and OutputRecord.
-     */
-    static String contentName(int contentType) {
-        switch (contentType) {
-        case ct_change_cipher_spec:
-            return "Change Cipher Spec";
-        case ct_alert:
-            return "Alert";
-        case ct_handshake:
-            return "Handshake";
-        case ct_application_data:
-            return "Application Data";
-        default:
-            return "contentType = " + contentType;
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/JsseJce.java b/ojluni/src/main/java/sun/security/ssl/JsseJce.java
deleted file mode 100755
index d91b8f4..0000000
--- a/ojluni/src/main/java/sun/security/ssl/JsseJce.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (c) 2001, 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.security.ssl;
-
-import java.util.*;
-import java.math.BigInteger;
-
-import java.security.*;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.*;
-
-import javax.crypto.*;
-
-// explicit import to override the Provider class in this package
-import java.security.Provider;
-
-// need internal Sun classes for FIPS tricks
-import sun.security.jca.Providers;
-import sun.security.jca.ProviderList;
-
-import sun.security.ec.ECParameters;
-import sun.security.ec.NamedCurve;
-
-import static sun.security.ssl.SunJSSE.cryptoProvider;
-
-/**
- * This class contains a few static methods for interaction with the JCA/JCE
- * to obtain implementations, etc.
- *
- * @author  Andreas Sterbenz
- */
-final class JsseJce {
-
-    private final static Debug debug = Debug.getInstance("ssl");
-
-    private final static ProviderList fipsProviderList;
-
-    // Flag indicating whether EC crypto is available.
-    // If null, then we have not checked yet.
-    // If yes, then all the EC based crypto we need is available.
-    private static Boolean ecAvailable;
-
-    // Flag indicating whether Kerberos crypto is available.
-    // If true, then all the Kerberos-based crypto we need is available.
-    private final static boolean kerberosAvailable;
-    static {
-        boolean temp;
-        try {
-            AccessController.doPrivileged(
-                new PrivilegedExceptionAction<Void>() {
-                    public Void run() throws Exception {
-                        // Test for Kerberos using the bootstrap class loader
-                        Class.forName("sun.security.krb5.PrincipalName", true,
-                                null);
-                        return null;
-                    }
-                });
-            temp = true;
-
-        } catch (Exception e) {
-            temp = false;
-        }
-        kerberosAvailable = temp;
-    }
-
-    static {
-        // force FIPS flag initialization
-        // Because isFIPS() is synchronized and cryptoProvider is not modified
-        // after it completes, this also eliminates the need for any further
-        // synchronization when accessing cryptoProvider
-        if (SunJSSE.isFIPS() == false) {
-            fipsProviderList = null;
-        } else {
-            // Setup a ProviderList that can be used by the trust manager
-            // during certificate chain validation. All the crypto must be
-            // from the FIPS provider, but we also allow the required
-            // certificate related services from the SUN provider.
-            Provider sun = Security.getProvider("SUN");
-            if (sun == null) {
-                throw new RuntimeException
-                    ("FIPS mode: SUN provider must be installed");
-            }
-            Provider sunCerts = new SunCertificates(sun);
-            fipsProviderList = ProviderList.newList(cryptoProvider, sunCerts);
-        }
-    }
-
-    private static final class SunCertificates extends Provider {
-        SunCertificates(final Provider p) {
-            super("SunCertificates", 1.0d, "SunJSSE internal");
-            AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                public Object run() {
-                    // copy certificate related services from the Sun provider
-                    for (Map.Entry<Object,Object> entry : p.entrySet()) {
-                        String key = (String)entry.getKey();
-                        if (key.startsWith("CertPathValidator.")
-                                || key.startsWith("CertPathBuilder.")
-                                || key.startsWith("CertStore.")
-                                || key.startsWith("CertificateFactory.")) {
-                            put(key, entry.getValue());
-                        }
-                    }
-                    return null;
-                }
-            });
-        }
-    }
-
-    /**
-     * JCE transformation string for RSA with PKCS#1 v1.5 padding.
-     * Can be used for encryption, decryption, signing, verifying.
-     */
-    final static String CIPHER_RSA_PKCS1 = "RSA/ECB/PKCS1Padding";
-    /**
-     * JCE transformation string for the stream cipher RC4.
-     */
-    final static String CIPHER_RC4 = "RC4";
-    /**
-     * JCE transformation string for DES in CBC mode without padding.
-     */
-    final static String CIPHER_DES = "DES/CBC/NoPadding";
-    /**
-     * JCE transformation string for (3-key) Triple DES in CBC mode
-     * without padding.
-     */
-    final static String CIPHER_3DES = "DESede/CBC/NoPadding";
-    /**
-     * JCE transformation string for AES in CBC mode
-     * without padding.
-     */
-    final static String CIPHER_AES = "AES/CBC/NoPadding";
-    /**
-     * JCA identifier string for DSA, i.e. a DSA with SHA-1.
-     */
-    final static String SIGNATURE_DSA = "DSA";
-    /**
-     * JCA identifier string for ECDSA, i.e. a ECDSA with SHA-1.
-     */
-    final static String SIGNATURE_ECDSA = "SHA1withECDSA";
-    /**
-     * JCA identifier string for Raw DSA, i.e. a DSA signature without
-     * hashing where the application provides the SHA-1 hash of the data.
-     * Note that the standard name is "NONEwithDSA" but we use "RawDSA"
-     * for compatibility.
-     */
-    final static String SIGNATURE_RAWDSA = "RawDSA";
-    /**
-     * JCA identifier string for Raw ECDSA, i.e. a DSA signature without
-     * hashing where the application provides the SHA-1 hash of the data.
-     */
-    final static String SIGNATURE_RAWECDSA = "NONEwithECDSA";
-    /**
-     * JCA identifier string for Raw RSA, i.e. a RSA PKCS#1 v1.5 signature
-     * without hashing where the application provides the hash of the data.
-     * Used for RSA client authentication with a 36 byte hash.
-     */
-    final static String SIGNATURE_RAWRSA = "NONEwithRSA";
-    /**
-     * JCA identifier string for the SSL/TLS style RSA Signature. I.e.
-     * an signature using RSA with PKCS#1 v1.5 padding signing a
-     * concatenation of an MD5 and SHA-1 digest.
-     */
-    final static String SIGNATURE_SSLRSA = "MD5andSHA1withRSA";
-
-    private JsseJce() {
-        // no instantiation of this class
-    }
-
-    synchronized static boolean isEcAvailable() {
-        if (ecAvailable == null) {
-            try {
-                JsseJce.getSignature(SIGNATURE_ECDSA);
-                JsseJce.getSignature(SIGNATURE_RAWECDSA);
-                JsseJce.getKeyAgreement("ECDH");
-                JsseJce.getKeyFactory("EC");
-                JsseJce.getKeyPairGenerator("EC");
-                ecAvailable = true;
-            } catch (Exception e) {
-                ecAvailable = false;
-            }
-        }
-        return ecAvailable;
-    }
-
-    synchronized static void clearEcAvailable() {
-        ecAvailable = null;
-    }
-
-    static boolean isKerberosAvailable() {
-        return kerberosAvailable;
-    }
-
-    /**
-     * Return an JCE cipher implementation for the specified algorithm.
-     */
-    static Cipher getCipher(String transformation)
-            throws NoSuchAlgorithmException {
-        try {
-            if (cryptoProvider == null) {
-                return Cipher.getInstance(transformation);
-            } else {
-                return Cipher.getInstance(transformation, cryptoProvider);
-            }
-        } catch (NoSuchPaddingException e) {
-            throw new NoSuchAlgorithmException(e);
-        }
-    }
-
-    /**
-     * Return an JCA signature implementation for the specified algorithm.
-     * The algorithm string should be one of the constants defined
-     * in this class.
-     */
-    static Signature getSignature(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return Signature.getInstance(algorithm);
-        } else {
-            // reference equality
-            if (algorithm == SIGNATURE_SSLRSA) {
-                // The SunPKCS11 provider currently does not support this
-                // special algorithm. We allow a fallback in this case because
-                // the SunJSSE implementation does the actual crypto using
-                // a NONEwithRSA signature obtained from the cryptoProvider.
-                if (cryptoProvider.getService("Signature", algorithm) == null) {
-                    // Calling Signature.getInstance() and catching the
-                    // exception would be cleaner, but exceptions are a little
-                    // expensive. So we check directly via getService().
-                    try {
-                        return Signature.getInstance(algorithm, "SunJSSE");
-                    } catch (NoSuchProviderException e) {
-                        throw new NoSuchAlgorithmException(e);
-                    }
-                }
-            }
-            return Signature.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyGenerator getKeyGenerator(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyGenerator.getInstance(algorithm);
-        } else {
-            return KeyGenerator.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyPairGenerator getKeyPairGenerator(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyPairGenerator.getInstance(algorithm);
-        } else {
-            return KeyPairGenerator.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyAgreement getKeyAgreement(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyAgreement.getInstance(algorithm);
-        } else {
-            return KeyAgreement.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static Mac getMac(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return Mac.getInstance(algorithm);
-        } else {
-            return Mac.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static KeyFactory getKeyFactory(String algorithm)
-            throws NoSuchAlgorithmException {
-        if (cryptoProvider == null) {
-            return KeyFactory.getInstance(algorithm);
-        } else {
-            return KeyFactory.getInstance(algorithm, cryptoProvider);
-        }
-    }
-
-    static SecureRandom getSecureRandom() throws KeyManagementException {
-        if (cryptoProvider == null) {
-            return new SecureRandom();
-        }
-        // Try "PKCS11" first. If that is not supported, iterate through
-        // the provider and return the first working implementation.
-        try {
-            return SecureRandom.getInstance("PKCS11", cryptoProvider);
-        } catch (NoSuchAlgorithmException e) {
-            // ignore
-        }
-        for (Provider.Service s : cryptoProvider.getServices()) {
-            if (s.getType().equals("SecureRandom")) {
-                try {
-                    return SecureRandom.getInstance(s.getAlgorithm(), cryptoProvider);
-                } catch (NoSuchAlgorithmException ee) {
-                    // ignore
-                }
-            }
-        }
-        throw new KeyManagementException("FIPS mode: no SecureRandom "
-            + " implementation found in provider " + cryptoProvider.getName());
-    }
-
-    static MessageDigest getMD5() {
-        return getMessageDigest("MD5");
-    }
-
-    static MessageDigest getSHA() {
-        return getMessageDigest("SHA");
-    }
-
-    static MessageDigest getMessageDigest(String algorithm) {
-        try {
-            if (cryptoProvider == null) {
-                return MessageDigest.getInstance(algorithm);
-            } else {
-                return MessageDigest.getInstance(algorithm, cryptoProvider);
-            }
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException
-                        ("Algorithm " + algorithm + " not available", e);
-        }
-    }
-
-    static int getRSAKeyLength(PublicKey key) {
-        BigInteger modulus;
-        if (key instanceof RSAPublicKey) {
-            modulus = ((RSAPublicKey)key).getModulus();
-        } else {
-            RSAPublicKeySpec spec = getRSAPublicKeySpec(key);
-            modulus = spec.getModulus();
-        }
-        return modulus.bitLength();
-    }
-
-    static RSAPublicKeySpec getRSAPublicKeySpec(PublicKey key) {
-        if (key instanceof RSAPublicKey) {
-            RSAPublicKey rsaKey = (RSAPublicKey)key;
-            return new RSAPublicKeySpec(rsaKey.getModulus(),
-                                        rsaKey.getPublicExponent());
-        }
-        try {
-            KeyFactory factory = JsseJce.getKeyFactory("RSA");
-            return factory.getKeySpec(key, RSAPublicKeySpec.class);
-        } catch (Exception e) {
-            throw (RuntimeException)new RuntimeException().initCause(e);
-        }
-    }
-
-    static ECParameterSpec getECParameterSpec(String namedCurveOid) {
-        return NamedCurve.getECParameterSpec(namedCurveOid);
-    }
-
-    static String getNamedCurveOid(ECParameterSpec params) {
-        return ECParameters.getCurveName(params);
-    }
-
-    static ECPoint decodePoint(byte[] encoded, EllipticCurve curve)
-            throws java.io.IOException {
-        return ECParameters.decodePoint(encoded, curve);
-    }
-
-    static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
-        return ECParameters.encodePoint(point, curve);
-    }
-
-    // In FIPS mode, set thread local providers; otherwise a no-op.
-    // Must be paired with endFipsProvider.
-    static Object beginFipsProvider() {
-        if (fipsProviderList == null) {
-            return null;
-        } else {
-            return Providers.beginThreadProviderList(fipsProviderList);
-        }
-    }
-
-    static void endFipsProvider(Object o) {
-        if (fipsProviderList != null) {
-            Providers.endThreadProviderList((ProviderList)o);
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java
deleted file mode 100755
index 339f94b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.SecureRandom;
-import javax.crypto.SecretKey;
-
-/**
- * A helper class that calls the KerberosClientKeyExchange implementation.
- */
-public class KerberosClientKeyExchange extends HandshakeMessage {
-
-    private static final String IMPL_CLASS =
-        "sun.security.ssl.krb5.KerberosClientKeyExchangeImpl";
-
-    private static final Class<?> implClass = AccessController.doPrivileged(
-            new PrivilegedAction<Class<?>>() {
-                public Class<?> run() {
-                    try {
-                        return Class.forName(IMPL_CLASS, true, null);
-                    } catch (ClassNotFoundException cnf) {
-                        return null;
-                    }
-                }
-            }
-        );
-    private final KerberosClientKeyExchange impl = createImpl();
-
-    private KerberosClientKeyExchange createImpl() {
-        if (getClass() == KerberosClientKeyExchange.class) {
-            try {
-                return (KerberosClientKeyExchange)implClass.newInstance();
-            } catch (InstantiationException e) {
-                throw new AssertionError(e);
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-        return null;
-    }
-
-    public KerberosClientKeyExchange() {
-        // empty
-    }
-
-    public KerberosClientKeyExchange(String serverName, boolean isLoopback,
-        AccessControlContext acc, ProtocolVersion protocolVersion,
-        SecureRandom rand) throws IOException {
-
-        if (impl != null) {
-            init(serverName, isLoopback, acc, protocolVersion, rand);
-        } else {
-            throw new IllegalStateException("Kerberos is unavailable");
-        }
-    }
-
-    public KerberosClientKeyExchange(ProtocolVersion protocolVersion,
-        ProtocolVersion clientVersion, SecureRandom rand,
-        HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
-
-        if (impl != null) {
-            init(protocolVersion, clientVersion, rand, input, serverKeys);
-        } else {
-            throw new IllegalStateException("Kerberos is unavailable");
-        }
-    }
-
-    @Override
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    @Override
-    public int  messageLength() {
-        return impl.messageLength();
-    }
-
-    @Override
-    public void send(HandshakeOutStream s) throws IOException {
-        impl.send(s);
-    }
-
-    @Override
-    public void print(PrintStream p) throws IOException {
-        impl.print(p);
-    }
-
-    public void init(String serverName, boolean isLoopback,
-        AccessControlContext acc, ProtocolVersion protocolVersion,
-        SecureRandom rand) throws IOException {
-
-        if (impl != null) {
-            impl.init(serverName, isLoopback, acc, protocolVersion, rand);
-        }
-    }
-
-    public void init(ProtocolVersion protocolVersion,
-        ProtocolVersion clientVersion, SecureRandom rand,
-        HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
-
-        if (impl != null) {
-            impl.init(protocolVersion, clientVersion, rand, input, serverKeys);
-        }
-    }
-
-    public byte[] getUnencryptedPreMasterSecret() {
-        return impl.getUnencryptedPreMasterSecret();
-    }
-
-    public Principal getPeerPrincipal(){
-        return impl.getPeerPrincipal();
-    }
-
-    public Principal getLocalPrincipal(){
-        return impl.getLocalPrincipal();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java b/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java
deleted file mode 100755
index d1bbe83..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import javax.crypto.SecretKey;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-/**
- * A helper class for Kerberos APIs.
- */
-public final class Krb5Helper {
-
-    private Krb5Helper() { }
-
-    // loads Krb5Proxy implementation class if available
-    private static final String IMPL_CLASS =
-        "sun.security.ssl.krb5.Krb5ProxyImpl";
-
-    private static final Krb5Proxy proxy =
-        AccessController.doPrivileged(new PrivilegedAction<Krb5Proxy>() {
-            public Krb5Proxy run() {
-                try {
-                    Class<?> c = Class.forName(IMPL_CLASS, true, null);
-                    return (Krb5Proxy)c.newInstance();
-                } catch (ClassNotFoundException cnf) {
-                    return null;
-                } catch (InstantiationException e) {
-                    throw new AssertionError(e);
-                } catch (IllegalAccessException e) {
-                    throw new AssertionError(e);
-                }
-            }});
-
-    /**
-     * Returns true if Kerberos is available.
-     */
-    public static boolean isAvailable() {
-        return proxy != null;
-    }
-
-    private static void ensureAvailable() {
-        if (proxy == null)
-            throw new AssertionError("Kerberos should have been available");
-    }
-
-    /**
-     * Returns the Subject associated with client-side of the SSL socket.
-     */
-    public static Subject getClientSubject(AccessControlContext acc)
-            throws LoginException {
-        ensureAvailable();
-        return proxy.getClientSubject(acc);
-    }
-
-    /**
-     * Returns the Subject associated with server-side of the SSL socket.
-     */
-    public static Subject getServerSubject(AccessControlContext acc)
-            throws LoginException {
-        ensureAvailable();
-        return proxy.getServerSubject(acc);
-    }
-
-    /**
-     * Returns the KerberosKeys for the default server-side principal.
-     */
-    public static SecretKey[] getServerKeys(AccessControlContext acc)
-            throws LoginException {
-        ensureAvailable();
-        return proxy.getServerKeys(acc);
-    }
-
-    /**
-     * Returns the server-side principal name associated with the KerberosKey.
-     */
-    public static String getServerPrincipalName(SecretKey kerberosKey) {
-        ensureAvailable();
-        return proxy.getServerPrincipalName(kerberosKey);
-    }
-
-    /**
-     * Returns the hostname embedded in the principal name.
-     */
-    public static String getPrincipalHostName(Principal principal) {
-        ensureAvailable();
-        return proxy.getPrincipalHostName(principal);
-    }
-
-    /**
-     * Returns a ServicePermission for the principal name and action.
-     */
-    public static Permission getServicePermission(String principalName,
-            String action) {
-        ensureAvailable();
-        return proxy.getServicePermission(principalName, action);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java b/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java
deleted file mode 100755
index 14a1501..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AccessControlContext;
-import java.security.Permission;
-import java.security.Principal;
-import javax.crypto.SecretKey;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-/**
- * An interface to a subset of the Kerberos APIs to avoid a static dependency
- * on the types defined by these APIs.
- */
-public interface Krb5Proxy {
-
-    /**
-     * Returns the Subject associated with the client-side of the SSL socket.
-     */
-    Subject getClientSubject(AccessControlContext acc) throws LoginException;
-
-    /**
-     * Returns the Subject associated with the server-side of the SSL socket.
-     */
-    Subject getServerSubject(AccessControlContext acc) throws LoginException;
-
-
-    /**
-     * Returns the KerberosKeys for the default server-side principal.
-     */
-    SecretKey[] getServerKeys(AccessControlContext acc) throws LoginException;
-
-    /**
-     * Returns the server-side principal name associated with the KerberosKey.
-     */
-    String getServerPrincipalName(SecretKey kerberosKey);
-
-    /**
-     * Returns the hostname embedded in the principal name.
-     */
-    String getPrincipalHostName(Principal principal);
-
-    /**
-     * Returns a ServicePermission for the principal name and action.
-     */
-    Permission getServicePermission(String principalName, String action);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/MAC.java b/ojluni/src/main/java/sun/security/ssl/MAC.java
deleted file mode 100755
index e491cc3..0000000
--- a/ojluni/src/main/java/sun/security/ssl/MAC.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-
-import java.nio.ByteBuffer;
-
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-
-import sun.security.ssl.CipherSuite.MacAlg;
-import static sun.security.ssl.CipherSuite.*;
-
-/**
- * This class computes the "Message Authentication Code" (MAC) for each
- * SSL message.  This is essentially a shared-secret signature, used to
- * provide integrity protection for SSL messages.  The MAC is actually
- * one of several keyed hashes, as associated with the cipher suite and
- * protocol version.  (SSL v3.0 uses one construct, TLS uses another.)
- * <P>
- * NOTE: MAC computation is the only place in the SSL protocol that the
- * sequence number is used.  It's also reset to zero with each change of
- * a cipher spec, so this is the only place this state is needed.
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class MAC {
-
-    final static MAC NULL = new MAC();
-
-    // Value of the null MAC is fixed
-    private static final byte nullMAC[] = new byte[0];
-
-    // internal identifier for the MAC algorithm
-    private final MacAlg        macAlg;
-
-    // stuff defined by the kind of MAC algorithm
-    private final int           macSize;
-
-    // JCE Mac object
-    private final Mac mac;
-
-    // byte array containing the additional information we MAC in each record
-    // (see below)
-    private final byte[] block;
-
-    // sequence number + record type + + record length
-    private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
-
-    // sequence number + record type + protocol version + record length
-    private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
-
-    // offset of record type in block
-    private static final int BLOCK_OFFSET_TYPE    = 8;
-
-    // offset of protocol version number in block (TLS only)
-    private static final int BLOCK_OFFSET_VERSION = 8 + 1;
-
-    private MAC() {
-        macSize = 0;
-        macAlg = M_NULL;
-        mac = null;
-        block = null;
-    }
-
-    /**
-     * Set up, configured for the given SSL/TLS MAC type and version.
-     */
-    MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
-            throws NoSuchAlgorithmException, InvalidKeyException {
-        this.macAlg = macAlg;
-        this.macSize = macAlg.size;
-
-        String algorithm;
-        boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);
-
-        if (macAlg == M_MD5) {
-            algorithm = tls ? "HmacMD5" : "SslMacMD5";
-        } else if (macAlg == M_SHA) {
-            algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
-        } else if (macAlg == M_SHA256) {
-            algorithm = "HmacSHA256";    // TLS 1.2+
-        } else if (macAlg == M_SHA384) {
-            algorithm = "HmacSHA384";    // TLS 1.2+
-        } else {
-            throw new RuntimeException("Unknown Mac " + macAlg);
-        }
-
-        mac = JsseJce.getMac(algorithm);
-        mac.init(key);
-
-        if (tls) {
-            block = new byte[BLOCK_SIZE_TLS];
-            block[BLOCK_OFFSET_VERSION]   = protocolVersion.major;
-            block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
-        } else {
-            block = new byte[BLOCK_SIZE_SSL];
-        }
-    }
-
-    /**
-     * Returns the length of the MAC.
-     */
-    int MAClen() {
-        return macSize;
-    }
-
-    /**
-     * Returns the hash function block length of the MAC alorithm.
-     */
-    int hashBlockLen() {
-        return macAlg.hashBlockSize;
-    }
-
-    /**
-     * Returns the hash function minimal padding length of the MAC alorithm.
-     */
-    int minimalPaddingLen() {
-        return macAlg.minimalPaddingSize;
-    }
-
-    /**
-     * Computes and returns the MAC for the data in this byte array.
-     *
-     * @param type record type
-     * @param buf compressed record on which the MAC is computed
-     * @param offset start of compressed record data
-     * @param len the size of the compressed record
-     * @param isSimulated if true, simulate the the MAC computation
-     */
-    final byte[] compute(byte type, byte buf[],
-            int offset, int len, boolean isSimulated) {
-        return compute(type, null, buf, offset, len, isSimulated);
-    }
-
-    /**
-     * Compute and returns the MAC for the remaining data
-     * in this ByteBuffer.
-     *
-     * On return, the bb position == limit, and limit will
-     * have not changed.
-     *
-     * @param type record type
-     * @param bb a ByteBuffer in which the position and limit
-     *          demarcate the data to be MAC'd.
-     * @param isSimulated if true, simulate the the MAC computation
-     */
-    final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
-        return compute(type, bb, null, 0, bb.remaining(), isSimulated);
-    }
-
-    /**
-     * Check whether the sequence number is close to wrap
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap. When the sequence number is near
-     * to wrap, we need to close the connection immediately.
-     */
-    final boolean seqNumOverflow() {
-        /*
-         * Conservatively, we don't allow more records to be generated
-         * when there are only 2^8 sequence numbers left.
-         */
-        return (block != null && mac != null &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
-                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
-                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
-                block[6] == (byte)0xFF);
-    }
-
-    /*
-     * Check whether to renew the sequence number
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap.  If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead.
-     */
-    final boolean seqNumIsHuge() {
-        /*
-         * Conservatively, we should ask for renegotiation when there are
-         * only 2^48 sequence numbers left.
-         */
-        return (block != null && mac != null &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF);
-    }
-
-    // increment the sequence number in the block array
-    // it is a 64-bit number stored in big-endian format
-    private void incrementSequenceNumber() {
-        int k = 7;
-        while ((k >= 0) && (++block[k] == 0)) {
-            k--;
-        }
-    }
-
-    /*
-     * Compute based on either buffer type, either bb.position/limit
-     * or buf/offset/len.
-     */
-    private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
-            int offset, int len, boolean isSimulated) {
-
-        if (macSize == 0) {
-            return nullMAC;
-        }
-
-        // MUST NOT increase the sequence number for a simulated computation.
-        if (!isSimulated) {
-            block[BLOCK_OFFSET_TYPE] = type;
-            block[block.length - 2]  = (byte)(len >> 8);
-            block[block.length - 1]  = (byte)(len     );
-
-            mac.update(block);
-            incrementSequenceNumber();
-        }
-
-        // content
-        if (bb != null) {
-            mac.update(bb);
-        } else {
-            mac.update(buf, offset, len);
-        }
-
-        return mac.doFinal();
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/OutputRecord.java b/ojluni/src/main/java/sun/security/ssl/OutputRecord.java
deleted file mode 100755
index 012816d..0000000
--- a/ojluni/src/main/java/sun/security/ssl/OutputRecord.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.util.Arrays;
-
-import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as written to a TCP stream.
- *
- * Each record has a message area that starts out with data supplied by the
- * application.  It may grow/shrink due to compression and will be modified
- * in place for mac-ing and encryption.
- *
- * Handshake records have additional needs, notably accumulation of a set
- * of hashes which are used to establish that handshaking was done right.
- * Handshake records usually have several handshake messages each, and we
- * need message-level control over what's hashed.
- *
- * @author David Brownell
- */
-class OutputRecord extends ByteArrayOutputStream implements Record {
-
-    private HandshakeHash       handshakeHash;
-    private int                 lastHashed;
-    private boolean             firstMessage;
-    final private byte          contentType;
-
-    // current protocol version, sent as record version
-    ProtocolVersion     protocolVersion;
-
-    // version for the ClientHello message. Only relevant if this is a
-    // client handshake record. If set to ProtocolVersion.SSL20Hello,
-    // the V3 client hello is converted to V2 format.
-    private ProtocolVersion     helloVersion;
-
-    /* Class and subclass dynamic debugging support */
-    static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Default constructor makes a record supporting the maximum
-     * SSL record size.  It allocates the header bytes directly.
-     *
-     * @param type the content type for the record
-     */
-    OutputRecord(byte type, int size) {
-        super(size);
-        this.protocolVersion = ProtocolVersion.DEFAULT;
-        this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
-        firstMessage = true;
-        count = headerSize;
-        contentType = type;
-        lastHashed = count;
-    }
-
-    OutputRecord(byte type) {
-        this(type, recordSize(type));
-    }
-
-    /**
-     * Get the size of the buffer we need for records of the specified
-     * type.
-     */
-    private static int recordSize(byte type) {
-        if ((type == ct_change_cipher_spec) || (type == ct_alert)) {
-            return maxAlertRecordSize;
-        } else {
-            return maxRecordSize;
-        }
-    }
-
-    /*
-     * Updates the SSL version of this record.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-    }
-
-    /*
-     * Updates helloVersion of this record.
-     */
-    synchronized void setHelloVersion(ProtocolVersion helloVersion) {
-        this.helloVersion = helloVersion;
-    }
-
-    /*
-     * Reset the record so that it can be refilled, starting
-     * immediately after the header.
-     */
-    public synchronized void reset() {
-        super.reset();
-        count = headerSize;
-        lastHashed = count;
-    }
-
-    /*
-     * For handshaking, we need to be able to hash every byte above the
-     * record marking layer.  This is where we're guaranteed to see those
-     * bytes, so this is where we can hash them.
-     */
-    void setHandshakeHash(HandshakeHash handshakeHash) {
-        assert(contentType == ct_handshake);
-        this.handshakeHash = handshakeHash;
-    }
-
-    /*
-     * We hash (the plaintext) on demand.  There is one place where
-     * we want to access the hash in the middle of a record:  client
-     * cert message gets hashed, and part of the same record is the
-     * client cert verify message which uses that hash.  So we track
-     * how much of each record we've hashed so far.
-     */
-    void doHashes() {
-        int len = count - lastHashed;
-
-        if (len > 0) {
-            hashInternal(buf, lastHashed, len);
-            lastHashed = count;
-        }
-    }
-
-    /*
-     * Need a helper function so we can hash the V2 hello correctly
-     */
-    private void hashInternal(byte buf [], int offset, int len) {
-        if (debug != null && Debug.isOn("data")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-
-                System.out.println("[write] MD5 and SHA1 hashes:  len = "
-                    + len);
-                hd.encodeBuffer(new ByteArrayInputStream(buf,
-                    lastHashed, len), System.out);
-            } catch (IOException e) { }
-        }
-
-        handshakeHash.update(buf, lastHashed, len);
-        lastHashed = count;
-    }
-
-    /*
-     * Return true iff the record is empty -- to avoid doing the work
-     * of sending empty records over the network.
-     */
-    boolean isEmpty() {
-        return count == headerSize;
-    }
-
-    /*
-     * Return true if the record is of a given alert.
-     */
-    boolean isAlert(byte description) {
-        // An alert is defined with a two bytes struct,
-        // {byte level, byte description}, following after the header bytes.
-        if (count > (headerSize + 1) && contentType == ct_alert) {
-            return buf[headerSize + 1] == description;
-        }
-
-        return false;
-    }
-
-    /*
-     * Compute the MAC and append it to this record.  In case we
-     * are automatically flushing a handshake stream, make sure we
-     * have hashed the message first.
-     */
-    void addMAC(MAC signer) throws IOException {
-        //
-        // when we support compression, hashing can't go here
-        // since it'll need to be done on the uncompressed data,
-        // and the MAC applies to the compressed data.
-        //
-        if (contentType == ct_handshake) {
-            doHashes();
-        }
-        if (signer.MAClen() != 0) {
-            byte[] hash = signer.compute(contentType, buf,
-                    headerSize, count - headerSize, false);
-            write(hash);
-        }
-    }
-
-    /*
-     * Encrypt ... length may grow due to block cipher padding
-     */
-    void encrypt(CipherBox box) {
-        int len = count - headerSize;
-        count = headerSize + box.encrypt(buf, headerSize, len);
-    }
-
-
-    /*
-     * Tell how full the buffer is ... for filling it with application or
-     * handshake data.
-     */
-    final int availableDataBytes() {
-        int dataSize = count - headerSize;
-        return maxDataSize - dataSize;
-    }
-
-    /*
-     * Increases the capacity if necessary to ensure that it can hold
-     * at least the number of elements specified by the minimum
-     * capacity argument.
-     *
-     * Note that the increased capacity is only can be used for held
-     * record buffer. Please DO NOT update the availableDataBytes()
-     * according to the expended buffer capacity.
-     *
-     * @see availableDataBytes()
-     */
-    private void ensureCapacity(int minCapacity) {
-        // overflow-conscious code
-        if (minCapacity > buf.length) {
-            buf = Arrays.copyOf(buf, minCapacity);
-        }
-    }
-
-    /*
-     * Return the type of SSL record that's buffered here.
-     */
-    final byte contentType() {
-        return contentType;
-    }
-
-    /*
-     * Write the record out on the stream.  Note that you must have (in
-     * order) compressed the data, appended the MAC, and encrypted it in
-     * order for the record to be understood by the other end.  (Some of
-     * those steps will be null early in handshaking.)
-     *
-     * Note that this does no locking for the connection, it's required
-     * that synchronization be done elsewhere.  Also, this does its work
-     * in a single low level write, for efficiency.
-     */
-    void write(OutputStream s, boolean holdRecord,
-            ByteArrayOutputStream heldRecordBuffer) throws IOException {
-        /*
-         * Don't emit content-free records.  (Even change cipher spec
-         * messages have a byte of data!)
-         */
-        if (count == headerSize) {
-            return;
-        }
-
-        int length = count - headerSize;
-        // "should" really never write more than about 14 Kb...
-        if (length < 0) {
-            throw new SSLException("output record size too small: "
-                + length);
-        }
-
-        if (debug != null
-                && (Debug.isOn("record") || Debug.isOn("handshake"))) {
-            if ((debug != null && Debug.isOn("record"))
-                    || contentType() == ct_change_cipher_spec)
-                System.out.println(Thread.currentThread().getName()
-                    // v3.0/v3.1 ...
-                    + ", WRITE: " + protocolVersion
-                    + " " + InputRecord.contentName(contentType())
-                    + ", length = " + length);
-        }
-
-        /*
-         * If this is the initial ClientHello on this connection and
-         * we're not trying to resume a (V3) session then send a V2
-         * ClientHello instead so we can detect V2 servers cleanly.
-         */
-         if (firstMessage && useV2Hello()) {
-            byte[] v3Msg = new byte[length - 4];
-            System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length);
-            V3toV2ClientHello(v3Msg);
-            handshakeHash.reset();
-            lastHashed = 2;
-            doHashes();
-            if (debug != null && Debug.isOn("record"))  {
-                System.out.println(
-                    Thread.currentThread().getName()
-                    + ", WRITE: SSLv2 client hello message"
-                    + ", length = " + (count - 2)); // 2 byte SSLv2 header
-            }
-        } else {
-            /*
-             * Fill out the header, write it and the message.
-             */
-            buf[0] = contentType;
-            buf[1] = protocolVersion.major;
-            buf[2] = protocolVersion.minor;
-            buf[3] = (byte)(length >> 8);
-            buf[4] = (byte)(length);
-        }
-        firstMessage = false;
-
-        /*
-         * The upper levels may want us to delay sending this packet so
-         * multiple TLS Records can be sent in one (or more) TCP packets.
-         * If so, add this packet to the heldRecordBuffer.
-         *
-         * NOTE:  all writes have been synchronized by upper levels.
-         */
-        int debugOffset = 0;
-        if (holdRecord) {
-            /*
-             * If holdRecord is true, we must have a heldRecordBuffer.
-             *
-             * Don't worry about the override of writeBuffer(), because
-             * when holdRecord is true, the implementation in this class
-             * will be used.
-             */
-            writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset);
-        } else {
-            // It's time to send, do we have buffered data?
-            // May or may not have a heldRecordBuffer.
-            if (heldRecordBuffer != null && heldRecordBuffer.size() > 0) {
-                int heldLen = heldRecordBuffer.size();
-
-                // Ensure the capacity of this buffer.
-                ensureCapacity(count + heldLen);
-
-                // Slide everything in the buffer to the right.
-                System.arraycopy(buf, 0, buf, heldLen, count);
-
-                // Prepend the held record to the buffer.
-                System.arraycopy(
-                    heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
-                count += heldLen;
-
-                // Clear the held buffer.
-                heldRecordBuffer.reset();
-
-                // The held buffer has been dumped, set the debug dump offset.
-                debugOffset = heldLen;
-            }
-            writeBuffer(s, buf, 0, count, debugOffset);
-        }
-
-        reset();
-    }
-
-    /*
-     * Actually do the write here.  For SSLEngine's HS data,
-     * we'll override this method and let it take the appropriate
-     * action.
-     */
-    void writeBuffer(OutputStream s, byte [] buf, int off, int len,
-            int debugOffset) throws IOException {
-
-        s.write(buf, off, len);
-        s.flush();
-
-        // Output only the record from the specified debug offset.
-        if (debug != null && Debug.isOn("packet")) {
-            try {
-                HexDumpEncoder hd = new HexDumpEncoder();
-                ByteBuffer bb = ByteBuffer.wrap(
-                        buf, off + debugOffset, len - debugOffset);
-
-                System.out.println("[Raw write]: length = " +
-                    bb.remaining());
-                hd.encodeBuffer(bb, System.out);
-            } catch (IOException e) { }
-        }
-    }
-
-    /*
-     * Return whether the buffer contains a ClientHello message that should
-     * be converted to V2 format.
-     */
-    private boolean useV2Hello() {
-        return firstMessage
-            && (helloVersion == ProtocolVersion.SSL20Hello)
-            && (contentType == ct_handshake)
-            && (buf[5] == HandshakeMessage.ht_client_hello)
-            && (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty
-    }
-
-    /*
-     * Detect "old" servers which are capable of SSL V2.0 protocol ... for
-     * example, Netscape Commerce 1.0 servers.  The V3 message is in the
-     * header and the bytes passed as parameter.  This routine translates
-     * the V3 message into an equivalent V2 one.
-     *
-     * Note that the translation will strip off all hello extensions as
-     * SSL V2.0 does not support hello extension.
-     */
-    private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
-        int v3SessionIdLenOffset = 2 + 32; // version + nonce
-        int v3SessionIdLen = v3Msg[v3SessionIdLenOffset];
-        int v3CipherSpecLenOffset = v3SessionIdLenOffset + 1 + v3SessionIdLen;
-        int v3CipherSpecLen = ((v3Msg[v3CipherSpecLenOffset] & 0xff) << 8) +
-          (v3Msg[v3CipherSpecLenOffset + 1] & 0xff);
-        int cipherSpecs = v3CipherSpecLen / 2; // 2 bytes each in V3
-
-        /*
-         * Copy over the cipher specs. We don't care about actually translating
-         * them for use with an actual V2 server since we only talk V3.
-         * Therefore, just copy over the V3 cipher spec values with a leading
-         * 0.
-         */
-        int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
-        int v2CipherSpecLen = 0;
-        count = 11;
-        boolean containsRenegoInfoSCSV = false;
-        for (int i = 0; i < cipherSpecs; i++) {
-            byte byte1, byte2;
-
-            byte1 = v3Msg[v3CipherSpecOffset++];
-            byte2 = v3Msg[v3CipherSpecOffset++];
-            v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
-            if (!containsRenegoInfoSCSV &&
-                        byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
-                containsRenegoInfoSCSV = true;
-            }
-        }
-
-        if (!containsRenegoInfoSCSV) {
-            v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
-        }
-
-        /*
-         * Build the first part of the V3 record header from the V2 one
-         * that's now buffered up.  (Lengths are fixed up later).
-         */
-        buf[2] = HandshakeMessage.ht_client_hello;
-        buf[3] = v3Msg[0];      // major version
-        buf[4] = v3Msg[1];      // minor version
-        buf[5] = (byte)(v2CipherSpecLen >>> 8);
-        buf[6] = (byte)v2CipherSpecLen;
-        buf[7] = 0;
-        buf[8] = 0;             // always no session
-        buf[9] = 0;
-        buf[10] = 32;           // nonce length (always 32 in V3)
-
-        /*
-         * Copy in the nonce.
-         */
-        System.arraycopy(v3Msg, 2, buf, count, 32);
-        count += 32;
-
-        /*
-         * Set the length of the message.
-         */
-        count -= 2; // don't include length field itself
-        buf[0] = (byte)(count >>> 8);
-        buf[0] |= 0x80;
-        buf[1] = (byte)(count);
-        count += 2;
-    }
-
-    /*
-     * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
-     * This is taken from the SSL V3 specification, Appendix E.
-     */
-    private static int[] V3toV2CipherMap1 =
-        {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
-    private static int[] V3toV2CipherMap3 =
-        {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
-
-    /*
-     * See which matching pure-V2 cipher specs we need to include.
-     * We are including these not because we are actually prepared
-     * to talk V2 but because the Oracle Web Server insists on receiving
-     * at least 1 "pure V2" cipher suite that it supports and returns an
-     * illegal_parameter alert unless one is present. Rather than mindlessly
-     * claiming to implement all documented pure V2 cipher suites the code below
-     * just claims to implement the V2 cipher suite that is "equivalent"
-     * in terms of cipher algorithm & exportability with the actual V3 cipher
-     * suite that we do support.
-     */
-    private int V3toV2CipherSuite(byte byte1, byte byte2) {
-        buf[count++] = 0;
-        buf[count++] = byte1;
-        buf[count++] = byte2;
-
-        if (((byte2 & 0xff) > 0xA) ||
-                (V3toV2CipherMap1[byte2] == -1)) {
-            return 3;
-        }
-
-        buf[count++] = (byte)V3toV2CipherMap1[byte2];
-        buf[count++] = 0;
-        buf[count++] = (byte)V3toV2CipherMap3[byte2];
-
-        return 6;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ProtocolList.java b/ojluni/src/main/java/sun/security/ssl/ProtocolList.java
deleted file mode 100755
index a57a9bd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ProtocolList.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-
-/**
- * A list of ProtocolVersions. Also maintains the list of supported protocols.
- * Instances of this class are immutable. Some member variables are final
- * and can be accessed directly without method accessors.
- *
- * @author  Andreas Sterbenz
- * @since   1.4.1
- */
-final class ProtocolList {
-
-    // the sorted protocol version list
-    private final ArrayList<ProtocolVersion> protocols;
-
-    private String[] protocolNames;
-
-    // the minimum and maximum ProtocolVersions in this list
-    final ProtocolVersion min, max;
-
-    // the format for the hello version to use
-    final ProtocolVersion helloVersion;
-
-    ProtocolList(String[] names) {
-        this(convert(names));
-    }
-
-    ProtocolList(ArrayList<ProtocolVersion> versions) {
-        this.protocols = versions;
-
-        if ((protocols.size() == 1) &&
-                protocols.contains(ProtocolVersion.SSL20Hello)) {
-            throw new IllegalArgumentException("SSLv2Hello cannot be " +
-                "enabled unless at least one other supported version " +
-                "is also enabled.");
-        }
-
-        if (protocols.size() != 0) {
-            Collections.sort(protocols);
-            min = protocols.get(0);
-            max = protocols.get(protocols.size() - 1);
-            helloVersion = protocols.get(0);
-        } else {
-            min = ProtocolVersion.NONE;
-            max = ProtocolVersion.NONE;
-            helloVersion = ProtocolVersion.NONE;
-        }
-    }
-
-    private static ArrayList<ProtocolVersion> convert(String[] names) {
-        if (names == null) {
-            throw new IllegalArgumentException("Protocols may not be null");
-        }
-
-        ArrayList<ProtocolVersion> versions = new ArrayList<>(3);
-        for (int i = 0; i < names.length; i++ ) {
-            ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
-            if (versions.contains(version) == false) {
-                versions.add(version);
-            }
-        }
-
-        return versions;
-    }
-
-    /**
-     * Return whether this list contains the specified protocol version.
-     * SSLv2Hello is not a real protocol version we support, we always
-     * return false for it.
-     */
-    boolean contains(ProtocolVersion protocolVersion) {
-        if (protocolVersion == ProtocolVersion.SSL20Hello) {
-            return false;
-        }
-        return protocols.contains(protocolVersion);
-    }
-
-    /**
-     * Return a reference to the internal Collection of CipherSuites.
-     * The Collection MUST NOT be modified.
-     */
-    Collection<ProtocolVersion> collection() {
-        return protocols;
-    }
-
-    /**
-     * Select a protocol version from the list.
-     *
-     * Return the lower of the protocol version of that suggested by
-     * the <code>protocolVersion</code> and the highest version of this
-     * protocol list, or null if no protocol version is available.
-     *
-     * The method is used by TLS server to negotiated the protocol
-     * version between client suggested protocol version in the
-     * client hello and protocol versions supported by the server.
-     */
-    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
-        ProtocolVersion selectedVersion = null;
-        for (ProtocolVersion pv : protocols) {
-            if (pv.v > protocolVersion.v) {
-                break;  // Safe to break here as this.protocols is sorted
-            }
-            selectedVersion = pv;
-        }
-
-        return selectedVersion;
-    }
-
-    /**
-     * Return an array with the names of the ProtocolVersions in this list.
-     */
-    synchronized String[] toStringArray() {
-        if (protocolNames == null) {
-            protocolNames = new String[protocols.size()];
-            int i = 0;
-            for (ProtocolVersion version : protocols) {
-                protocolNames[i++] = version.name;
-            }
-        }
-        return protocolNames.clone();
-    }
-
-    public String toString() {
-        return protocols.toString();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java b/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java
deleted file mode 100755
index 77c102a..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-/**
- * Type safe enum for an SSL/TLS protocol version. Instances are obtained
- * using the static factory methods or by referencing the static members
- * in this class. Member variables are final and can be accessed without
- * accessor methods.
- *
- * There is only ever one instance per supported protocol version, this
- * means == can be used for comparision instead of equals() if desired.
- *
- * Checks for a particular version number should generally take this form:
- *
- * if (protocolVersion.v >= ProtocolVersion.TLS10) {
- *   // TLS 1.0 code goes here
- * } else {
- *   // SSL 3.0 code here
- * }
- *
- * @author  Andreas Sterbenz
- * @since   1.4.1
- */
-public final class ProtocolVersion implements Comparable<ProtocolVersion> {
-
-    // The limit of maximum protocol version
-    final static int LIMIT_MAX_VALUE = 0xFFFF;
-
-    // The limit of minimum protocol version
-    final static int LIMIT_MIN_VALUE = 0x0000;
-
-    // Dummy protocol version value for invalid SSLSession
-    final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
-
-    // If enabled, send/ accept SSLv2 hello messages
-    final static ProtocolVersion SSL20Hello = new ProtocolVersion(0x0002,
-                                                                "SSLv2Hello");
-
-    // SSL 3.0
-    final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3");
-
-    // TLS 1.0
-    final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
-
-    // TLS 1.1
-    final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
-
-    // TLS 1.2
-    final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
-
-    private static final boolean FIPS = SunJSSE.isFIPS();
-
-    // minimum version we implement (SSL 3.0)
-    final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
-
-    // maximum version we implement (TLS 1.2)
-    final static ProtocolVersion MAX = TLS12;
-
-    // ProtocolVersion to use by default (TLS 1.0)
-    final static ProtocolVersion DEFAULT = TLS10;
-
-    // Default version for hello messages (SSLv2Hello)
-    final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
-
-    // version in 16 bit MSB format as it appears in records and
-    // messages, i.e. 0x0301 for TLS 1.0
-    public final int v;
-
-    // major and minor version
-    public final byte major, minor;
-
-    // name used in JSSE (e.g. TLSv1 for TLS 1.0)
-    final String name;
-
-    // private
-    private ProtocolVersion(int v, String name) {
-        this.v = v;
-        this.name = name;
-        major = (byte)(v >>> 8);
-        minor = (byte)(v & 0xff);
-    }
-
-    // private
-    private static ProtocolVersion valueOf(int v) {
-        if (v == SSL30.v) {
-            return SSL30;
-        } else if (v == TLS10.v) {
-            return TLS10;
-        } else if (v == TLS11.v) {
-            return TLS11;
-        } else if (v == TLS12.v) {
-            return TLS12;
-        } else if (v == SSL20Hello.v) {
-            return SSL20Hello;
-        } else {
-            int major = (v >>> 8) & 0xff;
-            int minor = v & 0xff;
-            return new ProtocolVersion(v, "Unknown-" + major + "." + minor);
-        }
-    }
-
-    /**
-     * Return a ProtocolVersion with the specified major and minor version
-     * numbers. Never throws exceptions.
-     */
-    public static ProtocolVersion valueOf(int major, int minor) {
-        major &= 0xff;
-        minor &= 0xff;
-        int v = (major << 8) | minor;
-        return valueOf(v);
-    }
-
-    /**
-     * Return a ProtocolVersion for the given name.
-     *
-     * @exception IllegalArgumentException if name is null or does not
-     * identify a supported protocol
-     */
-    static ProtocolVersion valueOf(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Protocol cannot be null");
-        }
-
-        if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
-            throw new IllegalArgumentException
-                ("Only TLS 1.0 or later allowed in FIPS mode");
-        }
-
-        if (name.equals(SSL30.name)) {
-            return SSL30;
-        } else if (name.equals(TLS10.name)) {
-            return TLS10;
-        } else if (name.equals(TLS11.name)) {
-            return TLS11;
-        } else if (name.equals(TLS12.name)) {
-            return TLS12;
-        } else if (name.equals(SSL20Hello.name)) {
-            return SSL20Hello;
-        } else {
-            throw new IllegalArgumentException(name);
-        }
-    }
-
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * Compares this object with the specified object for order.
-     */
-    public int compareTo(ProtocolVersion protocolVersion) {
-        return this.v - protocolVersion.v;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java
deleted file mode 100755
index f8e501e..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.security.*;
-import java.security.interfaces.*;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
-import sun.security.util.KeyUtil;
-
-/**
- * This is the client key exchange message (CLIENT --> SERVER) used with
- * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
- *
- * The message is encrypted using PKCS #1 block type 02 encryption with the
- * server's public key.  The padding and resulting message size is a function
- * of this server's public key modulus size, but the pre-master secret is
- * always exactly 48 bytes.
- *
- */
-final class RSAClientKeyExchange extends HandshakeMessage {
-
-    /**
-     * The TLS spec says that the version in the RSA premaster secret must
-     * be the maximum version supported by the client (i.e. the version it
-     * requested in its client hello version). However, we (and other
-     * implementations) used to send the active negotiated version. The
-     * system property below allows to toggle the behavior.
-     */
-    private final static String PROP_NAME =
-                                "com.sun.net.ssl.rsaPreMasterSecretFix";
-
-    /*
-     * Default is "false" (old behavior) for compatibility reasons in
-     * SSLv3/TLSv1.  Later protocols (TLSv1.1+) do not use this property.
-     */
-    private final static boolean rsaPreMasterSecretFix =
-                                Debug.getBooleanProperty(PROP_NAME, false);
-
-    /*
-     * The following field values were encrypted with the server's public
-     * key (or temp key from server key exchange msg) and are presented
-     * here in DECRYPTED form.
-     */
-    private ProtocolVersion protocolVersion; // preMaster [0,1]
-    SecretKey preMaster;
-    private byte[] encrypted;           // same size as public modulus
-
-    /*
-     * Client randomly creates a pre-master secret and encrypts it
-     * using the server's RSA public key; only the server can decrypt
-     * it, using its RSA private key.  Result is the same size as the
-     * server's public key, and uses PKCS #1 block format 02.
-     */
-    RSAClientKeyExchange(ProtocolVersion protocolVersion,
-            ProtocolVersion maxVersion,
-            SecureRandom generator, PublicKey publicKey) throws IOException {
-        if (publicKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Public key not of type RSA");
-        }
-        this.protocolVersion = protocolVersion;
-
-        int major, minor;
-
-        if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
-            major = maxVersion.major;
-            minor = maxVersion.minor;
-        } else {
-            major = protocolVersion.major;
-            minor = protocolVersion.minor;
-        }
-
-        try {
-            String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
-                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
-            KeyGenerator kg = JsseJce.getKeyGenerator(s);
-            kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
-                    generator);
-            preMaster = kg.generateKey();
-
-            Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-            cipher.init(Cipher.WRAP_MODE, publicKey, generator);
-            encrypted = cipher.wrap(preMaster);
-        } catch (GeneralSecurityException e) {
-            throw (SSLKeyException)new SSLKeyException
-                                ("RSA premaster secret error").initCause(e);
-        }
-    }
-
-    /*
-     * Server gets the PKCS #1 (block format 02) data, decrypts
-     * it with its private key.
-     */
-    RSAClientKeyExchange(ProtocolVersion currentVersion,
-            ProtocolVersion maxVersion,
-            SecureRandom generator, HandshakeInStream input,
-            int messageSize, PrivateKey privateKey) throws IOException {
-
-        if (privateKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Private key not of type RSA");
-        }
-
-        if (currentVersion.v >= ProtocolVersion.TLS10.v) {
-            encrypted = input.getBytes16();
-        } else {
-            encrypted = new byte [messageSize];
-            if (input.read(encrypted) != messageSize) {
-                throw new SSLProtocolException
-                        ("SSL: read PreMasterSecret: short read");
-            }
-        }
-
-        try {
-            Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-            cipher.init(Cipher.UNWRAP_MODE, privateKey);
-            preMaster = (SecretKey)cipher.unwrap(encrypted,
-                                "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
-
-            // polish the premaster secret
-            preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
-                                                generator, preMaster, null);
-        } catch (Exception e) {
-            // polish the premaster secret
-            preMaster =
-                    polishPreMasterSecretKey(currentVersion, maxVersion,
-                                                generator, null, e);
-        }
-    }
-
-    /**
-     * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
-     * treating incorrectly formatted message blocks and/or mismatched
-     * version numbers in a manner indistinguishable from correctly
-     * formatted RSA blocks.
-     *
-     * RFC 5246 describes the approach as :
-     *
-     *  1. Generate a string R of 46 random bytes
-     *
-     *  2. Decrypt the message to recover the plaintext M
-     *
-     *  3. If the PKCS#1 padding is not correct, or the length of message
-     *     M is not exactly 48 bytes:
-     *        pre_master_secret = ClientHello.client_version || R
-     *     else If ClientHello.client_version <= TLS 1.0, and version
-     *     number check is explicitly disabled:
-     *        pre_master_secret = M
-     *     else:
-     *        pre_master_secret = ClientHello.client_version || M[2..47]
-     */
-    private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
-            ProtocolVersion clientHelloVersion, SecureRandom generator,
-            SecretKey secretKey, Exception failoverException) {
-
-        this.protocolVersion = clientHelloVersion;
-
-        if (failoverException == null && secretKey != null) {
-            // check the length
-            byte[] encoded = secretKey.getEncoded();
-            if (encoded == null) {      // unable to get the encoded key
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "unable to get the plaintext of the premaster secret");
-                }
-
-                int keySize = KeyUtil.getKeySize(secretKey);
-                if (keySize > 0 && keySize != 384) {       // 384 = 48 * 8
-                    if (debug != null && Debug.isOn("handshake")) {
-                        System.out.println(
-                            "incorrect length of premaster secret: " +
-                            (keySize/8));
-                    }
-
-                    return generateDummySecret(clientHelloVersion);
-                }
-
-                // The key size is exactly 48 bytes or not accessible.
-                //
-                // Conservatively, pass the checking to master secret
-                // calculation.
-                return secretKey;
-            } else if (encoded.length == 48) {
-                // check the version
-                if (clientHelloVersion.major == encoded[0] &&
-                    clientHelloVersion.minor == encoded[1]) {
-
-                    return secretKey;
-                } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
-                           currentVersion.major == encoded[0] &&
-                           currentVersion.minor == encoded[1]) {
-                    /*
-                     * For compatibility, we maintain the behavior that the
-                     * version in pre_master_secret can be the negotiated
-                     * version for TLS v1.0 and SSL v3.0.
-                     */
-                    this.protocolVersion = currentVersion;
-                    return secretKey;
-                }
-
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Mismatching Protocol Versions, " +
-                        "ClientHello.client_version is " + clientHelloVersion +
-                        ", while PreMasterSecret.client_version is " +
-                        ProtocolVersion.valueOf(encoded[0], encoded[1]));
-                }
-
-                return generateDummySecret(clientHelloVersion);
-            } else {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "incorrect length of premaster secret: " +
-                        encoded.length);
-                }
-
-                return generateDummySecret(clientHelloVersion);
-            }
-        }
-
-        if (debug != null && Debug.isOn("handshake") &&
-                    failoverException != null) {
-            System.out.println("Error decrypting premaster secret:");
-            failoverException.printStackTrace(System.out);
-        }
-
-        return generateDummySecret(clientHelloVersion);
-    }
-
-    // generate a premaster secret with the specified version number
-    static SecretKey generateDummySecret(ProtocolVersion version) {
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("Generating a random fake premaster secret");
-        }
-
-        try {
-            String s = ((version.v >= ProtocolVersion.TLS12.v) ?
-                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
-            KeyGenerator kg = JsseJce.getKeyGenerator(s);
-            kg.init(new TlsRsaPremasterSecretParameterSpec
-                    (version.major, version.minor));
-            return kg.generateKey();
-        } catch (GeneralSecurityException e) {
-            throw new RuntimeException("Could not generate dummy secret", e);
-        }
-    }
-
-    @Override
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
-    @Override
-    int messageLength() {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            return encrypted.length + 2;
-        } else {
-            return encrypted.length;
-        }
-    }
-
-    @Override
-    void send(HandshakeOutStream s) throws IOException {
-        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            s.putBytes16(encrypted);
-        } else {
-            s.write(encrypted);
-        }
-    }
-
-    @Override
-    void print(PrintStream s) throws IOException {
-        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
-                                                        protocolVersion);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RSASignature.java b/ojluni/src/main/java/sun/security/ssl/RSASignature.java
deleted file mode 100755
index 5b97bed..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RSASignature.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Arrays;
-
-import java.security.*;
-
-/**
- * Signature implementation for the SSL/TLS RSA Signature variant with both
- * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication
- * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client
- * authentication (RSA signed certificate verify message).
- *
- * It conforms to the standard JCA Signature API. It is registered in the
- * SunJSSE provider to avoid more complicated getInstance() code and
- * negative interaction with the JCA mechanisms for hardware providers.
- *
- * The class should be instantiated via the getInstance() method in this class,
- * which returns the implementation from the prefered provider. The internal
- * implementation allows the hashes to be explicitly set, which is required
- * for RSA client authentication. It can be obtained via the
- * getInternalInstance() method.
- *
- * This class is not thread safe.
- *
- */
-public final class RSASignature extends SignatureSpi {
-
-    private final Signature rawRsa;
-    private MessageDigest md5, sha;
-
-    // flag indicating if the MessageDigests are in reset state
-    private boolean isReset;
-
-    public RSASignature() throws NoSuchAlgorithmException {
-        super();
-        rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
-        isReset = true;
-    }
-
-    /**
-     * Get an implementation for the RSA signature. Follows the standard
-     * JCA getInstance() model, so it return the implementation from the
-     * provider with the highest precedence, which may be this class.
-     */
-    static Signature getInstance() throws NoSuchAlgorithmException {
-        return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA);
-    }
-
-    /**
-     * Get an internal implementation for the RSA signature. Used for RSA
-     * client authentication, which needs the ability to set the digests
-     * to externally provided values via the setHashes() method.
-     */
-    static Signature getInternalInstance()
-            throws NoSuchAlgorithmException, NoSuchProviderException {
-        return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE");
-    }
-
-    /**
-     * Set the MD5 and SHA hashes to the provided objects.
-     */
-    static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) {
-        sig.setParameter("hashes", new MessageDigest[] {md5, sha});
-    }
-
-    /**
-     * Reset the MessageDigests unless they are already reset.
-     */
-    private void reset() {
-        if (isReset == false) {
-            md5.reset();
-            sha.reset();
-            isReset = true;
-        }
-    }
-
-    private static void checkNull(Key key) throws InvalidKeyException {
-        if (key == null) {
-            throw new InvalidKeyException("Key must not be null");
-        }
-    }
-
-    protected void engineInitVerify(PublicKey publicKey)
-            throws InvalidKeyException {
-        checkNull(publicKey);
-        reset();
-        rawRsa.initVerify(publicKey);
-    }
-
-    protected void engineInitSign(PrivateKey privateKey)
-            throws InvalidKeyException {
-        engineInitSign(privateKey, null);
-    }
-
-    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
-            throws InvalidKeyException {
-        checkNull(privateKey);
-        reset();
-        rawRsa.initSign(privateKey, random);
-    }
-
-    // lazily initialize the MessageDigests
-    private void initDigests() {
-        if (md5 == null) {
-            md5 = JsseJce.getMD5();
-            sha = JsseJce.getSHA();
-        }
-    }
-
-    protected void engineUpdate(byte b) {
-        initDigests();
-        isReset = false;
-        md5.update(b);
-        sha.update(b);
-    }
-
-    protected void engineUpdate(byte[] b, int off, int len) {
-        initDigests();
-        isReset = false;
-        md5.update(b, off, len);
-        sha.update(b, off, len);
-    }
-
-    private byte[] getDigest() throws SignatureException {
-        try {
-            initDigests();
-            byte[] data = new byte[36];
-            md5.digest(data, 0, 16);
-            sha.digest(data, 16, 20);
-            isReset = true;
-            return data;
-        } catch (DigestException e) {
-            // should never occur
-            throw new SignatureException(e);
-        }
-    }
-
-    protected byte[] engineSign() throws SignatureException {
-        rawRsa.update(getDigest());
-        return rawRsa.sign();
-    }
-
-    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
-        return engineVerify(sigBytes, 0, sigBytes.length);
-    }
-
-    protected boolean engineVerify(byte[] sigBytes, int offset, int length)
-            throws SignatureException {
-        rawRsa.update(getDigest());
-        return rawRsa.verify(sigBytes, offset, length);
-    }
-
-    protected void engineSetParameter(String param, Object value)
-            throws InvalidParameterException {
-        if (param.equals("hashes") == false) {
-            throw new InvalidParameterException
-                ("Parameter not supported: " + param);
-        }
-        if (value instanceof MessageDigest[] == false) {
-            throw new InvalidParameterException
-                ("value must be MessageDigest[]");
-        }
-        MessageDigest[] digests = (MessageDigest[])value;
-        md5 = digests[0];
-        sha = digests[1];
-    }
-
-    protected Object engineGetParameter(String param)
-            throws InvalidParameterException {
-        throw new InvalidParameterException("Parameters not supported");
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RandomCookie.java b/ojluni/src/main/java/sun/security/ssl/RandomCookie.java
deleted file mode 100755
index 5f414c4..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RandomCookie.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.security.SecureRandom;
-
-/*
- * RandomCookie ... SSL hands standard format random cookies (nonces)
- * around.  These know how to encode/decode themselves on SSL streams,
- * and can be created and printed.
- *
- * @author David Brownell
- */
-final class RandomCookie {
-
-    byte random_bytes[];  // exactly 32 bytes
-
-    RandomCookie(SecureRandom generator) {
-        long temp = System.currentTimeMillis() / 1000;
-        int gmt_unix_time;
-        if (temp < Integer.MAX_VALUE) {
-            gmt_unix_time = (int) temp;
-        } else {
-            gmt_unix_time = Integer.MAX_VALUE;          // Whoops!
-        }
-
-        random_bytes = new byte[32];
-        generator.nextBytes(random_bytes);
-
-        random_bytes[0] = (byte)(gmt_unix_time >> 24);
-        random_bytes[1] = (byte)(gmt_unix_time >> 16);
-        random_bytes[2] = (byte)(gmt_unix_time >>  8);
-        random_bytes[3] = (byte)gmt_unix_time;
-    }
-
-    RandomCookie(HandshakeInStream m) throws IOException {
-        random_bytes = new byte[32];
-        m.read(random_bytes, 0, 32);
-    }
-
-    void send(HandshakeOutStream out) throws IOException {
-        out.write(random_bytes, 0, 32);
-    }
-
-    void print(PrintStream s) {
-        int i, gmt_unix_time;
-
-        gmt_unix_time = random_bytes[0] << 24;
-        gmt_unix_time += random_bytes[1] << 16;
-        gmt_unix_time += random_bytes[2] << 8;
-        gmt_unix_time += random_bytes[3];
-
-        s.print("GMT: " + gmt_unix_time + " ");
-        s.print("bytes = { ");
-
-        for (i = 4; i < 32; i++) {
-            if (i != 4) {
-                s.print(", ");
-            }
-            s.print(random_bytes[i] & 0x0ff);
-        }
-        s.println(" }");
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Record.java b/ojluni/src/main/java/sun/security/ssl/Record.java
deleted file mode 100755
index 0494d9a..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Record.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-
-/**
- * SSL/TLS records, as pulled off (and put onto) a TCP stream.  This is
- * the base interface, which defines common information and interfaces
- * used by both Input and Output records.
- *
- * @author David Brownell
- */
-interface Record {
-    /*
-     * There are four SSL record types, which are part of the interface
-     * to this level (along with the maximum record size)
-     *
-     * enum { change_cipher_spec(20), alert(21), handshake(22),
-     *      application_data(23), (255) } ContentType;
-     */
-    static final byte   ct_change_cipher_spec = 20;
-    static final byte   ct_alert = 21;
-    static final byte   ct_handshake = 22;
-    static final byte   ct_application_data = 23;
-
-    static final int    headerSize = 5;         // SSLv3 record header
-    static final int    maxExpansion = 1024;    // for bad compression
-    static final int    trailerSize = 20;       // SHA1 hash size
-    static final int    maxDataSize = 16384;    // 2^14 bytes of data
-    static final int    maxPadding = 256;       // block cipher padding
-    static final int    maxIVLength = 256;      // block length
-
-    /*
-     * SSL has a maximum record size.  It's header, (compressed) data,
-     * padding, and a trailer for the MAC.
-     * Some compression algorithms have rare cases where they expand the data.
-     * As we don't support compression at this time, leave that out.
-     */
-    static final int    maxRecordSize =
-                                      headerSize        // header
-                                    + maxIVLength       // iv
-                                    + maxDataSize       // data
-                                    + maxPadding        // padding
-                                    + trailerSize;      // MAC
-
-    static final boolean enableCBCProtection =
-            Debug.getBooleanProperty("jsse.enableCBCProtection", true);
-
-    /*
-     * For CBC protection in SSL3/TLS1, we break some plaintext into two
-     * packets.  Max application data size for the second packet.
-     */
-    static final int    maxDataSizeMinusOneByteRecord =
-                                  maxDataSize       // max data size
-                                - (                 // max one byte record size
-                                      headerSize    // header
-                                    + maxIVLength   // iv
-                                    + 1             // one byte data
-                                    + maxPadding    // padding
-                                    + trailerSize   // MAC
-                                  );
-
-    /*
-     * The maximum large record size.
-     *
-     * Some SSL/TLS implementations support large fragment upto 2^15 bytes,
-     * such as Microsoft. We support large incoming fragments.
-     *
-     * The maximum large record size is defined as maxRecordSize plus 2^14,
-     * this is the amount OpenSSL is using.
-     */
-    static final int    maxLargeRecordSize =
-                maxRecordSize   // Max size with a conforming implemenation
-              + maxDataSize;    // extra 2^14 bytes for large data packets.
-
-
-    /*
-     * Maximum record size for alert and change cipher spec records.
-     * They only contain 2 and 1 bytes of data, respectively.
-     * Allocate a smaller array.
-     */
-    static final int    maxAlertRecordSize =
-                                      headerSize        // header
-                                    + maxIVLength       // iv
-                                    + 2                 // alert
-                                    + maxPadding        // padding
-                                    + trailerSize;      // MAC
-
-    /*
-     * The overflow values of integers of 8, 16 and 24 bits.
-     */
-    static final int OVERFLOW_OF_INT08 = (1 << 8);
-    static final int OVERFLOW_OF_INT16 = (1 << 16);
-    static final int OVERFLOW_OF_INT24 = (1 << 24);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java b/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java
deleted file mode 100755
index 3980705..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (c) 2010, 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.security.ssl;
-
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AlgorithmParameters;
-
-import javax.net.ssl.*;
-
-import java.security.Key;
-
-import java.util.Set;
-import java.util.HashSet;
-
-import sun.security.util.DisabledAlgorithmConstraints;
-import sun.security.ssl.CipherSuite.*;
-
-/**
- * Algorithm constraints for disabled algorithms property
- *
- * See the "jdk.certpath.disabledAlgorithms" specification in java.security
- * for the syntax of the disabled algorithm string.
- */
-final class SSLAlgorithmConstraints implements AlgorithmConstraints {
-    private final static AlgorithmConstraints tlsDisabledAlgConstraints =
-            new TLSDisabledAlgConstraints();
-    private final static AlgorithmConstraints x509DisabledAlgConstraints =
-            new X509DisabledAlgConstraints();
-    private AlgorithmConstraints userAlgConstraints = null;
-    private AlgorithmConstraints peerAlgConstraints = null;
-
-    private boolean enabledX509DisabledAlgConstraints = true;
-
-    SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
-        userAlgConstraints = algorithmConstraints;
-    }
-
-    SSLAlgorithmConstraints(SSLSocket socket,
-            boolean withDefaultCertPathConstraints) {
-        if (socket != null) {
-            userAlgConstraints =
-                socket.getSSLParameters().getAlgorithmConstraints();
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLEngine engine,
-            boolean withDefaultCertPathConstraints) {
-        if (engine != null) {
-            userAlgConstraints =
-                engine.getSSLParameters().getAlgorithmConstraints();
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
-            boolean withDefaultCertPathConstraints) {
-        if (socket != null) {
-            userAlgConstraints =
-                socket.getSSLParameters().getAlgorithmConstraints();
-            peerAlgConstraints =
-                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
-            boolean withDefaultCertPathConstraints) {
-        if (engine != null) {
-            userAlgConstraints =
-                engine.getSSLParameters().getAlgorithmConstraints();
-            peerAlgConstraints =
-                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
-        }
-
-        if (!withDefaultCertPathConstraints) {
-            enabledX509DisabledAlgConstraints = false;
-        }
-    }
-
-    public boolean permits(Set<CryptoPrimitive> primitives,
-            String algorithm, AlgorithmParameters parameters) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(
-                                    primitives, algorithm, parameters);
-        }
-
-        return permitted;
-    }
-
-    public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(primitives, key);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(primitives, key);
-        }
-
-        return permitted;
-    }
-
-    public boolean permits(Set<CryptoPrimitive> primitives,
-            String algorithm, Key key, AlgorithmParameters parameters) {
-
-        boolean permitted = true;
-
-        if (peerAlgConstraints != null) {
-            permitted = peerAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted && userAlgConstraints != null) {
-            permitted = userAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted) {
-            permitted = tlsDisabledAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        if (permitted && enabledX509DisabledAlgConstraints) {
-            permitted = x509DisabledAlgConstraints.permits(
-                                    primitives, algorithm, key, parameters);
-        }
-
-        return permitted;
-    }
-
-
-    static private class SupportedSignatureAlgorithmConstraints
-                                    implements AlgorithmConstraints {
-        // supported signature algorithms
-        private String[] supportedAlgorithms;
-
-        SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
-            if (supportedAlgorithms != null) {
-                this.supportedAlgorithms = supportedAlgorithms.clone();
-            } else {
-                this.supportedAlgorithms = null;
-            }
-        }
-
-        public boolean permits(Set<CryptoPrimitive> primitives,
-                String algorithm, AlgorithmParameters parameters) {
-
-            if (algorithm == null || algorithm.length() == 0) {
-                throw new IllegalArgumentException(
-                        "No algorithm name specified");
-            }
-
-            if (primitives == null || primitives.isEmpty()) {
-                throw new IllegalArgumentException(
-                        "No cryptographic primitive specified");
-            }
-
-            if (supportedAlgorithms == null ||
-                        supportedAlgorithms.length == 0) {
-                return false;
-            }
-
-            // trim the MGF part: <digest>with<encryption>and<mgf>
-            int position = algorithm.indexOf("and");
-            if (position > 0) {
-                algorithm = algorithm.substring(0, position);
-            }
-
-            for (String supportedAlgorithm : supportedAlgorithms) {
-                if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
-            return true;
-        }
-
-        final public boolean permits(Set<CryptoPrimitive> primitives,
-                String algorithm, Key key, AlgorithmParameters parameters) {
-
-            if (algorithm == null || algorithm.length() == 0) {
-                throw new IllegalArgumentException(
-                        "No algorithm name specified");
-            }
-
-            return permits(primitives, algorithm, parameters);
-        }
-    }
-
-    static private class BasicDisabledAlgConstraints
-            extends DisabledAlgorithmConstraints {
-        BasicDisabledAlgConstraints(String propertyName) {
-            super(propertyName);
-        }
-
-        protected Set<String> decomposes(KeyExchange keyExchange,
-                        boolean forCertPathOnly) {
-            Set<String> components = new HashSet<>();
-            switch (keyExchange) {
-                case K_NULL:
-                    if (!forCertPathOnly) {
-                        components.add("NULL");
-                    }
-                    break;
-                case K_RSA:
-                    components.add("RSA");
-                    break;
-                case K_RSA_EXPORT:
-                    components.add("RSA");
-                    components.add("RSA_EXPORT");
-                    break;
-                case K_DH_RSA:
-                    components.add("RSA");
-                    components.add("DH");
-                    components.add("DiffieHellman");
-                    components.add("DH_RSA");
-                    break;
-                case K_DH_DSS:
-                    components.add("DSA");
-                    components.add("DSS");
-                    components.add("DH");
-                    components.add("DiffieHellman");
-                    components.add("DH_DSS");
-                    break;
-                case K_DHE_DSS:
-                    components.add("DSA");
-                    components.add("DSS");
-                    components.add("DH");
-                    components.add("DHE");
-                    components.add("DiffieHellman");
-                    components.add("DHE_DSS");
-                    break;
-                case K_DHE_RSA:
-                    components.add("RSA");
-                    components.add("DH");
-                    components.add("DHE");
-                    components.add("DiffieHellman");
-                    components.add("DHE_RSA");
-                    break;
-                case K_DH_ANON:
-                    if (!forCertPathOnly) {
-                        components.add("ANON");
-                        components.add("DH");
-                        components.add("DiffieHellman");
-                        components.add("DH_ANON");
-                    }
-                    break;
-                case K_ECDH_ECDSA:
-                    components.add("ECDH");
-                    components.add("ECDSA");
-                    components.add("ECDH_ECDSA");
-                    break;
-                case K_ECDH_RSA:
-                    components.add("ECDH");
-                    components.add("RSA");
-                    components.add("ECDH_RSA");
-                    break;
-                case K_ECDHE_ECDSA:
-                    components.add("ECDHE");
-                    components.add("ECDSA");
-                    components.add("ECDHE_ECDSA");
-                    break;
-                case K_ECDHE_RSA:
-                    components.add("ECDHE");
-                    components.add("RSA");
-                    components.add("ECDHE_RSA");
-                    break;
-                case K_ECDH_ANON:
-                    if (!forCertPathOnly) {
-                        components.add("ECDH");
-                        components.add("ANON");
-                        components.add("ECDH_ANON");
-                    }
-                    break;
-                case K_KRB5:
-                    if (!forCertPathOnly) {
-                        components.add("KRB5");
-                    }
-                    break;
-                case K_KRB5_EXPORT:
-                    if (!forCertPathOnly) {
-                        components.add("KRB5_EXPORT");
-                    }
-                    break;
-                default:
-                    // ignore
-            }
-
-            return components;
-        }
-
-        protected Set<String> decomposes(BulkCipher bulkCipher) {
-            Set<String> components = new HashSet<>();
-
-            if (bulkCipher.transformation != null) {
-                components.addAll(super.decomposes(bulkCipher.transformation));
-            }
-
-            return components;
-        }
-
-        protected Set<String> decomposes(MacAlg macAlg) {
-            Set<String> components = new HashSet<>();
-
-            if (macAlg == CipherSuite.M_MD5) {
-                components.add("MD5");
-                components.add("HmacMD5");
-            } else if (macAlg == CipherSuite.M_SHA) {
-                components.add("SHA1");
-                components.add("SHA-1");
-                components.add("HmacSHA1");
-            } else if (macAlg == CipherSuite.M_SHA256) {
-                components.add("SHA256");
-                components.add("SHA-256");
-                components.add("HmacSHA256");
-            } else if (macAlg == CipherSuite.M_SHA384) {
-                components.add("SHA384");
-                components.add("SHA-384");
-                components.add("HmacSHA384");
-            }
-
-            return components;
-        }
-    }
-
-    static private class TLSDisabledAlgConstraints
-            extends BasicDisabledAlgConstraints {
-
-        TLSDisabledAlgConstraints() {
-            super(DisabledAlgorithmConstraints.PROPERTY_TLS_DISABLED_ALGS);
-        }
-
-        @Override
-        protected Set<String> decomposes(String algorithm) {
-            if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
-                CipherSuite cipherSuite = null;
-                try {
-                    cipherSuite = CipherSuite.valueOf(algorithm);
-                } catch (IllegalArgumentException iae) {
-                    // ignore: unknown or unsupported ciphersuite
-                }
-
-                if (cipherSuite != null) {
-                    Set<String> components = new HashSet<>();
-
-                    if(cipherSuite.keyExchange != null) {
-                        components.addAll(
-                            decomposes(cipherSuite.keyExchange, false));
-                    }
-
-                    if (cipherSuite.cipher != null) {
-                        components.addAll(decomposes(cipherSuite.cipher));
-                    }
-
-                    if (cipherSuite.macAlg != null) {
-                        components.addAll(decomposes(cipherSuite.macAlg));
-                    }
-
-                    return components;
-                }
-            }
-
-            return super.decomposes(algorithm);
-        }
-    }
-
-    static private class X509DisabledAlgConstraints
-            extends BasicDisabledAlgConstraints {
-
-        X509DisabledAlgConstraints() {
-            super(DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
-        }
-
-        @Override
-        protected Set<String> decomposes(String algorithm) {
-            if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
-                CipherSuite cipherSuite = null;
-                try {
-                    cipherSuite = CipherSuite.valueOf(algorithm);
-                } catch (IllegalArgumentException iae) {
-                    // ignore: unknown or unsupported ciphersuite
-                }
-
-                if (cipherSuite != null) {
-                    Set<String> components = new HashSet<>();
-
-                    if(cipherSuite.keyExchange != null) {
-                        components.addAll(
-                            decomposes(cipherSuite.keyExchange, true));
-                    }
-
-                    // Certification path algorithm constraints do not apply
-                    // to cipherSuite.cipher and cipherSuite.macAlg.
-
-                    return components;
-                }
-            }
-
-            return super.decomposes(algorithm);
-        }
-    }
-}
-
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java
deleted file mode 100755
index c2081b7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.net.Socket;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-
-public abstract class SSLContextImpl extends SSLContextSpi {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private final EphemeralKeyManager ephemeralKeyManager;
-    private final SSLSessionContextImpl clientCache;
-    private final SSLSessionContextImpl serverCache;
-
-    private boolean isInitialized;
-
-    private X509ExtendedKeyManager keyManager;
-    private X509TrustManager trustManager;
-    private SecureRandom secureRandom;
-
-    // The default algrithm constraints
-    private AlgorithmConstraints defaultAlgorithmConstraints =
-                                 new SSLAlgorithmConstraints(null);
-
-    // supported and default protocols
-    private ProtocolList defaultServerProtocolList;
-    private ProtocolList defaultClientProtocolList;
-    private ProtocolList supportedProtocolList;
-
-    // supported and default cipher suites
-    private CipherSuiteList defaultServerCipherSuiteList;
-    private CipherSuiteList defaultClientCipherSuiteList;
-    private CipherSuiteList supportedCipherSuiteList;
-
-    SSLContextImpl() {
-        ephemeralKeyManager = new EphemeralKeyManager();
-        clientCache = new SSLSessionContextImpl();
-        serverCache = new SSLSessionContextImpl();
-    }
-
-    protected void engineInit(KeyManager[] km, TrustManager[] tm,
-                                SecureRandom sr) throws KeyManagementException {
-        isInitialized = false;
-        keyManager = chooseKeyManager(km);
-
-        if (tm == null) {
-            try {
-                TrustManagerFactory tmf = TrustManagerFactory.getInstance(
-                        TrustManagerFactory.getDefaultAlgorithm());
-                tmf.init((KeyStore)null);
-                tm = tmf.getTrustManagers();
-            } catch (Exception e) {
-                // eat
-            }
-        }
-        trustManager = chooseTrustManager(tm);
-
-        if (sr == null) {
-            secureRandom = JsseJce.getSecureRandom();
-        } else {
-            if (SunJSSE.isFIPS() &&
-                        (sr.getProvider() != SunJSSE.cryptoProvider)) {
-                throw new KeyManagementException
-                    ("FIPS mode: SecureRandom must be from provider "
-                    + SunJSSE.cryptoProvider.getName());
-            }
-            secureRandom = sr;
-        }
-
-        /*
-         * The initial delay of seeding the random number generator
-         * could be long enough to cause the initial handshake on our
-         * first connection to timeout and fail. Make sure it is
-         * primed and ready by getting some initial output from it.
-         */
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("trigger seeding of SecureRandom");
-        }
-        secureRandom.nextInt();
-        if (debug != null && Debug.isOn("sslctx")) {
-            System.out.println("done seeding SecureRandom");
-        }
-        isInitialized = true;
-    }
-
-    private X509TrustManager chooseTrustManager(TrustManager[] tm)
-            throws KeyManagementException {
-        // We only use the first instance of X509TrustManager passed to us.
-        for (int i = 0; tm != null && i < tm.length; i++) {
-            if (tm[i] instanceof X509TrustManager) {
-                if (SunJSSE.isFIPS() &&
-                        !(tm[i] instanceof X509TrustManagerImpl)) {
-                    throw new KeyManagementException
-                        ("FIPS mode: only SunJSSE TrustManagers may be used");
-                }
-
-                if (tm[i] instanceof X509ExtendedTrustManager) {
-                    return (X509TrustManager)tm[i];
-                } else {
-                    return new AbstractTrustManagerWrapper(
-                                        (X509TrustManager)tm[i]);
-                }
-            }
-        }
-
-        // nothing found, return a dummy X509TrustManager.
-        return DummyX509TrustManager.INSTANCE;
-    }
-
-    private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
-            throws KeyManagementException {
-        for (int i = 0; kms != null && i < kms.length; i++) {
-            KeyManager km = kms[i];
-            if (!(km instanceof X509KeyManager)) {
-                continue;
-            }
-            if (SunJSSE.isFIPS()) {
-                // In FIPS mode, require that one of SunJSSE's own keymanagers
-                // is used. Otherwise, we cannot be sure that only keys from
-                // the FIPS token are used.
-                if ((km instanceof X509KeyManagerImpl)
-                            || (km instanceof SunX509KeyManagerImpl)) {
-                    return (X509ExtendedKeyManager)km;
-                } else {
-                    // throw exception, we don't want to silently use the
-                    // dummy keymanager without telling the user.
-                    throw new KeyManagementException
-                        ("FIPS mode: only SunJSSE KeyManagers may be used");
-                }
-            }
-            if (km instanceof X509ExtendedKeyManager) {
-                return (X509ExtendedKeyManager)km;
-            }
-            if (debug != null && Debug.isOn("sslctx")) {
-                System.out.println(
-                    "X509KeyManager passed to " +
-                    "SSLContext.init():  need an " +
-                    "X509ExtendedKeyManager for SSLEngine use");
-            }
-            return new AbstractKeyManagerWrapper((X509KeyManager)km);
-        }
-
-        // nothing found, return a dummy X509ExtendedKeyManager
-        return DummyX509KeyManager.INSTANCE;
-    }
-
-    protected SSLSocketFactory engineGetSocketFactory() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-       return new SSLSocketFactoryImpl(this);
-    }
-
-    protected SSLServerSocketFactory engineGetServerSocketFactory() {
-        if (!isInitialized) {
-            throw new IllegalStateException("SSLContext is not initialized");
-        }
-        return new SSLServerSocketFactoryImpl(this);
-    }
-
-    protected SSLEngine engineCreateSSLEngine() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-        return new SSLEngineImpl(this);
-    }
-
-    protected SSLEngine engineCreateSSLEngine(String host, int port) {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                "SSLContextImpl is not initialized");
-        }
-        return new SSLEngineImpl(this, host, port);
-    }
-
-    protected SSLSessionContext engineGetClientSessionContext() {
-        return clientCache;
-    }
-
-    protected SSLSessionContext engineGetServerSessionContext() {
-        return serverCache;
-    }
-
-    SecureRandom getSecureRandom() {
-        return secureRandom;
-    }
-
-    X509ExtendedKeyManager getX509KeyManager() {
-        return keyManager;
-    }
-
-    X509TrustManager getX509TrustManager() {
-        return trustManager;
-    }
-
-    EphemeralKeyManager getEphemeralKeyManager() {
-        return ephemeralKeyManager;
-    }
-
-    abstract SSLParameters getDefaultServerSSLParams();
-    abstract SSLParameters getDefaultClientSSLParams();
-    abstract SSLParameters getSupportedSSLParams();
-
-    // Get suported ProtoclList.
-    ProtocolList getSuportedProtocolList() {
-        if (supportedProtocolList == null) {
-            supportedProtocolList =
-                new ProtocolList(getSupportedSSLParams().getProtocols());
-        }
-
-        return supportedProtocolList;
-    }
-
-    // Get default ProtoclList.
-    ProtocolList getDefaultProtocolList(boolean roleIsServer) {
-        if (roleIsServer) {
-            if (defaultServerProtocolList == null) {
-                defaultServerProtocolList = new ProtocolList(
-                        getDefaultServerSSLParams().getProtocols());
-            }
-
-            return defaultServerProtocolList;
-        } else {
-            if (defaultClientProtocolList == null) {
-                defaultClientProtocolList = new ProtocolList(
-                        getDefaultClientSSLParams().getProtocols());
-            }
-
-            return defaultClientProtocolList;
-        }
-    }
-
-    // Get suported CipherSuiteList.
-    CipherSuiteList getSupportedCipherSuiteList() {
-        // The maintenance of cipher suites needs to be synchronized.
-        synchronized (this) {
-            // Clear cache of available ciphersuites.
-            clearAvailableCache();
-
-            if (supportedCipherSuiteList == null) {
-                supportedCipherSuiteList = getApplicableCipherSuiteList(
-                        getSuportedProtocolList(), false);
-            }
-
-            return supportedCipherSuiteList;
-        }
-    }
-
-    // Get default CipherSuiteList.
-    CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
-        // The maintenance of cipher suites needs to be synchronized.
-        synchronized (this) {
-            // Clear cache of available ciphersuites.
-            clearAvailableCache();
-
-            if (roleIsServer) {
-                if (defaultServerCipherSuiteList == null) {
-                    defaultServerCipherSuiteList = getApplicableCipherSuiteList(
-                        getDefaultProtocolList(true), true);
-                }
-
-                return defaultServerCipherSuiteList;
-            } else {
-                if (defaultClientCipherSuiteList == null) {
-                    defaultClientCipherSuiteList = getApplicableCipherSuiteList(
-                        getDefaultProtocolList(false), true);
-                }
-
-                return defaultClientCipherSuiteList;
-            }
-        }
-    }
-
-    /**
-     * Return whether a protocol list is the original default enabled
-     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
-     */
-    boolean isDefaultProtocolList(ProtocolList protocols) {
-        return (protocols == defaultServerProtocolList) ||
-               (protocols == defaultClientProtocolList);
-    }
-
-
-    /*
-     * Return the list of all available CipherSuites with a priority of
-     * minPriority or above.
-     */
-    private CipherSuiteList getApplicableCipherSuiteList(
-            ProtocolList protocols, boolean onlyEnabled) {
-
-        int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
-        if (onlyEnabled) {
-            minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
-        }
-
-        Collection<CipherSuite> allowedCipherSuites =
-                                    CipherSuite.allowedCipherSuites();
-
-        TreeSet<CipherSuite> suites = new TreeSet<>();
-        if (!(protocols.collection().isEmpty()) &&
-                protocols.min.v != ProtocolVersion.NONE.v) {
-            for (CipherSuite suite : allowedCipherSuites) {
-                if (!suite.allowed || suite.priority < minPriority) {
-                    continue;
-                }
-
-                if (suite.isAvailable() &&
-                        suite.obsoleted > protocols.min.v &&
-                        suite.supported <= protocols.max.v) {
-                    if (defaultAlgorithmConstraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            suite.name, null)) {
-                        suites.add(suite);
-                    }
-                } else if (debug != null &&
-                        Debug.isOn("sslctx") && Debug.isOn("verbose")) {
-                    if (suite.obsoleted <= protocols.min.v) {
-                        System.out.println(
-                            "Ignoring obsoleted cipher suite: " + suite);
-                    } else if (suite.supported > protocols.max.v) {
-                        System.out.println(
-                            "Ignoring unsupported cipher suite: " + suite);
-                    } else {
-                        System.out.println(
-                            "Ignoring unavailable cipher suite: " + suite);
-                    }
-                }
-            }
-        }
-
-        return new CipherSuiteList(suites);
-    }
-
-    /**
-     * Clear cache of available ciphersuites. If we support all ciphers
-     * internally, there is no need to clear the cache and calling this
-     * method has no effect.
-     *
-     * Note that every call to clearAvailableCache() and the maintenance of
-     * cipher suites need to be synchronized with this instance.
-     */
-    private void clearAvailableCache() {
-        if (CipherSuite.DYNAMIC_AVAILABILITY) {
-            supportedCipherSuiteList = null;
-            defaultServerCipherSuiteList = null;
-            defaultClientCipherSuiteList = null;
-            CipherSuite.BulkCipher.clearAvailableCache();
-            JsseJce.clearEcAvailable();
-        }
-    }
-
-    /*
-     * The SSLContext implementation for TLS/SSL algorithm
-     *
-     * SSL/TLS protocols specify the forward compatibility and version
-     * roll-back attack protections, however, a number of SSL/TLS server
-     * vendors did not implement these aspects properly, and some current
-     * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
-     *
-     * Considering above interoperability issues, SunJSSE will not set
-     * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
-     *
-     * For SSL/TLS servers, there is no such interoperability issues as
-     * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
-     * enabled protocols for server by default.
-     *
-     * We may change the behavior when popular TLS/SSL vendors support TLS
-     * forward compatibility properly.
-     *
-     * SSLv2Hello is no longer necessary.  This interoperability option was
-     * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
-     * and there were a fair number of SSLv2-only servers deployed.  Because
-     * of the security issues in SSLv2, it is rarely (if ever) used, as
-     * deployments should now be using SSLv3 and TLSv1.
-     *
-     * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
-     * by default. Applications still can use it by enabling SSLv2Hello with
-     * the series of setEnabledProtocols APIs.
-     */
-
-    /*
-     * The conservative SSLContext implementation for TLS, SSL, SSLv3 and
-     * TLS10 algorithm.
-     *
-     * This is a super class of DefaultSSLContext and TLS10Context.
-     *
-     * @see SSLContext
-     */
-    private static class ConservativeSSLContext extends SSLContextImpl {
-        // parameters
-        private static SSLParameters defaultServerSSLParams;
-        private static SSLParameters defaultClientSSLParams;
-        private static SSLParameters supportedSSLParams;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name
-                });
-
-            } else {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL20Hello.name,
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name
-                });
-            }
-        }
-
-        SSLParameters getDefaultServerSSLParams() {
-            return defaultServerSSLParams;
-        }
-
-        SSLParameters getDefaultClientSSLParams() {
-            return defaultClientSSLParams;
-        }
-
-        SSLParameters getSupportedSSLParams() {
-            return supportedSSLParams;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for default algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class DefaultSSLContext extends ConservativeSSLContext {
-        private static final String NONE = "NONE";
-        private static final String P11KEYSTORE = "PKCS11";
-
-        private static volatile SSLContextImpl defaultImpl;
-
-        private static TrustManager[] defaultTrustManagers;
-        private static KeyManager[] defaultKeyManagers;
-
-        public DefaultSSLContext() throws Exception {
-            try {
-                super.engineInit(getDefaultKeyManager(),
-                        getDefaultTrustManager(), null);
-            } catch (Exception e) {
-                if (debug != null && Debug.isOn("defaultctx")) {
-                    System.out.println("default context init failed: " + e);
-                }
-                throw e;
-            }
-
-            if (defaultImpl == null) {
-                defaultImpl = this;
-            }
-        }
-
-        protected void engineInit(KeyManager[] km, TrustManager[] tm,
-            SecureRandom sr) throws KeyManagementException {
-            throw new KeyManagementException
-                ("Default SSLContext is initialized automatically");
-        }
-
-        static synchronized SSLContextImpl getDefaultImpl() throws Exception {
-            if (defaultImpl == null) {
-                new DefaultSSLContext();
-            }
-            return defaultImpl;
-        }
-
-        private static synchronized TrustManager[] getDefaultTrustManager()
-                throws Exception {
-            if (defaultTrustManagers != null) {
-                return defaultTrustManagers;
-            }
-
-            KeyStore ks =
-                TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
-
-            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
-                TrustManagerFactory.getDefaultAlgorithm());
-            tmf.init(ks);
-            defaultTrustManagers = tmf.getTrustManagers();
-            return defaultTrustManagers;
-        }
-
-        private static synchronized KeyManager[] getDefaultKeyManager()
-                throws Exception {
-            if (defaultKeyManagers != null) {
-                return defaultKeyManagers;
-            }
-
-            final Map<String,String> props = new HashMap<>();
-            AccessController.doPrivileged(
-                        new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    props.put("keyStore",  System.getProperty(
-                                "javax.net.ssl.keyStore", ""));
-                    props.put("keyStoreType", System.getProperty(
-                                "javax.net.ssl.keyStoreType",
-                                KeyStore.getDefaultType()));
-                    props.put("keyStoreProvider", System.getProperty(
-                                "javax.net.ssl.keyStoreProvider", ""));
-                    props.put("keyStorePasswd", System.getProperty(
-                                "javax.net.ssl.keyStorePassword", ""));
-                    return null;
-                }
-            });
-
-            final String defaultKeyStore = props.get("keyStore");
-            String defaultKeyStoreType = props.get("keyStoreType");
-            String defaultKeyStoreProvider = props.get("keyStoreProvider");
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("keyStore is : " + defaultKeyStore);
-                System.out.println("keyStore type is : " +
-                                        defaultKeyStoreType);
-                System.out.println("keyStore provider is : " +
-                                        defaultKeyStoreProvider);
-            }
-
-            if (P11KEYSTORE.equals(defaultKeyStoreType) &&
-                    !NONE.equals(defaultKeyStore)) {
-                throw new IllegalArgumentException("if keyStoreType is "
-                    + P11KEYSTORE + ", then keyStore must be " + NONE);
-            }
-
-            FileInputStream fs = null;
-            if (defaultKeyStore.length() != 0 && !NONE.equals(defaultKeyStore)) {
-                fs = AccessController.doPrivileged(
-                        new PrivilegedExceptionAction<FileInputStream>() {
-                    public FileInputStream run() throws Exception {
-                        return new FileInputStream(defaultKeyStore);
-                    }
-                });
-            }
-
-            String defaultKeyStorePassword = props.get("keyStorePasswd");
-            char[] passwd = null;
-            if (defaultKeyStorePassword.length() != 0) {
-                passwd = defaultKeyStorePassword.toCharArray();
-            }
-
-            /**
-             * Try to initialize key store.
-             */
-            KeyStore ks = null;
-            if ((defaultKeyStoreType.length()) != 0) {
-                if (debug != null && Debug.isOn("defaultctx")) {
-                    System.out.println("init keystore");
-                }
-                if (defaultKeyStoreProvider.length() == 0) {
-                    ks = KeyStore.getInstance(defaultKeyStoreType);
-                } else {
-                    ks = KeyStore.getInstance(defaultKeyStoreType,
-                                        defaultKeyStoreProvider);
-                }
-
-                // if defaultKeyStore is NONE, fs will be null
-                ks.load(fs, passwd);
-            }
-            if (fs != null) {
-                fs.close();
-                fs = null;
-            }
-
-            /*
-             * Try to initialize key manager.
-             */
-            if (debug != null && Debug.isOn("defaultctx")) {
-                System.out.println("init keymanager of type " +
-                    KeyManagerFactory.getDefaultAlgorithm());
-            }
-            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
-                KeyManagerFactory.getDefaultAlgorithm());
-
-            if (P11KEYSTORE.equals(defaultKeyStoreType)) {
-                kmf.init(ks, null); // do not pass key passwd if using token
-            } else {
-                kmf.init(ks, passwd);
-            }
-
-            defaultKeyManagers = kmf.getKeyManagers();
-            return defaultKeyManagers;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for TLS, SSL, SSLv3 and TLS10 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS10Context extends ConservativeSSLContext {
-        // use the default constructor and methods
-    }
-
-    /*
-     * The SSLContext implementation for TLS11 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS11Context extends SSLContextImpl {
-        // parameters
-        private static SSLParameters defaultServerSSLParams;
-        private static SSLParameters defaultClientSSLParams;
-        private static SSLParameters supportedSSLParams;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name
-                });
-
-            } else {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL20Hello.name,
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name
-                });
-            }
-        }
-
-        SSLParameters getDefaultServerSSLParams() {
-            return defaultServerSSLParams;
-        }
-
-        SSLParameters getDefaultClientSSLParams() {
-            return defaultClientSSLParams;
-        }
-
-        SSLParameters getSupportedSSLParams() {
-            return supportedSSLParams;
-        }
-    }
-
-    /*
-     * The SSLContext implementation for TLS12 algorithm
-     *
-     * @see SSLContext
-     */
-    public static final class TLS12Context extends SSLContextImpl {
-        // parameters
-        private static SSLParameters defaultServerSSLParams;
-        private static SSLParameters defaultClientSSLParams;
-        private static SSLParameters supportedSSLParams;
-
-        static {
-            if (SunJSSE.isFIPS()) {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-            } else {
-                supportedSSLParams = new SSLParameters();
-                supportedSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL20Hello.name,
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-
-                defaultServerSSLParams = supportedSSLParams;
-
-                defaultClientSSLParams = new SSLParameters();
-                defaultClientSSLParams.setProtocols(new String[] {
-                    ProtocolVersion.SSL30.name,
-                    ProtocolVersion.TLS10.name,
-                    ProtocolVersion.TLS11.name,
-                    ProtocolVersion.TLS12.name
-                });
-            }
-        }
-
-        SSLParameters getDefaultServerSSLParams() {
-            return defaultServerSSLParams;
-        }
-
-        SSLParameters getDefaultClientSSLParams() {
-            return defaultClientSSLParams;
-        }
-
-        SSLParameters getSupportedSSLParams() {
-            return supportedSSLParams;
-        }
-    }
-
-}
-
-
-final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
-            implements X509TrustManager {
-
-    // the delegated trust manager
-    private final X509TrustManager tm;
-
-    AbstractTrustManagerWrapper(X509TrustManager tm) {
-        this.tm = tm;
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-    }
-
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        return tm.getAcceptedIssuers();
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, socket, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, socket, false);
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        tm.checkClientTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, engine, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        tm.checkServerTrusted(chain, authType);
-        checkAdditionalTrust(chain, authType, engine, false);
-    }
-
-    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
-                Socket socket, boolean isClient) throws CertificateException {
-        if (socket != null && socket.isConnected() &&
-                                    socket instanceof SSLSocket) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = sslSocket.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                String hostname = session.getPeerHost();
-                X509TrustManagerImpl.checkIdentity(
-                                    hostname, chain[0], identityAlg);
-            }
-
-            // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] peerSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    sslSocket, peerSupportedSignAlgs, true);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(sslSocket, true);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(sslSocket, true);
-            }
-
-            checkAlgorithmConstraints(chain, constraints);
-        }
-    }
-
-    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
-            SSLEngine engine, boolean isClient) throws CertificateException {
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = engine.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                String hostname = session.getPeerHost();
-                X509TrustManagerImpl.checkIdentity(
-                                    hostname, chain[0], identityAlg);
-            }
-
-            // try the best to check the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            AlgorithmConstraints constraints = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] peerSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    engine, peerSupportedSignAlgs, true);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(engine, true);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(engine, true);
-            }
-
-            checkAlgorithmConstraints(chain, constraints);
-        }
-    }
-
-    private void checkAlgorithmConstraints(X509Certificate[] chain,
-            AlgorithmConstraints constraints) throws CertificateException {
-
-        try {
-            // Does the certificate chain end with a trusted certificate?
-            int checkedLength = chain.length - 1;
-
-            Collection<X509Certificate> trustedCerts = new HashSet<>();
-            X509Certificate[] certs = tm.getAcceptedIssuers();
-            if ((certs != null) && (certs.length > 0)){
-                Collections.addAll(trustedCerts, certs);
-            }
-
-            if (trustedCerts.contains(chain[checkedLength])) {
-                    checkedLength--;
-            }
-
-            // A forward checker, need to check from trust to target
-            if (checkedLength >= 0) {
-                AlgorithmChecker checker = new AlgorithmChecker(constraints);
-                checker.init(false);
-                for (int i = checkedLength; i >= 0; i--) {
-                    Certificate cert = chain[i];
-                    // We don't care about the unresolved critical extensions.
-                    checker.check(cert, Collections.<String>emptySet());
-                }
-            }
-        } catch (CertPathValidatorException cpve) {
-            throw new CertificateException(
-                "Certificates does not conform to algorithm constraints");
-        }
-    }
-}
-
-// Dummy X509TrustManager implementation, rejects all peer certificates.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509TrustManager extends X509ExtendedTrustManager
-            implements X509TrustManager {
-
-    static final X509TrustManager INSTANCE = new DummyX509TrustManager();
-
-    private DummyX509TrustManager() {
-        // empty
-    }
-
-    /*
-     * Given the partial or complete certificate chain
-     * provided by the peer, build a certificate path
-     * to a trusted root and return if it can be
-     * validated and is trusted for client SSL authentication.
-     * If not, it throws an exception.
-     */
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation avaiable");
-    }
-
-    /*
-     * Given the partial or complete certificate chain
-     * provided by the peer, build a certificate path
-     * to a trusted root and return if it can be
-     * validated and is trusted for server SSL authentication.
-     * If not, it throws an exception.
-     */
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType)
-        throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    /*
-     * Return an array of issuer certificates which are trusted
-     * for authenticating peers.
-     */
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        return new X509Certificate[0];
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        throw new CertificateException(
-            "No X509TrustManager implementation available");
-    }
-}
-
-/*
- * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
- */
-final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
-
-    private final X509KeyManager km;
-
-    AbstractKeyManagerWrapper(X509KeyManager km) {
-        this.km = km;
-    }
-
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return km.getClientAliases(keyType, issuers);
-    }
-
-    public String chooseClientAlias(String[] keyType, Principal[] issuers,
-            Socket socket) {
-        return km.chooseClientAlias(keyType, issuers, socket);
-    }
-
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return km.getServerAliases(keyType, issuers);
-    }
-
-    public String chooseServerAlias(String keyType, Principal[] issuers,
-            Socket socket) {
-        return km.chooseServerAlias(keyType, issuers, socket);
-    }
-
-    public X509Certificate[] getCertificateChain(String alias) {
-        return km.getCertificateChain(alias);
-    }
-
-    public PrivateKey getPrivateKey(String alias) {
-        return km.getPrivateKey(alias);
-    }
-
-    // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
-    // X509ExtendedKeymanager. It defines them to return null;
-}
-
-
-// Dummy X509KeyManager implementation, never returns any certificates/keys.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509KeyManager extends X509ExtendedKeyManager {
-
-    static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
-
-    private DummyX509KeyManager() {
-        // empty
-    }
-
-    /*
-     * Get the matching aliases for authenticating the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of an
-     * engine given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseEngineClientAlias(
-            String[] keyTypes, Principal[] issuers, SSLEngine engine) {
-        return null;
-    }
-
-    /*
-     * Get the matching aliases for authenticating the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseServerAlias(String keyType, Principal[] issuers,
-            Socket socket) {
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of an engine
-     * given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseEngineServerAlias(
-            String keyType, Principal[] issuers, SSLEngine engine) {
-        return null;
-    }
-
-    /**
-     * Returns the certificate chain associated with the given alias.
-     *
-     * @param alias the alias name
-     *
-     * @return the certificate chain (ordered with the user's certificate first
-     * and the root certificate authority last)
-     */
-    public X509Certificate[] getCertificateChain(String alias) {
-        return null;
-    }
-
-    /*
-     * Returns the key associated with the given alias, using the given
-     * password to recover it.
-     *
-     * @param alias the alias name
-     *
-     * @return the requested key
-     */
-    public PrivateKey getPrivateKey(String alias) {
-        return null;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java
deleted file mode 100755
index afcbd51..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java
+++ /dev/null
@@ -1,2087 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.nio.ReadOnlyBufferException;
-import java.util.LinkedList;
-import java.security.*;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-import javax.net.ssl.SSLEngineResult.*;
-
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
-/**
- * Implementation of an non-blocking SSLEngine.
- *
- * *Currently*, the SSLEngine code exists in parallel with the current
- * SSLSocket.  As such, the current implementation is using legacy code
- * with many of the same abstractions.  However, it varies in many
- * areas, most dramatically in the IO handling.
- *
- * There are three main I/O threads that can be existing in parallel:
- * wrap(), unwrap(), and beginHandshake().  We are encouraging users to
- * not call multiple instances of wrap or unwrap, because the data could
- * appear to flow out of the SSLEngine in a non-sequential order.  We
- * take all steps we can to at least make sure the ordering remains
- * consistent, but once the calls returns, anything can happen.  For
- * example, thread1 and thread2 both call wrap, thread1 gets the first
- * packet, thread2 gets the second packet, but thread2 gets control back
- * before thread1, and sends the data.  The receiving side would see an
- * out-of-order error.
- *
- * Handshaking is still done the same way as SSLSocket using the normal
- * InputStream/OutputStream abstactions.  We create
- * ClientHandshakers/ServerHandshakers, which produce/consume the
- * handshaking data.  The transfer of the data is largely handled by the
- * HandshakeInStream/HandshakeOutStreams.  Lastly, the
- * InputRecord/OutputRecords still have the same functionality, except
- * that they are overridden with EngineInputRecord/EngineOutputRecord,
- * which provide SSLEngine-specific functionality.
- *
- * Some of the major differences are:
- *
- * EngineInputRecord/EngineOutputRecord/EngineWriter:
- *
- *      In order to avoid writing whole new control flows for
- *      handshaking, and to reuse most of the same code, we kept most
- *      of the actual handshake code the same.  As usual, reading
- *      handshake data may trigger output of more handshake data, so
- *      what we do is write this data to internal buffers, and wait for
- *      wrap() to be called to give that data a ride.
- *
- *      All data is routed through
- *      EngineInputRecord/EngineOutputRecord.  However, all handshake
- *      data (ct_alert/ct_change_cipher_spec/ct_handshake) are passed
- *      through to the the underlying InputRecord/OutputRecord, and
- *      the data uses the internal buffers.
- *
- *      Application data is handled slightly different, we copy the data
- *      directly from the src to the dst buffers, and do all operations
- *      on those buffers, saving the overhead of multiple copies.
- *
- *      In the case of an inbound record, unwrap passes the inbound
- *      ByteBuffer to the InputRecord.  If the data is handshake data,
- *      the data is read into the InputRecord's internal buffer.  If
- *      the data is application data, the data is decoded directly into
- *      the dst buffer.
- *
- *      In the case of an outbound record, when the write to the
- *      "real" OutputStream's would normally take place, instead we
- *      call back up to the EngineOutputRecord's version of
- *      writeBuffer, at which time we capture the resulting output in a
- *      ByteBuffer, and send that back to the EngineWriter for internal
- *      storage.
- *
- *      EngineWriter is responsible for "handling" all outbound
- *      data, be it handshake or app data, and for returning the data
- *      to wrap() in the proper order.
- *
- * ClientHandshaker/ServerHandshaker/Handshaker:
- *      Methods which relied on SSLSocket now have work on either
- *      SSLSockets or SSLEngines.
- *
- * @author Brad Wetmore
- */
-final public class SSLEngineImpl extends SSLEngine {
-
-    //
-    // Fields and global comments
-    //
-
-    /*
-     * There's a state machine associated with each connection, which
-     * among other roles serves to negotiate session changes.
-     *
-     * - START with constructor, until the TCP connection's around.
-     * - HANDSHAKE picks session parameters before allowing traffic.
-     *          There are many substates due to sequencing requirements
-     *          for handshake messages.
-     * - DATA may be transmitted.
-     * - RENEGOTIATE state allows concurrent data and handshaking
-     *          traffic ("same" substates as HANDSHAKE), and terminates
-     *          in selection of new session (and connection) parameters
-     * - ERROR state immediately precedes abortive disconnect.
-     * - CLOSED when one side closes down, used to start the shutdown
-     *          process.  SSL connection objects are not reused.
-     *
-     * State affects what SSL record types may legally be sent:
-     *
-     * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
-     * - App Data ... only in DATA and RENEGOTIATE states
-     * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
-     *
-     * Re what may be received:  same as what may be sent, except that
-     * HandshakeRequest handshaking messages can come from servers even
-     * in the application data state, to request entry to RENEGOTIATE.
-     *
-     * The state machine within HANDSHAKE and RENEGOTIATE states controls
-     * the pending session, not the connection state, until the change
-     * cipher spec and "Finished" handshake messages are processed and
-     * make the "new" session become the current one.
-     *
-     * NOTE: details of the SMs always need to be nailed down better.
-     * The text above illustrates the core ideas.
-     *
-     *                +---->-------+------>--------->-------+
-     *                |            |                        |
-     *     <-----<    ^            ^  <-----<               |
-     *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE    |
-     *                v            v               v        |
-     *                |            |               |        |
-     *                +------------+---------------+        |
-     *                |                                     |
-     *                v                                     |
-     *               ERROR>------>----->CLOSED<--------<----+
-     *
-     * ALSO, note that the the purpose of handshaking (renegotiation is
-     * included) is to assign a different, and perhaps new, session to
-     * the connection.  The SSLv3 spec is a bit confusing on that new
-     * protocol feature.
-     */
-    private int                 connectionState;
-
-    private static final int    cs_START = 0;
-    private static final int    cs_HANDSHAKE = 1;
-    private static final int    cs_DATA = 2;
-    private static final int    cs_RENEGOTIATE = 3;
-    private static final int    cs_ERROR = 4;
-    private static final int    cs_CLOSED = 6;
-
-    /*
-     * Once we're in state cs_CLOSED, we can continue to
-     * wrap/unwrap until we finish sending/receiving the messages
-     * for close_notify.  EngineWriter handles outboundDone.
-     */
-    private boolean             inboundDone = false;
-
-    EngineWriter                writer;
-
-    /*
-     * The authentication context holds all information used to establish
-     * who this end of the connection is (certificate chains, private keys,
-     * etc) and who is trusted (e.g. as CAs or websites).
-     */
-    private SSLContextImpl      sslContext;
-
-    /*
-     * This connection is one of (potentially) many associated with
-     * any given session.  The output of the handshake protocol is a
-     * new session ... although all the protocol description talks
-     * about changing the cipher spec (and it does change), in fact
-     * that's incidental since it's done by changing everything that
-     * is associated with a session at the same time.  (TLS/IETF may
-     * change that to add client authentication w/o new key exchg.)
-     */
-    private Handshaker                  handshaker;
-    private SSLSessionImpl              sess;
-    private volatile SSLSessionImpl     handshakeSession;
-
-
-    /*
-     * Client authentication be off, requested, or required.
-     *
-     * This will be used by both this class and SSLSocket's variants.
-     */
-    static final byte           clauth_none = 0;
-    static final byte           clauth_requested = 1;
-    static final byte           clauth_required = 2;
-
-    /*
-     * Flag indicating if the next record we receive MUST be a Finished
-     * message. Temporarily set during the handshake to ensure that
-     * a change cipher spec message is followed by a finished message.
-     */
-    private boolean             expectingFinished;
-
-
-    /*
-     * If someone tries to closeInbound() (say at End-Of-Stream)
-     * our engine having received a close_notify, we need to
-     * notify the app that we may have a truncation attack underway.
-     */
-    private boolean             recvCN;
-
-    /*
-     * For improved diagnostics, we detail connection closure
-     * If the engine is closed (connectionState >= cs_ERROR),
-     * closeReason != null indicates if the engine was closed
-     * because of an error or because or normal shutdown.
-     */
-    private SSLException        closeReason;
-
-    /*
-     * Per-connection private state that doesn't change when the
-     * session is changed.
-     */
-    private byte                        doClientAuth;
-    private boolean                     enableSessionCreation = true;
-    EngineInputRecord                   inputRecord;
-    EngineOutputRecord                  outputRecord;
-    private AccessControlContext        acc;
-
-    // The cipher suites enabled for use on this connection.
-    private CipherSuiteList             enabledCipherSuites;
-
-    // the endpoint identification protocol
-    private String                      identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints        algorithmConstraints = null;
-
-    // Have we been told whether we're client or server?
-    private boolean                     serverModeSet = false;
-    private boolean                     roleIsServer;
-
-    /*
-     * The protocol versions enabled for use on this connection.
-     *
-     * Note: we support a pseudo protocol called SSLv2Hello which when
-     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
-     * or TLS (version 3.1, 3.2, etc.) version info.
-     */
-    private ProtocolList        enabledProtocols;
-
-    /*
-     * The SSL version associated with this connection.
-     */
-    private ProtocolVersion     protocolVersion = ProtocolVersion.DEFAULT;
-
-    /*
-     * Crypto state that's reinitialized when the session changes.
-     */
-    private MAC                 readMAC, writeMAC;
-    private CipherBox           readCipher, writeCipher;
-    // NOTE: compression state would be saved here
-
-    /*
-     * security parameters for secure renegotiation.
-     */
-    private boolean             secureRenegotiation;
-    private byte[]              clientVerifyData;
-    private byte[]              serverVerifyData;
-
-    /*
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     *
-     * There are several locks here.
-     *
-     * The primary lock is the per-instance lock used by
-     * synchronized(this) and the synchronized methods.  It controls all
-     * access to things such as the connection state and variables which
-     * affect handshaking.  If we are inside a synchronized method, we
-     * can access the state directly, otherwise, we must use the
-     * synchronized equivalents.
-     *
-     * Note that we must never acquire the <code>this</code> lock after
-     * <code>writeLock</code> or run the risk of deadlock.
-     *
-     * Grab some coffee, and be careful with any code changes.
-     */
-    private Object              wrapLock;
-    private Object              unwrapLock;
-    Object                      writeLock;
-
-    /*
-     * Is it the first application record to write?
-     */
-    private boolean isFirstAppOutputRecord = true;
-
-    /*
-     * Class and subclass dynamic debugging support
-     */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    //
-    // Initialization/Constructors
-    //
-
-    /**
-     * Constructor for an SSLEngine from SSLContext, without
-     * host/port hints.  This Engine will not be able to cache
-     * sessions, but must renegotiate everything by hand.
-     */
-    SSLEngineImpl(SSLContextImpl ctx) {
-        super();
-        init(ctx);
-    }
-
-    /**
-     * Constructor for an SSLEngine from SSLContext.
-     */
-    SSLEngineImpl(SSLContextImpl ctx, String host, int port) {
-        super(host, port);
-        init(ctx);
-    }
-
-    /**
-     * Initializes the Engine
-     */
-    private void init(SSLContextImpl ctx) {
-        if (debug != null && Debug.isOn("ssl")) {
-            System.out.println("Using SSLEngineImpl.");
-        }
-
-        sslContext = ctx;
-        sess = SSLSessionImpl.nullSession;
-        handshakeSession = null;
-
-        /*
-         * State is cs_START until we initialize the handshaker.
-         *
-         * Apps using SSLEngine are probably going to be server.
-         * Somewhat arbitrary choice.
-         */
-        roleIsServer = true;
-        connectionState = cs_START;
-
-        /*
-         * default read and write side cipher and MAC support
-         *
-         * Note:  compression support would go here too
-         */
-        readCipher = CipherBox.NULL;
-        readMAC = MAC.NULL;
-        writeCipher = CipherBox.NULL;
-        writeMAC = MAC.NULL;
-
-        // default security parameters for secure renegotiation
-        secureRenegotiation = false;
-        clientVerifyData = new byte[0];
-        serverVerifyData = new byte[0];
-
-        enabledCipherSuites =
-                sslContext.getDefaultCipherSuiteList(roleIsServer);
-        enabledProtocols =
-                sslContext.getDefaultProtocolList(roleIsServer);
-
-        wrapLock = new Object();
-        unwrapLock = new Object();
-        writeLock = new Object();
-
-        /*
-         * Save the Access Control Context.  This will be used later
-         * for a couple of things, including providing a context to
-         * run tasks in, and for determining which credentials
-         * to use for Subject based (JAAS) decisions
-         */
-        acc = AccessController.getContext();
-
-        /*
-         * All outbound application data goes through this OutputRecord,
-         * other data goes through their respective records created
-         * elsewhere.  All inbound data goes through this one
-         * input record.
-         */
-        outputRecord =
-            new EngineOutputRecord(Record.ct_application_data, this);
-        inputRecord = new EngineInputRecord(this);
-        inputRecord.enableFormatChecks();
-
-        writer = new EngineWriter();
-    }
-
-    /**
-     * Initialize the handshaker object. This means:
-     *
-     *  . if a handshake is already in progress (state is cs_HANDSHAKE
-     *    or cs_RENEGOTIATE), do nothing and return
-     *
-     *  . if the engine is already closed, throw an Exception (internal error)
-     *
-     *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object and advance the connection state (to cs_HANDSHAKE or
-     *    cs_RENEGOTIATE, respectively).
-     *
-     * This method is called right after a new engine is created, when
-     * starting renegotiation, or when changing client/server mode of the
-     * engine.
-     */
-    private void initHandshaker() {
-        switch (connectionState) {
-
-        //
-        // Starting a new handshake.
-        //
-        case cs_START:
-        case cs_DATA:
-            break;
-
-        //
-        // We're already in the middle of a handshake.
-        //
-        case cs_HANDSHAKE:
-        case cs_RENEGOTIATE:
-            return;
-
-        //
-        // Anyone allowed to call this routine is required to
-        // do so ONLY if the connection state is reasonable...
-        //
-        default:
-            throw new IllegalStateException("Internal error");
-        }
-
-        // state is either cs_START or cs_DATA
-        if (connectionState == cs_START) {
-            connectionState = cs_HANDSHAKE;
-        } else { // cs_DATA
-            connectionState = cs_RENEGOTIATE;
-        }
-        if (roleIsServer) {
-            handshaker = new ServerHandshaker(this, sslContext,
-                    enabledProtocols, doClientAuth,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-        } else {
-            handshaker = new ClientHandshaker(this, sslContext,
-                    enabledProtocols,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-        }
-        handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        handshaker.setEnableSessionCreation(enableSessionCreation);
-    }
-
-    /*
-     * Report the current status of the Handshaker
-     */
-    private HandshakeStatus getHSStatus(HandshakeStatus hss) {
-
-        if (hss != null) {
-            return hss;
-        }
-
-        synchronized (this) {
-            if (writer.hasOutboundData()) {
-                return HandshakeStatus.NEED_WRAP;
-            } else if (handshaker != null) {
-                if (handshaker.taskOutstanding()) {
-                    return HandshakeStatus.NEED_TASK;
-                } else {
-                    return HandshakeStatus.NEED_UNWRAP;
-                }
-            } else if (connectionState == cs_CLOSED) {
-                /*
-                 * Special case where we're closing, but
-                 * still need the close_notify before we
-                 * can officially be closed.
-                 *
-                 * Note isOutboundDone is taken care of by
-                 * hasOutboundData() above.
-                 */
-                if (!isInboundDone()) {
-                    return HandshakeStatus.NEED_UNWRAP;
-                } // else not handshaking
-            }
-
-            return HandshakeStatus.NOT_HANDSHAKING;
-        }
-    }
-
-    synchronized private void checkTaskThrown() throws SSLException {
-        if (handshaker != null) {
-            handshaker.checkThrown();
-        }
-    }
-
-    //
-    // Handshaking and connection state code
-    //
-
-    /*
-     * Provides "this" synchronization for connection state.
-     * Otherwise, you can access it directly.
-     */
-    synchronized private int getConnectionState() {
-        return connectionState;
-    }
-
-    synchronized private void setConnectionState(int state) {
-        connectionState = state;
-    }
-
-    /*
-     * Get the Access Control Context.
-     *
-     * Used for a known context to
-     * run tasks in, and for determining which credentials
-     * to use for Subject-based (JAAS) decisions.
-     */
-    AccessControlContext getAcc() {
-        return acc;
-    }
-
-    /*
-     * Is a handshake currently underway?
-     */
-    public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
-        return getHSStatus(null);
-    }
-
-    /*
-     * When a connection finishes handshaking by enabling use of a newly
-     * negotiated session, each end learns about it in two halves (read,
-     * and write).  When both read and write ciphers have changed, and the
-     * last handshake message has been read, the connection has joined
-     * (rejoined) the new session.
-     *
-     * NOTE:  The SSLv3 spec is rather unclear on the concepts here.
-     * Sessions don't change once they're established (including cipher
-     * suite and master secret) but connections can join them (and leave
-     * them).  They're created by handshaking, though sometime handshaking
-     * causes connections to join up with pre-established sessions.
-     *
-     * Synchronized on "this" from readRecord.
-     */
-    private void changeReadCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create decompressor
-
-        CipherBox oldCipher = readCipher;
-
-        try {
-            readCipher = handshaker.newReadCipher();
-            readMAC = handshaker.newReadMAC();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw (SSLException)new SSLException
-                                ("Algorithm missing:  ").initCause(e);
-        }
-
-        /*
-         * Dispose of any intermediate state in the underlying cipher.
-         * For PKCS11 ciphers, this will release any attached sessions,
-         * and thus make finalization faster.
-         *
-         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
-         * not necessary to do the same with MAC's.
-         */
-        oldCipher.dispose();
-    }
-
-    /*
-     * used by Handshaker to change the active write cipher, follows
-     * the output of the CCS message.
-     *
-     * Also synchronized on "this" from readRecord/delegatedTask.
-     */
-    void changeWriteCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create compressor
-
-        CipherBox oldCipher = writeCipher;
-
-        try {
-            writeCipher = handshaker.newWriteCipher();
-            writeMAC = handshaker.newWriteMAC();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw (SSLException)new SSLException
-                                ("Algorithm missing:  ").initCause(e);
-        }
-
-        // See comment above.
-        oldCipher.dispose();
-
-        // reset the flag of the first application record
-        isFirstAppOutputRecord = true;
-    }
-
-    /*
-     * Updates the SSL version associated with this connection.
-     * Called from Handshaker once it has determined the negotiated version.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        outputRecord.setVersion(protocolVersion);
-    }
-
-
-    /**
-     * Kickstart the handshake if it is not already in progress.
-     * This means:
-     *
-     *  . if handshaking is already underway, do nothing and return
-     *
-     *  . if the engine is not connected or already closed, throw an
-     *    Exception.
-     *
-     *  . otherwise, call initHandshake() to initialize the handshaker
-     *    object and progress the state. Then, send the initial
-     *    handshaking message if appropriate (always on clients and
-     *    on servers when renegotiating).
-     */
-    private synchronized void kickstartHandshake() throws IOException {
-        switch (connectionState) {
-
-        case cs_START:
-            if (!serverModeSet) {
-                throw new IllegalStateException(
-                    "Client/Server mode not yet set.");
-            }
-            initHandshaker();
-            break;
-
-        case cs_HANDSHAKE:
-            // handshaker already setup, proceed
-            break;
-
-        case cs_DATA:
-            if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
-                throw new SSLHandshakeException(
-                        "Insecure renegotiation is not allowed");
-            }
-
-            if (!secureRenegotiation) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "Warning: Using insecure renegotiation");
-                }
-            }
-
-            // initialize the handshaker, move to cs_RENEGOTIATE
-            initHandshaker();
-            break;
-
-        case cs_RENEGOTIATE:
-            // handshaking already in progress, return
-            return;
-
-        default:
-            // cs_ERROR/cs_CLOSED
-            throw new SSLException("SSLEngine is closing/closed");
-        }
-
-        //
-        // Kickstart handshake state machine if we need to ...
-        //
-        // Note that handshaker.kickstart() writes the message
-        // to its HandshakeOutStream, which calls back into
-        // SSLSocketImpl.writeRecord() to send it.
-        //
-        if (!handshaker.activated()) {
-             // prior to handshaking, activate the handshake
-            if (connectionState == cs_RENEGOTIATE) {
-                // don't use SSLv2Hello when renegotiating
-                handshaker.activate(protocolVersion);
-            } else {
-                handshaker.activate(null);
-            }
-
-            if (handshaker instanceof ClientHandshaker) {
-                // send client hello
-                handshaker.kickstart();
-            } else {    // instanceof ServerHandshaker
-                if (connectionState == cs_HANDSHAKE) {
-                    // initial handshake, no kickstart message to send
-                } else {
-                    // we want to renegotiate, send hello request
-                    handshaker.kickstart();
-
-                    // hello request is not included in the handshake
-                    // hashes, reset them
-                    handshaker.handshakeHash.reset();
-                }
-            }
-        }
-    }
-
-    /*
-     * Start a SSLEngine handshake
-     */
-    public void beginHandshake() throws SSLException {
-        try {
-            kickstartHandshake();
-        } catch (Exception e) {
-            fatal(Alerts.alert_handshake_failure,
-                "Couldn't kickstart handshaking", e);
-        }
-    }
-
-
-    //
-    // Read/unwrap side
-    //
-
-
-    /**
-     * Unwraps a buffer.  Does a variety of checks before grabbing
-     * the unwrapLock, which blocks multiple unwraps from occuring.
-     */
-    public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData,
-            int offset, int length) throws SSLException {
-
-        EngineArgs ea = new EngineArgs(netData, appData, offset, length);
-
-        try {
-            synchronized (unwrapLock) {
-                return readNetRecord(ea);
-            }
-        } catch (Exception e) {
-            /*
-             * Don't reset position so it looks like we didn't
-             * consume anything.  We did consume something, and it
-             * got us into this situation, so report that much back.
-             * Our days of consuming are now over anyway.
-             */
-            fatal(Alerts.alert_internal_error,
-                "problem unwrapping net record", e);
-            return null;  // make compiler happy
-        } finally {
-            /*
-             * Just in case something failed to reset limits properly.
-             */
-            ea.resetLim();
-        }
-    }
-
-    /*
-     * Makes additional checks for unwrap, but this time more
-     * specific to this packet and the current state of the machine.
-     */
-    private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException {
-
-        Status status = null;
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * See if the handshaker needs to report back some SSLException.
-         */
-        checkTaskThrown();
-
-        /*
-         * Check if we are closing/closed.
-         */
-        if (isInboundDone()) {
-            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
-        }
-
-        /*
-         * If we're still in cs_HANDSHAKE, make sure it's been
-         * started.
-         */
-        synchronized (this) {
-            if ((connectionState == cs_HANDSHAKE) ||
-                    (connectionState == cs_START)) {
-                kickstartHandshake();
-
-                /*
-                 * If there's still outbound data to flush, we
-                 * can return without trying to unwrap anything.
-                 */
-                hsStatus = getHSStatus(null);
-
-                if (hsStatus == HandshakeStatus.NEED_WRAP) {
-                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
-                }
-            }
-        }
-
-        /*
-         * Grab a copy of this if it doesn't already exist,
-         * and we can use it several places before anything major
-         * happens on this side.  Races aren't critical
-         * here.
-         */
-        if (hsStatus == null) {
-            hsStatus = getHSStatus(null);
-        }
-
-        /*
-         * If we have a task outstanding, this *MUST* be done before
-         * doing any more unwrapping, because we could be in the middle
-         * of receiving a handshake message, for example, a finished
-         * message which would change the ciphers.
-         */
-        if (hsStatus == HandshakeStatus.NEED_TASK) {
-            return new SSLEngineResult(
-                Status.OK, hsStatus, 0, 0);
-        }
-
-        /*
-         * Check the packet to make sure enough is here.
-         * This will also indirectly check for 0 len packets.
-         */
-        int packetLen = inputRecord.bytesInCompletePacket(ea.netData);
-
-        // Is this packet bigger than SSL/TLS normally allows?
-        if (packetLen > sess.getPacketBufferSize()) {
-            if (packetLen > Record.maxLargeRecordSize) {
-                throw new SSLProtocolException(
-                    "Input SSL/TLS record too big: max = " +
-                    Record.maxLargeRecordSize +
-                    " len = " + packetLen);
-            } else {
-                // Expand the expected maximum packet/application buffer
-                // sizes.
-                sess.expandBufferSizes();
-            }
-        }
-
-        /*
-         * Check for OVERFLOW.
-         *
-         * To be considered: We could delay enforcing the application buffer
-         * free space requirement until after the initial handshaking.
-         */
-        if ((packetLen - Record.headerSize) > ea.getAppRemaining()) {
-            return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
-        }
-
-        // check for UNDERFLOW.
-        if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) {
-            return new SSLEngineResult(
-                Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
-        }
-
-        /*
-         * We're now ready to actually do the read.
-         * The only result code we really need to be exactly
-         * right is the HS finished, for signaling to
-         * HandshakeCompletedListeners.
-         */
-        try {
-            hsStatus = readRecord(ea);
-        } catch (SSLException e) {
-            throw e;
-        } catch (IOException e) {
-            SSLException ex = new SSLException("readRecord");
-            ex.initCause(e);
-            throw ex;
-        }
-
-        /*
-         * Check the various condition that we could be reporting.
-         *
-         * It's *possible* something might have happened between the
-         * above and now, but it was better to minimally lock "this"
-         * during the read process.  We'll return the current
-         * status, which is more representative of the current state.
-         *
-         * status above should cover:  FINISHED, NEED_TASK
-         */
-        status = (isInboundDone() ? Status.CLOSED : Status.OK);
-        hsStatus = getHSStatus(hsStatus);
-
-        return new SSLEngineResult(status, hsStatus,
-            ea.deltaNet(), ea.deltaApp());
-    }
-
-    /*
-     * Actually do the read record processing.
-     *
-     * Returns a Status if it can make specific determinations
-     * of the engine state.  In particular, we need to signal
-     * that a handshake just completed.
-     *
-     * It would be nice to be symmetrical with the write side and move
-     * the majority of this to EngineInputRecord, but there's too much
-     * SSLEngine state to do that cleanly.  It must still live here.
-     */
-    private HandshakeStatus readRecord(EngineArgs ea) throws IOException {
-
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * The various operations will return new sliced BB's,
-         * this will avoid having to worry about positions and
-         * limits in the netBB.
-         */
-        ByteBuffer readBB = null;
-        ByteBuffer decryptedBB = null;
-
-        if (getConnectionState() != cs_ERROR) {
-
-            /*
-             * Read a record ... maybe emitting an alert if we get a
-             * comprehensible but unsupported "hello" message during
-             * format checking (e.g. V2).
-             */
-            try {
-                readBB = inputRecord.read(ea.netData);
-            } catch (IOException e) {
-                fatal(Alerts.alert_unexpected_message, e);
-            }
-
-            /*
-             * The basic SSLv3 record protection involves (optional)
-             * encryption for privacy, and an integrity check ensuring
-             * data origin authentication.  We do them both here, and
-             * throw a fatal alert if the integrity check fails.
-             */
-            try {
-                decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
-            } catch (BadPaddingException e) {
-                byte alertType = (inputRecord.contentType() ==
-                    Record.ct_handshake) ?
-                        Alerts.alert_handshake_failure :
-                        Alerts.alert_bad_record_mac;
-                fatal(alertType, e.getMessage(), e);
-            }
-
-
-            // if (!inputRecord.decompress(c))
-            //     fatal(Alerts.alert_decompression_failure,
-            //     "decompression failure");
-
-
-            /*
-             * Process the record.
-             */
-
-            synchronized (this) {
-                switch (inputRecord.contentType()) {
-                case Record.ct_handshake:
-                    /*
-                     * Handshake messages always go to a pending session
-                     * handshaker ... if there isn't one, create one.  This
-                     * must work asynchronously, for renegotiation.
-                     *
-                     * NOTE that handshaking will either resume a session
-                     * which was in the cache (and which might have other
-                     * connections in it already), or else will start a new
-                     * session (new keys exchanged) with just this connection
-                     * in it.
-                     */
-                    initHandshaker();
-                    if (!handshaker.activated()) {
-                        // prior to handshaking, activate the handshake
-                        if (connectionState == cs_RENEGOTIATE) {
-                            // don't use SSLv2Hello when renegotiating
-                            handshaker.activate(protocolVersion);
-                        } else {
-                            handshaker.activate(null);
-                        }
-                    }
-
-                    /*
-                     * process the handshake record ... may contain just
-                     * a partial handshake message or multiple messages.
-                     *
-                     * The handshaker state machine will ensure that it's
-                     * a finished message.
-                     */
-                    handshaker.process_record(inputRecord, expectingFinished);
-                    expectingFinished = false;
-
-                    if (handshaker.invalidated) {
-                        handshaker = null;
-                        // if state is cs_RENEGOTIATE, revert it to cs_DATA
-                        if (connectionState == cs_RENEGOTIATE) {
-                            connectionState = cs_DATA;
-                        }
-                    } else if (handshaker.isDone()) {
-                        // reset the parameters for secure renegotiation.
-                        secureRenegotiation =
-                                        handshaker.isSecureRenegotiation();
-                        clientVerifyData = handshaker.getClientVerifyData();
-                        serverVerifyData = handshaker.getServerVerifyData();
-
-                        sess = handshaker.getSession();
-                        handshakeSession = null;
-                        if (!writer.hasOutboundData()) {
-                            hsStatus = HandshakeStatus.FINISHED;
-                        }
-                        handshaker = null;
-                        connectionState = cs_DATA;
-
-                        // No handshakeListeners here.  That's a
-                        // SSLSocket thing.
-                    } else if (handshaker.taskOutstanding()) {
-                        hsStatus = HandshakeStatus.NEED_TASK;
-                    }
-                    break;
-
-                case Record.ct_application_data:
-                    // Pass this right back up to the application.
-                    if ((connectionState != cs_DATA)
-                            && (connectionState != cs_RENEGOTIATE)
-                            && (connectionState != cs_CLOSED)) {
-                        throw new SSLProtocolException(
-                            "Data received in non-data state: " +
-                            connectionState);
-                    }
-
-                    if (expectingFinished) {
-                        throw new SSLProtocolException
-                                ("Expecting finished message, received data");
-                    }
-
-                    /*
-                     * Don't return data once the inbound side is
-                     * closed.
-                     */
-                    if (!inboundDone) {
-                        ea.scatter(decryptedBB.slice());
-                    }
-                    break;
-
-                case Record.ct_alert:
-                    recvAlert();
-                    break;
-
-                case Record.ct_change_cipher_spec:
-                    if ((connectionState != cs_HANDSHAKE
-                                && connectionState != cs_RENEGOTIATE)
-                            || inputRecord.available() != 1
-                            || inputRecord.read() != 1) {
-                        fatal(Alerts.alert_unexpected_message,
-                            "illegal change cipher spec msg, state = "
-                            + connectionState);
-                    }
-
-                    //
-                    // The first message after a change_cipher_spec
-                    // record MUST be a "Finished" handshake record,
-                    // else it's a protocol violation.  We force this
-                    // to be checked by a minor tweak to the state
-                    // machine.
-                    //
-                    changeReadCiphers();
-                    // next message MUST be a finished message
-                    expectingFinished = true;
-                    break;
-
-                default:
-                    //
-                    // TLS requires that unrecognized records be ignored.
-                    //
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(threadName() +
-                            ", Received record type: "
-                            + inputRecord.contentType());
-                    }
-                    break;
-                } // switch
-
-                /*
-                 * We only need to check the sequence number state for
-                 * non-handshaking record.
-                 *
-                 * Note that in order to maintain the handshake status
-                 * properly, we check the sequence number after the last
-                 * record reading process. As we request renegotiation
-                 * or close the connection for wrapped sequence number
-                 * when there is enough sequence number space left to
-                 * handle a few more records, so the sequence number
-                 * of the last record cannot be wrapped.
-                 */
-                if (connectionState < cs_ERROR && !isInboundDone() &&
-                        (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-                    if (checkSequenceNumber(readMAC,
-                            inputRecord.contentType())) {
-                        hsStatus = getHSStatus(null);
-                    }
-                }
-            } // synchronized (this)
-        }
-
-        return hsStatus;
-    }
-
-
-    //
-    // write/wrap side
-    //
-
-
-    /**
-     * Wraps a buffer.  Does a variety of checks before grabbing
-     * the wrapLock, which blocks multiple wraps from occuring.
-     */
-    public SSLEngineResult wrap(ByteBuffer [] appData,
-            int offset, int length, ByteBuffer netData) throws SSLException {
-
-        EngineArgs ea = new EngineArgs(appData, offset, length, netData);
-
-        /*
-         * We can be smarter about using smaller buffer sizes later.
-         * For now, force it to be large enough to handle any
-         * valid SSL/TLS record.
-         */
-        if (netData.remaining() < outputRecord.maxRecordSize) {
-            return new SSLEngineResult(
-                Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
-        }
-
-        try {
-            synchronized (wrapLock) {
-                return writeAppRecord(ea);
-            }
-        } catch (Exception e) {
-            ea.resetPos();
-
-            fatal(Alerts.alert_internal_error,
-                "problem wrapping app data", e);
-            return null;  // make compiler happy
-        } finally {
-            /*
-             * Just in case something didn't reset limits properly.
-             */
-            ea.resetLim();
-        }
-    }
-
-    /*
-     * Makes additional checks for unwrap, but this time more
-     * specific to this packet and the current state of the machine.
-     */
-    private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {
-
-        Status status = null;
-        HandshakeStatus hsStatus = null;
-
-        /*
-         * See if the handshaker needs to report back some SSLException.
-         */
-        checkTaskThrown();
-
-        /*
-         * short circuit if we're closed/closing.
-         */
-        if (writer.isOutboundDone()) {
-            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
-        }
-
-        /*
-         * If we're still in cs_HANDSHAKE, make sure it's been
-         * started.
-         */
-        synchronized (this) {
-            if ((connectionState == cs_HANDSHAKE) ||
-                    (connectionState == cs_START)) {
-                kickstartHandshake();
-
-                /*
-                 * If there's no HS data available to write, we can return
-                 * without trying to wrap anything.
-                 */
-                hsStatus = getHSStatus(null);
-
-                if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
-                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
-                }
-            }
-        }
-
-        /*
-         * Grab a copy of this if it doesn't already exist,
-         * and we can use it several places before anything major
-         * happens on this side.  Races aren't critical
-         * here.
-         */
-        if (hsStatus == null) {
-            hsStatus = getHSStatus(null);
-        }
-
-        /*
-         * If we have a task outstanding, this *MUST* be done before
-         * doing any more wrapping, because we could be in the middle
-         * of receiving a handshake message, for example, a finished
-         * message which would change the ciphers.
-         */
-        if (hsStatus == HandshakeStatus.NEED_TASK) {
-            return new SSLEngineResult(
-                Status.OK, hsStatus, 0, 0);
-        }
-
-        /*
-         * This will obtain any waiting outbound data, or will
-         * process the outbound appData.
-         */
-        try {
-            synchronized (writeLock) {
-                hsStatus = writeRecord(outputRecord, ea);
-            }
-        } catch (SSLException e) {
-            throw e;
-        } catch (IOException e) {
-            SSLException ex = new SSLException("Write problems");
-            ex.initCause(e);
-            throw ex;
-        }
-
-        /*
-         * writeRecord might have reported some status.
-         * Now check for the remaining cases.
-         *
-         * status above should cover:  NEED_WRAP/FINISHED
-         */
-        status = (isOutboundDone() ? Status.CLOSED : Status.OK);
-        hsStatus = getHSStatus(hsStatus);
-
-        return new SSLEngineResult(status, hsStatus,
-            ea.deltaApp(), ea.deltaNet());
-    }
-
-    /*
-     * Central point to write/get all of the outgoing data.
-     */
-    private HandshakeStatus writeRecord(EngineOutputRecord eor,
-            EngineArgs ea) throws IOException {
-
-        // eventually compress as well.
-        HandshakeStatus hsStatus =
-                writer.writeRecord(eor, ea, writeMAC, writeCipher);
-
-        /*
-         * We only need to check the sequence number state for
-         * non-handshaking record.
-         *
-         * Note that in order to maintain the handshake status
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        if (connectionState < cs_ERROR && !isOutboundDone() &&
-                (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-            if (checkSequenceNumber(writeMAC, eor.contentType())) {
-                hsStatus = getHSStatus(null);
-            }
-        }
-
-        /*
-         * turn off the flag of the first application record if we really
-         * consumed at least byte.
-         */
-        if (isFirstAppOutputRecord && ea.deltaApp() > 0) {
-            isFirstAppOutputRecord = false;
-        }
-
-        return hsStatus;
-    }
-
-    /*
-     * Need to split the payload except the following cases:
-     *
-     * 1. protocol version is TLS 1.1 or later;
-     * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
-     * 3. the payload is the first application record of a freshly
-     *    negotiated TLS session.
-     * 4. the CBC protection is disabled;
-     *
-     * More details, please refer to
-     * EngineOutputRecord.write(EngineArgs, MAC, CipherBox).
-     */
-    boolean needToSplitPayload(CipherBox cipher, ProtocolVersion protocol) {
-        return (protocol.v <= ProtocolVersion.TLS10.v) &&
-                cipher.isCBCMode() && !isFirstAppOutputRecord &&
-                Record.enableCBCProtection;
-    }
-
-    /*
-     * Non-application OutputRecords go through here.
-     */
-    void writeRecord(EngineOutputRecord eor) throws IOException {
-        // eventually compress as well.
-        writer.writeRecord(eor, writeMAC, writeCipher);
-
-        /*
-         * Check the sequence number state
-         *
-         * Note that in order to maintain the connection I/O
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        if ((connectionState < cs_ERROR) && !isOutboundDone()) {
-            checkSequenceNumber(writeMAC, eor.contentType());
-        }
-    }
-
-    //
-    // Close code
-    //
-
-    /**
-     * Check the sequence number state
-     *
-     * RFC 4346 states that, "Sequence numbers are of type uint64 and
-     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead."
-     *
-     * Return true if the handshake status may be changed.
-     */
-    private boolean checkSequenceNumber(MAC mac, byte type)
-            throws IOException {
-
-        /*
-         * Don't bother to check the sequence number for error or
-         * closed connections, or NULL MAC
-         */
-        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
-            return false;
-        }
-
-        /*
-         * Conservatively, close the connection immediately when the
-         * sequence number is close to overflow
-         */
-        if (mac.seqNumOverflow()) {
-            /*
-             * TLS protocols do not define a error alert for sequence
-             * number overflow. We use handshake_failure error alert
-             * for handshaking and bad_record_mac for other records.
-             */
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", sequence number extremely close to overflow " +
-                    "(2^64-1 packets). Closing connection.");
-            }
-
-            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
-
-            return true; // make the compiler happy
-        }
-
-        /*
-         * Ask for renegotiation when need to renew sequence number.
-         *
-         * Don't bother to kickstart the renegotiation when the local is
-         * asking for it.
-         */
-        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() + ", request renegotiation " +
-                        "to avoid sequence number overflow");
-            }
-
-            beginHandshake();
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Signals that no more outbound application data will be sent
-     * on this <code>SSLEngine</code>.
-     */
-    private void closeOutboundInternal() {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", closeOutboundInternal()");
-        }
-
-        /*
-         * Already closed, ignore
-         */
-        if (writer.isOutboundDone()) {
-            return;
-        }
-
-        switch (connectionState) {
-
-        /*
-         * If we haven't even started yet, don't bother reading inbound.
-         */
-        case cs_START:
-            writer.closeOutbound();
-            inboundDone = true;
-            break;
-
-        case cs_ERROR:
-        case cs_CLOSED:
-            break;
-
-        /*
-         * Otherwise we indicate clean termination.
-         */
-        // case cs_HANDSHAKE:
-        // case cs_DATA:
-        // case cs_RENEGOTIATE:
-        default:
-            warning(Alerts.alert_close_notify);
-            writer.closeOutbound();
-            break;
-        }
-
-        // See comment in changeReadCiphers()
-        writeCipher.dispose();
-
-        connectionState = cs_CLOSED;
-    }
-
-    synchronized public void closeOutbound() {
-        /*
-         * Dump out a close_notify to the remote side
-         */
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeOutbound()");
-        }
-
-        closeOutboundInternal();
-    }
-
-    /**
-     * Returns the outbound application data closure state
-     */
-    public boolean isOutboundDone() {
-        return writer.isOutboundDone();
-    }
-
-    /**
-     * Signals that no more inbound network data will be sent
-     * to this <code>SSLEngine</code>.
-     */
-    private void closeInboundInternal() {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", closeInboundInternal()");
-        }
-
-        /*
-         * Already closed, ignore
-         */
-        if (inboundDone) {
-            return;
-        }
-
-        closeOutboundInternal();
-        inboundDone = true;
-
-        // See comment in changeReadCiphers()
-        readCipher.dispose();
-
-        connectionState = cs_CLOSED;
-    }
-
-    /*
-     * Close the inbound side of the connection.  We grab the
-     * lock here, and do the real work in the internal verison.
-     * We do check for truncation attacks.
-     */
-    synchronized public void closeInbound() throws SSLException {
-        /*
-         * Currently closes the outbound side as well.  The IETF TLS
-         * working group has expressed the opinion that 1/2 open
-         * connections are not allowed by the spec.  May change
-         * someday in the future.
-         */
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeInbound()");
-        }
-
-        /*
-         * No need to throw an Exception if we haven't even started yet.
-         */
-        if ((connectionState != cs_START) && !recvCN) {
-            recvCN = true;  // Only receive the Exception once
-            fatal(Alerts.alert_internal_error,
-                "Inbound closed before receiving peer's close_notify: " +
-                "possible truncation attack?");
-        } else {
-            /*
-             * Currently, this is a no-op, but in case we change
-             * the close inbound code later.
-             */
-            closeInboundInternal();
-        }
-    }
-
-    /**
-     * Returns the network inbound data closure state
-     */
-    synchronized public boolean isInboundDone() {
-        return inboundDone;
-    }
-
-
-    //
-    // Misc stuff
-    //
-
-
-    /**
-     * Returns the current <code>SSLSession</code> for this
-     * <code>SSLEngine</code>
-     * <P>
-     * These can be long lived, and frequently correspond to an
-     * entire login session for some user.
-     */
-    synchronized public SSLSession getSession() {
-        return sess;
-    }
-
-    @Override
-    synchronized public SSLSession getHandshakeSession() {
-        return handshakeSession;
-    }
-
-    synchronized void setHandshakeSession(SSLSessionImpl session) {
-        handshakeSession = session;
-    }
-
-    /**
-     * Returns a delegated <code>Runnable</code> task for
-     * this <code>SSLEngine</code>.
-     */
-    synchronized public Runnable getDelegatedTask() {
-        if (handshaker != null) {
-            return handshaker.getTask();
-        }
-        return null;
-    }
-
-
-    //
-    // EXCEPTION AND ALERT HANDLING
-    //
-
-    /*
-     * Send a warning alert.
-     */
-    void warning(byte description) {
-        sendAlert(Alerts.alert_warning, description);
-    }
-
-    synchronized void fatal(byte description, String diagnostic)
-            throws SSLException {
-        fatal(description, diagnostic, null);
-    }
-
-    synchronized void fatal(byte description, Throwable cause)
-            throws SSLException {
-        fatal(description, null, cause);
-    }
-
-    /*
-     * We've got a fatal error here, so start the shutdown process.
-     *
-     * Because of the way the code was written, we have some code
-     * calling fatal directly when the "description" is known
-     * and some throwing Exceptions which are then caught by higher
-     * levels which then call here.  This code needs to determine
-     * if one of the lower levels has already started the process.
-     *
-     * We won't worry about Error's, if we have one of those,
-     * we're in worse trouble.  Note:  the networking code doesn't
-     * deal with Errors either.
-     */
-    synchronized void fatal(byte description, String diagnostic,
-            Throwable cause) throws SSLException {
-
-        /*
-         * If we have no further information, make a general-purpose
-         * message for folks to see.  We generally have one or the other.
-         */
-        if (diagnostic == null) {
-            diagnostic = "General SSLEngine problem";
-        }
-        if (cause == null) {
-            cause = Alerts.getSSLException(description, cause, diagnostic);
-        }
-
-        /*
-         * If we've already shutdown because of an error,
-         * there is nothing we can do except rethrow the exception.
-         *
-         * Most exceptions seen here will be SSLExceptions.
-         * We may find the occasional Exception which hasn't been
-         * converted to a SSLException, so we'll do it here.
-         */
-        if (closeReason != null) {
-            if ((debug != null) && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", fatal: engine already closed.  Rethrowing " +
-                    cause.toString());
-            }
-            if (cause instanceof RuntimeException) {
-                throw (RuntimeException)cause;
-            } else if (cause instanceof SSLException) {
-                throw (SSLException)cause;
-            } else if (cause instanceof Exception) {
-                SSLException ssle = new SSLException(
-                    "fatal SSLEngine condition");
-                ssle.initCause(cause);
-                throw ssle;
-            }
-        }
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName()
-                        + ", fatal error: " + description +
-                        ": " + diagnostic + "\n" + cause.toString());
-        }
-
-        /*
-         * Ok, this engine's going down.
-         */
-        int oldState = connectionState;
-        connectionState = cs_ERROR;
-
-        inboundDone = true;
-
-        sess.invalidate();
-        if (handshakeSession != null) {
-            handshakeSession.invalidate();
-        }
-
-        /*
-         * If we haven't even started handshaking yet, no need
-         * to generate the fatal close alert.
-         */
-        if (oldState != cs_START) {
-            sendAlert(Alerts.alert_fatal, description);
-        }
-
-        if (cause instanceof SSLException) { // only true if != null
-            closeReason = (SSLException)cause;
-        } else {
-            /*
-             * Including RuntimeExceptions, but we'll throw those
-             * down below.  The closeReason isn't used again,
-             * except for null checks.
-             */
-            closeReason =
-                Alerts.getSSLException(description, cause, diagnostic);
-        }
-
-        writer.closeOutbound();
-
-        connectionState = cs_CLOSED;
-
-        // See comment in changeReadCiphers()
-        readCipher.dispose();
-        writeCipher.dispose();
-
-        if (cause instanceof RuntimeException) {
-            throw (RuntimeException)cause;
-        } else {
-            throw closeReason;
-        }
-    }
-
-    /*
-     * Process an incoming alert ... caller must already have synchronized
-     * access to "this".
-     */
-    private void recvAlert() throws IOException {
-        byte level = (byte)inputRecord.read();
-        byte description = (byte)inputRecord.read();
-        if (description == -1) { // check for short message
-            fatal(Alerts.alert_illegal_parameter, "Short alert message");
-        }
-
-        if (debug != null && (Debug.isOn("record") ||
-                Debug.isOn("handshake"))) {
-            synchronized (System.out) {
-                System.out.print(threadName());
-                System.out.print(", RECV " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level " + (0x0ff & level) + ">, ");
-                }
-                System.out.println(Alerts.alertDescription(description));
-            }
-        }
-
-        if (level == Alerts.alert_warning) {
-            if (description == Alerts.alert_close_notify) {
-                if (connectionState == cs_HANDSHAKE) {
-                    fatal(Alerts.alert_unexpected_message,
-                                "Received close_notify during handshake");
-                } else {
-                    recvCN = true;
-                    closeInboundInternal();  // reply to close
-                }
-            } else {
-
-                //
-                // The other legal warnings relate to certificates,
-                // e.g. no_certificate, bad_certificate, etc; these
-                // are important to the handshaking code, which can
-                // also handle illegal protocol alerts if needed.
-                //
-                if (handshaker != null) {
-                    handshaker.handshakeAlert(description);
-                }
-            }
-        } else { // fatal or unknown level
-            String reason = "Received fatal alert: "
-                + Alerts.alertDescription(description);
-            if (closeReason == null) {
-                closeReason = Alerts.getSSLException(description, reason);
-            }
-            fatal(Alerts.alert_unexpected_message, reason);
-        }
-    }
-
-
-    /*
-     * Emit alerts.  Caller must have synchronized with "this".
-     */
-    private void sendAlert(byte level, byte description) {
-        // the connectionState cannot be cs_START
-        if (connectionState >= cs_CLOSED) {
-            return;
-        }
-
-        // For initial handshaking, don't send alert message to peer if
-        // handshaker has not started.
-        if (connectionState == cs_HANDSHAKE &&
-            (handshaker == null || !handshaker.started())) {
-            return;
-        }
-
-        EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
-        r.setVersion(protocolVersion);
-
-        boolean useDebug = debug != null && Debug.isOn("ssl");
-        if (useDebug) {
-            synchronized (System.out) {
-                System.out.print(threadName());
-                System.out.print(", SEND " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level = " + (0x0ff & level) + ">, ");
-                }
-                System.out.println("description = "
-                        + Alerts.alertDescription(description));
-            }
-        }
-
-        r.write(level);
-        r.write(description);
-        try {
-            writeRecord(r);
-        } catch (IOException e) {
-            if (useDebug) {
-                System.out.println(threadName() +
-                    ", Exception sending alert: " + e);
-            }
-        }
-    }
-
-
-    //
-    // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
-    //
-
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     *
-     * As long as handshaking has not started, we can change
-     * whether we enable session creations.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnableSessionCreation(enableSessionCreation);
-        }
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    synchronized public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-
-    /**
-     * Sets the flag controlling whether a server mode engine
-     * *REQUIRES* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is needed.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    synchronized public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Sets the flag controlling whether a server mode engine
-     * *REQUESTS* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is requested.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    synchronized public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-
-    /**
-     * Sets the flag controlling whether the engine is in SSL
-     * client or server mode.  Must be called before any SSL
-     * traffic has started.
-     */
-    synchronized public void setUseClientMode(boolean flag) {
-        switch (connectionState) {
-
-        case cs_START:
-            /*
-             * If we need to change the engine mode and the enabled
-             * protocols haven't specifically been set by the user,
-             * change them to the corresponding default ones.
-             */
-            if (roleIsServer != (!flag) &&
-                    sslContext.isDefaultProtocolList(enabledProtocols)) {
-                enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-            }
-
-            roleIsServer = !flag;
-            serverModeSet = true;
-            break;
-
-        case cs_HANDSHAKE:
-            /*
-             * If we have a handshaker, but haven't started
-             * SSL traffic, we can throw away our current
-             * handshaker, and start from scratch.  Don't
-             * need to call doneConnect() again, we already
-             * have the streams.
-             */
-            assert(handshaker != null);
-            if (!handshaker.activated()) {
-                /*
-                 * If we need to change the engine mode and the enabled
-                 * protocols haven't specifically been set by the user,
-                 * change them to the corresponding default ones.
-                 */
-                if (roleIsServer != (!flag) &&
-                        sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-                }
-
-                roleIsServer = !flag;
-                connectionState = cs_START;
-                initHandshaker();
-                break;
-            }
-
-            // If handshake has started, that's an error.  Fall through...
-
-        default:
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", setUseClientMode() invoked in state = " +
-                    connectionState);
-            }
-
-            /*
-             * We can let them continue if they catch this correctly,
-             * we don't need to shut this down.
-             */
-            throw new IllegalArgumentException(
-                "Cannot change mode after SSL traffic has started");
-        }
-    }
-
-    synchronized public boolean getUseClientMode() {
-        return !roleIsServer;
-    }
-
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Controls which particular cipher suites are enabled for use on
-     * this connection.  The cipher suites must have been listed by
-     * getCipherSuites() as being supported.  Even if a suite has been
-     * enabled, it might never be used if no peer supports it or the
-     * requisite certificates (and private keys) are not available.
-     *
-     * @param suites Names of all the cipher suites to enable.
-     */
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        }
-    }
-
-    /**
-     * Returns the names of the SSL cipher suites which are currently enabled
-     * for use on this connection.  When an SSL engine is first created,
-     * all enabled cipher suites <em>(a)</em> protect data confidentiality,
-     * by traffic encryption, and <em>(b)</em> can mutually authenticate
-     * both clients and servers.  Thus, in some environments, this value
-     * might be empty.
-     *
-     * @return an array of cipher suite names
-     */
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-
-    /**
-     * Returns the protocols that are supported by this implementation.
-     * A subset of the supported protocols may be enabled for this connection
-     * @return an array of protocol names.
-     */
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use on
-     * this connection.  The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledProtocols(enabledProtocols);
-        }
-    }
-
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Returns the SSLParameters in effect for this SSLEngine.
-     */
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to this engine.
-     */
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.setIdentificationProtocol(identificationProtocol);
-            handshaker.setAlgorithmConstraints(algorithmConstraints);
-        }
-    }
-
-    /**
-     * Return the name of the current thread. Utility method.
-     */
-    private static String threadName() {
-        return Thread.currentThread().getName();
-    }
-
-    /**
-     * Returns a printable representation of this end of the connection.
-     */
-    public String toString() {
-        StringBuilder retval = new StringBuilder(80);
-
-        retval.append(Integer.toHexString(hashCode()));
-        retval.append("[");
-        retval.append("SSLEngine[hostname=");
-        String host = getPeerHost();
-        retval.append((host == null) ? "null" : host);
-        retval.append(" port=");
-        retval.append(Integer.toString(getPeerPort()));
-        retval.append("] ");
-        retval.append(getSession().getCipherSuite());
-        retval.append("]");
-
-        return retval.toString();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java
deleted file mode 100755
index 2b99129..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-
-import javax.net.ssl.SSLServerSocketFactory;
-
-/**
- * This class creates SSL server sockets.
- *
- * @author David Brownell
- */
-final
-public class SSLServerSocketFactoryImpl extends SSLServerSocketFactory
-{
-    private static final int DEFAULT_BACKLOG = 50;
-    private SSLContextImpl context;
-
-
-    /**
-     * Constructor used to instantiate the default factory. This method is
-     * only called if the old "ssl.ServerSocketFactory.provider" property in the
-     * java.security file is set.
-     */
-    public SSLServerSocketFactoryImpl() throws Exception {
-        this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
-    }
-
-    /**
-     * Called from SSLContextImpl's getSSLServerSocketFactory().
-     */
-    SSLServerSocketFactoryImpl (SSLContextImpl context)
-    {
-        this.context = context;
-    }
-
-    /**
-     * Returns an unbound server socket.
-     *
-     * @return the unbound socket
-     * @throws IOException if the socket cannot be created
-     * @see java.net.Socket#bind(java.net.SocketAddress)
-     */
-    public ServerSocket createServerSocket() throws IOException {
-        return new SSLServerSocketImpl(context);
-    }
-
-    public ServerSocket createServerSocket (int port)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, DEFAULT_BACKLOG, context);
-    }
-
-
-    public ServerSocket createServerSocket (int port, int backlog)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, backlog, context);
-    }
-
-    public ServerSocket
-    createServerSocket (int port, int backlog, InetAddress ifAddress)
-    throws IOException
-    {
-        return new SSLServerSocketImpl (port, backlog, ifAddress, context);
-    }
-
-    /**
-     * Returns the subset of the supported cipher suites which are
-     * enabled by default.  These cipher suites all provide a minimum
-     * quality of service whereby the server authenticates itself
-     * (preventing person-in-the-middle attacks) and where traffic
-     * is encrypted to provide confidentiality.
-     */
-    public String[] getDefaultCipherSuites() {
-        return context.getDefaultCipherSuiteList(true).toStringArray();
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    public String[] getSupportedCipherSuites() {
-        return context.getSupportedCipherSuiteList().toStringArray();
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java
deleted file mode 100755
index c2098c1..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.ServerSocket;
-
-import java.security.AlgorithmConstraints;
-
-import java.util.*;
-
-import javax.net.ServerSocketFactory;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLParameters;
-
-
-/**
- * This class provides a simple way for servers to support conventional
- * use of the Secure Sockets Layer (SSL).  Application code uses an
- * SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
- * difference is that the connections established are secured using SSL.
- *
- * <P> Also, the constructors take an explicit authentication context
- * parameter, giving flexibility with respect to how the server socket
- * authenticates itself.  That policy flexibility is not exposed through
- * the standard SSLServerSocketFactory API.
- *
- * <P> System security defaults prevent server sockets from accepting
- * connections if they the authentication context has not been given
- * a certificate chain and its matching private key.  If the clients
- * of your application support "anonymous" cipher suites, you may be
- * able to configure a server socket to accept those suites.
- *
- * @see SSLSocketImpl
- * @see SSLServerSocketFactoryImpl
- *
- * @author David Brownell
- */
-final
-class SSLServerSocketImpl extends SSLServerSocket
-{
-    private SSLContextImpl      sslContext;
-
-    /* Do newly accepted connections require clients to authenticate? */
-    private byte                doClientAuth = SSLEngineImpl.clauth_none;
-
-    /* Do new connections created here use the "server" mode of SSL? */
-    private boolean             useServerMode = true;
-
-    /* Can new connections created establish new sessions? */
-    private boolean             enableSessionCreation = true;
-
-    /* what cipher suites to use by default */
-    private CipherSuiteList     enabledCipherSuites = null;
-
-    /* which protocol to use by default */
-    private ProtocolList        enabledProtocols = null;
-
-    /* could enabledCipherSuites ever complete handshaking? */
-    private boolean             checkedEnabled = false;
-
-    // the endpoint identification protocol to use by default
-    private String              identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
-
-    /**
-     * Create an SSL server socket on a port, using a non-default
-     * authentication context and a specified connection backlog.
-     *
-     * @param port the port on which to listen
-     * @param backlog how many connections may be pending before
-     *          the system should start rejecting new requests
-     * @param context authentication context for this server
-     */
-    SSLServerSocketImpl(int port, int backlog, SSLContextImpl context)
-    throws IOException, SSLException
-    {
-        super(port, backlog);
-        initServer(context);
-    }
-
-
-    /**
-     * Create an SSL server socket on a port, using a specified
-     * authentication context and a specified backlog of connections
-     * as well as a particular specified network interface.  This
-     * constructor is used on multihomed hosts, such as those used
-     * for firewalls or as routers, to control through which interface
-     * a network service is provided.
-     *
-     * @param port the port on which to listen
-     * @param backlog how many connections may be pending before
-     *          the system should start rejecting new requests
-     * @param address the address of the network interface through
-     *          which connections will be accepted
-     * @param context authentication context for this server
-     */
-    SSLServerSocketImpl(
-        int             port,
-        int             backlog,
-        InetAddress     address,
-        SSLContextImpl  context)
-        throws IOException
-    {
-        super(port, backlog, address);
-        initServer(context);
-    }
-
-
-    /**
-     * Creates an unbound server socket.
-     */
-    SSLServerSocketImpl(SSLContextImpl context) throws IOException {
-        super();
-        initServer(context);
-    }
-
-
-    /**
-     * Initializes the server socket.
-     */
-    private void initServer(SSLContextImpl context) throws SSLException {
-        if (context == null) {
-            throw new SSLException("No Authentication context given");
-        }
-        sslContext = context;
-        enabledCipherSuites = sslContext.getDefaultCipherSuiteList(true);
-        enabledProtocols = sslContext.getDefaultProtocolList(true);
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Returns the list of cipher suites which are currently enabled
-     * for use by newly accepted connections.  A null return indicates
-     * that the system defaults are in effect.
-     */
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-    /**
-     * Controls which particular SSL cipher suites are enabled for use
-     * by accepted connections.
-     *
-     * @param suites Names of all the cipher suites to enable; null
-     *  means to accept system defaults.
-     */
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-        checkedEnabled = false;
-    }
-
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use.
-     * The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-    }
-
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Controls whether the connections which are accepted must include
-     * client authentication.
-     */
-    public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-    }
-
-    public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Controls whether the connections which are accepted should request
-     * client authentication.
-     */
-    public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-    }
-
-    public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-    /**
-     * Makes the returned sockets act in SSL "client" mode, not the usual
-     * server mode.  The canonical example of why this is needed is for
-     * FTP clients, which accept connections from servers and should be
-     * rejoining the already-negotiated SSL connection.
-     */
-    public void setUseClientMode(boolean flag) {
-        /*
-         * If we need to change the socket mode and the enabled
-         * protocols haven't specifically been set by the user,
-         * change them to the corresponding default ones.
-         */
-        if (useServerMode != (!flag) &&
-                sslContext.isDefaultProtocolList(enabledProtocols)) {
-            enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-        }
-
-        useServerMode = !flag;
-    }
-
-    public boolean getUseClientMode() {
-        return !useServerMode;
-    }
-
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     */
-    public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-    /**
-     * Returns the SSLParameters in effect for newly accepted connections.
-     */
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to newly accepted connections.
-     */
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-    }
-
-    /**
-     * Accept a new SSL connection.  This server identifies itself with
-     * information provided in the authentication context which was
-     * presented during construction.
-     */
-    public Socket accept() throws IOException {
-        SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
-            enabledCipherSuites, doClientAuth, enableSessionCreation,
-            enabledProtocols, identificationProtocol, algorithmConstraints);
-
-        implAccept(s);
-        s.doneConnect();
-        return s;
-    }
-
-    /**
-     * Provides a brief description of this SSL socket.
-     */
-    public String toString() {
-        return "[SSL: "+ super.toString() + "]";
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
deleted file mode 100755
index 756a48e..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.Locale;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-
-import sun.security.util.Cache;
-
-
-final class SSLSessionContextImpl implements SSLSessionContext {
-    private Cache<SessionId, SSLSessionImpl> sessionCache;
-                                        // session cache, session id as key
-    private Cache<String, SSLSessionImpl> sessionHostPortCache;
-                                        // session cache, "host:port" as key
-    private int cacheLimit;             // the max cache size
-    private int timeout;                // timeout in seconds
-
-    // package private
-    SSLSessionContextImpl() {
-        cacheLimit = getDefaultCacheLimit();    // default cache size
-        timeout = 86400;                        // default, 24 hours
-
-        // use soft reference
-        sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
-        sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
-    }
-
-    /**
-     * Returns the <code>SSLSession</code> bound to the specified session id.
-     */
-    @Override
-    public SSLSession getSession(byte[] sessionId) {
-        if (sessionId == null) {
-            throw new NullPointerException("session id cannot be null");
-        }
-
-        SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId));
-        if (!isTimedout(sess)) {
-            return sess;
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns an enumeration of the active SSL sessions.
-     */
-    @Override
-    public Enumeration<byte[]> getIds() {
-        SessionCacheVisitor scVisitor = new SessionCacheVisitor();
-        sessionCache.accept(scVisitor);
-
-        return scVisitor.getSessionIds();
-    }
-
-    /**
-     * Sets the timeout limit for cached <code>SSLSession</code> objects
-     *
-     * Note that after reset the timeout, the cached session before
-     * should be timed within the shorter one of the old timeout and the
-     * new timeout.
-     */
-    @Override
-    public void setSessionTimeout(int seconds)
-                 throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException();
-        }
-
-        if (timeout != seconds) {
-            sessionCache.setTimeout(seconds);
-            sessionHostPortCache.setTimeout(seconds);
-            timeout = seconds;
-        }
-    }
-
-    /**
-     * Gets the timeout limit for cached <code>SSLSession</code> objects
-     */
-    @Override
-    public int getSessionTimeout() {
-        return timeout;
-    }
-
-    /**
-     * Sets the size of the cache used for storing
-     * <code>SSLSession</code> objects.
-     */
-    @Override
-    public void setSessionCacheSize(int size)
-                 throws IllegalArgumentException {
-        if (size < 0)
-            throw new IllegalArgumentException();
-
-        if (cacheLimit != size) {
-            sessionCache.setCapacity(size);
-            sessionHostPortCache.setCapacity(size);
-            cacheLimit = size;
-        }
-    }
-
-    /**
-     * Gets the size of the cache used for storing
-     * <code>SSLSession</code> objects.
-     */
-    @Override
-    public int getSessionCacheSize() {
-        return cacheLimit;
-    }
-
-
-    // package-private method, used ONLY by ServerHandshaker
-    SSLSessionImpl get(byte[] id) {
-        return (SSLSessionImpl)getSession(id);
-    }
-
-    // package-private method, used ONLY by ClientHandshaker
-    SSLSessionImpl get(String hostname, int port) {
-        /*
-         * If no session caching info is available, we won't
-         * get one, so exit before doing a lookup.
-         */
-        if (hostname == null && port == -1) {
-            return null;
-        }
-
-        SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port));
-        if (!isTimedout(sess)) {
-            return sess;
-        }
-
-        return null;
-    }
-
-    private String getKey(String hostname, int port) {
-        return (hostname + ":" +
-            String.valueOf(port)).toLowerCase(Locale.ENGLISH);
-    }
-
-    // cache a SSLSession
-    //
-    // In SunJSSE implementation, a session is created while getting a
-    // client hello or a server hello message, and cached while the
-    // handshaking finished.
-    // Here we time the session from the time it cached instead of the
-    // time it created, which is a little longer than the expected. So
-    // please do check isTimedout() while getting entry from the cache.
-    void put(SSLSessionImpl s) {
-        sessionCache.put(s.getSessionId(), s);
-
-        // If no hostname/port info is available, don't add this one.
-        if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) {
-            sessionHostPortCache.put(
-                getKey(s.getPeerHost(), s.getPeerPort()), s);
-        }
-
-        s.setContext(this);
-    }
-
-    // package-private method, remove a cached SSLSession
-    void remove(SessionId key) {
-        SSLSessionImpl s = sessionCache.get(key);
-        if (s != null) {
-            sessionCache.remove(key);
-            sessionHostPortCache.remove(
-                        getKey(s.getPeerHost(), s.getPeerPort()));
-        }
-    }
-
-    private int getDefaultCacheLimit() {
-        int cacheLimit = 0;
-        try {
-        String s = java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<String>() {
-                @Override
-                public String run() {
-                    return System.getProperty(
-                        "javax.net.ssl.sessionCacheSize");
-                }
-            });
-            cacheLimit = (s != null) ? Integer.parseInt(s) : 0;
-        } catch (Exception e) {
-        }
-
-        return (cacheLimit > 0) ? cacheLimit : 0;
-    }
-
-    boolean isTimedout(SSLSession sess) {
-        if (timeout == 0) {
-            return false;
-        }
-
-        if ((sess != null) && ((sess.getCreationTime() + timeout * 1000L)
-                                        <= (System.currentTimeMillis()))) {
-            sess.invalidate();
-            return true;
-        }
-
-        return false;
-    }
-
-    final class SessionCacheVisitor
-            implements Cache.CacheVisitor<SessionId, SSLSessionImpl> {
-        Vector<byte[]> ids = null;
-
-        // public void visit(java.util.Map<K,V> map) {}
-        @Override
-        public void visit(java.util.Map<SessionId, SSLSessionImpl> map) {
-            ids = new Vector<>(map.size());
-
-            for (SessionId key : map.keySet()) {
-                SSLSessionImpl value = map.get(key);
-                if (!isTimedout(value)) {
-                    ids.addElement(key.getId());
-                }
-            }
-        }
-
-        public Enumeration<byte[]> getSessionIds() {
-            return  ids != null ? ids.elements() :
-                                  new Vector<byte[]>().elements();
-        }
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java
deleted file mode 100755
index 110fc9c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java
+++ /dev/null
@@ -1,832 +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.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Arrays;
-import java.util.Collection;
-
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateEncodingException;
-
-import javax.crypto.SecretKey;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLSessionBindingListener;
-import javax.net.ssl.SSLSessionBindingEvent;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLPermission;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.ExtendedSSLSession;
-
-import javax.security.auth.x500.X500Principal;
-
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * Implements the SSL session interface, and exposes the session context
- * which is maintained by SSL servers.
- *
- * <P> Servers have the ability to manage the sessions associated with
- * their authentication context(s).  They can do this by enumerating the
- * IDs of the sessions which are cached, examining those sessions, and then
- * perhaps invalidating a given session so that it can't be used again.
- * If servers do not explicitly manage the cache, sessions will linger
- * until memory is low enough that the runtime environment purges cache
- * entries automatically to reclaim space.
- *
- * <P><em> The only reason this class is not package-private is that
- * there's no other public way to get at the server session context which
- * is associated with any given authentication context. </em>
- *
- * @author David Brownell
- */
-final class SSLSessionImpl extends ExtendedSSLSession {
-
-    /*
-     * we only really need a single null session
-     */
-    static final SSLSessionImpl         nullSession = new SSLSessionImpl();
-
-    // compression methods
-    private static final byte           compression_null = 0;
-
-    /*
-     * The state of a single session, as described in section 7.1
-     * of the SSLv3 spec.
-     */
-    private final ProtocolVersion       protocolVersion;
-    private final SessionId             sessionId;
-    private X509Certificate[]   peerCerts;
-    private byte                compressionMethod;
-    private CipherSuite         cipherSuite;
-    private SecretKey           masterSecret;
-
-    /*
-     * Information not part of the SSLv3 protocol spec, but used
-     * to support session management policies.
-     */
-    private final long          creationTime = System.currentTimeMillis();
-    private long                lastUsedTime = 0;
-    private final String        host;
-    private final int           port;
-    private SSLSessionContextImpl       context;
-    private int                 sessionCount;
-    private boolean             invalidated;
-    private X509Certificate[]   localCerts;
-    private PrivateKey          localPrivateKey;
-    private String[]            localSupportedSignAlgs;
-    private String[]            peerSupportedSignAlgs;
-
-    // Principals for non-certificate based cipher suites
-    private Principal peerPrincipal;
-    private Principal localPrincipal;
-
-    /*
-     * We count session creations, eventually for statistical data but
-     * also since counters make shorter debugging IDs than the big ones
-     * we use in the protocol for uniqueness-over-time.
-     */
-    private static volatile int counter = 0;
-
-    /*
-     * Use of session caches is globally enabled/disabled.
-     */
-    private static boolean      defaultRejoinable = true;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Create a new non-rejoinable session, using the default (null)
-     * cipher spec.  This constructor returns a session which could
-     * be used either by a client or by a server, as a connection is
-     * first opened and before handshaking begins.
-     */
-    private SSLSessionImpl() {
-        this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
-            new SessionId(false, null), null, -1);
-    }
-
-    /*
-     * Create a new session, using a given cipher spec.  This will
-     * be rejoinable if session caching is enabled; the constructor
-     * is intended mostly for use by serves.
-     */
-    SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            SecureRandom generator, String host, int port) {
-        this(protocolVersion, cipherSuite, algorithms,
-             new SessionId(defaultRejoinable, generator), host, port);
-    }
-
-    /*
-     * Record a new session, using a given cipher spec and session ID.
-     */
-    SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            SessionId id, String host, int port) {
-        this.protocolVersion = protocolVersion;
-        sessionId = id;
-        peerCerts = null;
-        compressionMethod = compression_null;
-        this.cipherSuite = cipherSuite;
-        masterSecret = null;
-        this.host = host;
-        this.port = port;
-        sessionCount = ++counter;
-        localSupportedSignAlgs =
-            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
-
-        if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Initialized:  " + this);
-        }
-    }
-
-    void setMasterSecret(SecretKey secret) {
-        if (masterSecret == null) {
-            masterSecret = secret;
-        } else {
-            throw new RuntimeException("setMasterSecret() error");
-        }
-    }
-
-    /**
-     * Returns the master secret ... treat with extreme caution!
-     */
-    SecretKey getMasterSecret() {
-        return masterSecret;
-    }
-
-    void setPeerCertificates(X509Certificate[] peer) {
-        if (peerCerts == null) {
-            peerCerts = peer;
-        }
-    }
-
-    void setLocalCertificates(X509Certificate[] local) {
-        localCerts = local;
-    }
-
-    void setLocalPrivateKey(PrivateKey privateKey) {
-        localPrivateKey = privateKey;
-    }
-
-    void setPeerSupportedSignatureAlgorithms(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        peerSupportedSignAlgs =
-            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
-    }
-
-    /**
-     * Set the peer principal.
-     */
-    void setPeerPrincipal(Principal principal) {
-        if (peerPrincipal == null) {
-            peerPrincipal = principal;
-        }
-    }
-
-    /**
-     * Set the local principal.
-     */
-    void setLocalPrincipal(Principal principal) {
-        localPrincipal = principal;
-    }
-
-    /**
-     * Returns true iff this session may be resumed ... sessions are
-     * usually resumable.  Security policies may suggest otherwise,
-     * for example sessions that haven't been used for a while (say,
-     * a working day) won't be resumable, and sessions might have a
-     * maximum lifetime in any case.
-     */
-    boolean isRejoinable() {
-        return sessionId != null && sessionId.length() != 0 &&
-            !invalidated && isLocalAuthenticationValid();
-    }
-
-    public synchronized boolean isValid() {
-        return isRejoinable();
-    }
-
-    /**
-     * Check if the authentication used when establishing this session
-     * is still valid. Returns true if no authentication was used
-     */
-    boolean isLocalAuthenticationValid() {
-        if (localPrivateKey != null) {
-            try {
-                // if the private key is no longer valid, getAlgorithm()
-                // should throw an exception
-                // (e.g. Smartcard has been removed from the reader)
-                localPrivateKey.getAlgorithm();
-            } catch (Exception e) {
-                invalidate();
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns the ID for this session.  The ID is fixed for the
-     * duration of the session; neither it, nor its value, changes.
-     */
-    public byte[] getId() {
-        return sessionId.getId();
-    }
-
-    /**
-     * For server sessions, this returns the set of sessions which
-     * are currently valid in this process.  For client sessions,
-     * this returns null.
-     */
-    public SSLSessionContext getSessionContext() {
-        /*
-         * An interim security policy until we can do something
-         * more specific in 1.2. Only allow trusted code (code which
-         * can set system properties) to get an
-         * SSLSessionContext. This is to limit the ability of code to
-         * look up specific sessions or enumerate over them. Otherwise,
-         * code can only get session objects from successful SSL
-         * connections which implies that they must have had permission
-         * to make the network connection in the first place.
-         */
-        SecurityManager sm;
-        if ((sm = System.getSecurityManager()) != null) {
-            sm.checkPermission(new SSLPermission("getSSLSessionContext"));
-        }
-
-        return context;
-    }
-
-
-    SessionId getSessionId() {
-        return sessionId;
-    }
-
-
-    /**
-     * Returns the cipher spec in use on this session
-     */
-    CipherSuite getSuite() {
-        return cipherSuite;
-    }
-
-    /**
-     * Resets the cipher spec in use on this session
-     */
-    void setSuite(CipherSuite suite) {
-       cipherSuite = suite;
-
-       if (debug != null && Debug.isOn("session")) {
-           System.out.println("%% Negotiating:  " + this);
-       }
-    }
-
-    /**
-     * Returns the name of the cipher suite in use on this session
-     */
-    public String getCipherSuite() {
-        return getSuite().name;
-    }
-
-    ProtocolVersion getProtocolVersion() {
-        return protocolVersion;
-    }
-
-    /**
-     * Returns the standard name of the protocol in use on this session
-     */
-    public String getProtocol() {
-        return getProtocolVersion().name;
-    }
-
-    /**
-     * Returns the compression technique used in this session
-     */
-    byte getCompression() {
-        return compressionMethod;
-    }
-
-    /**
-     * Returns the hashcode for this session
-     */
-    public int hashCode() {
-        return sessionId.hashCode();
-    }
-
-
-    /**
-     * Returns true if sessions have same ids, false otherwise.
-     */
-    public boolean equals(Object obj) {
-
-        if (obj == this) {
-            return true;
-        }
-
-        if (obj instanceof SSLSessionImpl) {
-            SSLSessionImpl sess = (SSLSessionImpl) obj;
-            return (sessionId != null) && (sessionId.equals(
-                        sess.getSessionId()));
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Return the cert chain presented by the peer in the
-     * java.security.cert format.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    public java.security.cert.Certificate[] getPeerCertificates()
-            throws SSLPeerUnverifiedException {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        //
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        // Certs are immutable objects, therefore we don't clone them.
-        // But do need to clone the array, so that nothing is inserted
-        // into peerCerts.
-        return (java.security.cert.Certificate[])peerCerts.clone();
-    }
-
-    /**
-     * Return the cert chain presented to the peer in the
-     * java.security.cert format.
-     * Note: This method is useful only when using certificate-based
-     * cipher suites.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    public java.security.cert.Certificate[] getLocalCertificates() {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        return (localCerts == null ? null :
-            (java.security.cert.Certificate[])localCerts.clone());
-    }
-
-    /**
-     * Return the cert chain presented by the peer in the
-     * javax.security.cert format.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
-            throws SSLPeerUnverifiedException {
-        //
-        // clone to preserve integrity of session ... caller can't
-        // change record of peer identity even by accident, much
-        // less do it intentionally.
-        //
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        javax.security.cert.X509Certificate[] certs;
-        certs = new javax.security.cert.X509Certificate[peerCerts.length];
-        for (int i = 0; i < peerCerts.length; i++) {
-            byte[] der = null;
-            try {
-                der = peerCerts[i].getEncoded();
-                certs[i] = javax.security.cert.X509Certificate.getInstance(der);
-            } catch (CertificateEncodingException e) {
-                throw new SSLPeerUnverifiedException(e.getMessage());
-            } catch (javax.security.cert.CertificateException e) {
-                throw new SSLPeerUnverifiedException(e.getMessage());
-            }
-        }
-
-        return certs;
-    }
-
-    /**
-     * Return the cert chain presented by the peer.
-     * Note: This method can be used only when using certificate-based
-     * cipher suites; using it with non-certificate-based cipher suites,
-     * such as Kerberos, will throw an SSLPeerUnverifiedException.
-     *
-     * @return array of peer X.509 certs, with the peer's own cert
-     *  first in the chain, and with the "root" CA last.
-     */
-    public X509Certificate[] getCertificateChain()
-            throws SSLPeerUnverifiedException {
-        /*
-         * clone to preserve integrity of session ... caller can't
-         * change record of peer identity even by accident, much
-         * less do it intentionally.
-         */
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            throw new SSLPeerUnverifiedException("no certificates expected"
-                        + " for Kerberos cipher suites");
-        }
-        if (peerCerts != null) {
-            return peerCerts.clone();
-        } else {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-    }
-
-    /**
-     * Returns the identity of the peer which was established as part of
-     * defining the session.
-     *
-     * @return the peer's principal. Returns an X500Principal of the
-     * end-entity certificate for X509-based cipher suites, and
-     * Principal for Kerberos cipher suites.
-     *
-     * @throws SSLPeerUnverifiedException if the peer's identity has not
-     *          been verified
-     */
-    public Principal getPeerPrincipal()
-                throws SSLPeerUnverifiedException
-    {
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-            if (peerPrincipal == null) {
-                throw new SSLPeerUnverifiedException("peer not authenticated");
-            } else {
-                // Eliminate dependency on KerberosPrincipal
-                return peerPrincipal;
-            }
-        }
-        if (peerCerts == null) {
-            throw new SSLPeerUnverifiedException("peer not authenticated");
-        }
-        return peerCerts[0].getSubjectX500Principal();
-    }
-
-    /**
-     * Returns the principal that was sent to the peer during handshaking.
-     *
-     * @return the principal sent to the peer. Returns an X500Principal
-     * of the end-entity certificate for X509-based cipher suites, and
-     * Principal for Kerberos cipher suites. If no principal was
-     * sent, then null is returned.
-     */
-    public Principal getLocalPrincipal() {
-
-        if ((cipherSuite.keyExchange == K_KRB5) ||
-            (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
-                // Eliminate dependency on KerberosPrincipal
-                return (localPrincipal == null ? null : localPrincipal);
-        }
-        return (localCerts == null ? null :
-                localCerts[0].getSubjectX500Principal());
-    }
-
-    /**
-     * Returns the time this session was created.
-     */
-    public long getCreationTime() {
-        return creationTime;
-    }
-
-    /**
-     * Returns the last time this session was used to initialize
-     * a connection.
-     */
-    public long getLastAccessedTime() {
-        return (lastUsedTime != 0) ? lastUsedTime : creationTime;
-    }
-
-    void setLastAccessedTime(long time) {
-        lastUsedTime = time;
-    }
-
-
-    /**
-     * Returns the network address of the session's peer.  This
-     * implementation does not insist that connections between
-     * different ports on the same host must necessarily belong
-     * to different sessions, though that is of course allowed.
-     */
-    public InetAddress getPeerAddress() {
-        try {
-            return InetAddress.getByName(host);
-        } catch (java.net.UnknownHostException e) {
-            return null;
-        }
-    }
-
-    public String getPeerHost() {
-        return host;
-    }
-
-    /**
-     * Need to provide the port info for caching sessions based on
-     * host and port. Accessed by SSLSessionContextImpl
-     */
-    public int getPeerPort() {
-        return port;
-    }
-
-    void setContext(SSLSessionContextImpl ctx) {
-        if (context == null) {
-            context = ctx;
-        }
-    }
-
-    /**
-     * Invalidate a session.  Active connections may still exist, but
-     * no connections will be able to rejoin this session.
-     */
-    synchronized public void invalidate() {
-        //
-        // Can't invalidate the NULL session -- this would be
-        // attempted when we get a handshaking error on a brand
-        // new connection, with no "real" session yet.
-        //
-        if (this == nullSession) {
-            return;
-        }
-        invalidated = true;
-        if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Invalidated:  " + this);
-        }
-        if (context != null) {
-            context.remove(sessionId);
-            context = null;
-        }
-    }
-
-    /*
-     * Table of application-specific session data indexed by an application
-     * key and the calling security context. This is important since
-     * sessions can be shared across different protection domains.
-     */
-    private Hashtable<SecureKey, Object> table = new Hashtable<>();
-
-    /**
-     * Assigns a session value.  Session change events are given if
-     * appropriate, to any original value as well as the new value.
-     */
-    public void putValue(String key, Object value) {
-        if ((key == null) || (value == null)) {
-            throw new IllegalArgumentException("arguments can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        Object oldValue = table.put(secureKey, value);
-
-        if (oldValue instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)oldValue).valueUnbound(e);
-        }
-        if (value instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)value).valueBound(e);
-        }
-    }
-
-
-    /**
-     * Returns the specified session value.
-     */
-    public Object getValue(String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("argument can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        return table.get(secureKey);
-    }
-
-
-    /**
-     * Removes the specified session value, delivering a session changed
-     * event as appropriate.
-     */
-    public void removeValue(String key) {
-        if (key == null) {
-            throw new IllegalArgumentException("argument can not be null");
-        }
-
-        SecureKey secureKey = new SecureKey(key);
-        Object value = table.remove(secureKey);
-
-        if (value instanceof SSLSessionBindingListener) {
-            SSLSessionBindingEvent e;
-
-            e = new SSLSessionBindingEvent(this, key);
-            ((SSLSessionBindingListener)value).valueUnbound(e);
-        }
-    }
-
-
-    /**
-     * Lists the names of the session values.
-     */
-    public String[] getValueNames() {
-        Enumeration<SecureKey> e;
-        Vector<Object> v = new Vector<>();
-        SecureKey key;
-        Object securityCtx = SecureKey.getCurrentSecurityContext();
-
-        for (e = table.keys(); e.hasMoreElements(); ) {
-            key = e.nextElement();
-
-            if (securityCtx.equals(key.getSecurityContext())) {
-                v.addElement(key.getAppKey());
-            }
-        }
-        String[] names = new String[v.size()];
-        v.copyInto(names);
-
-        return names;
-    }
-
-    /**
-     * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
-     * until changed.
-     *
-     * In the TLS specification (section 6.2.1, RFC2246), it is not
-     * recommended that the plaintext has more than 2^14 bytes.
-     * However, some TLS implementations violate the specification.
-     * This is a workaround for interoperability with these stacks.
-     *
-     * Application could accept large fragments up to 2^15 bytes by
-     * setting the system property jsse.SSLEngine.acceptLargeFragments
-     * to "true".
-     */
-    private boolean acceptLargeFragments =
-        Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false);
-
-    /**
-     * Expand the buffer size of both SSL/TLS network packet and
-     * application data.
-     */
-    protected synchronized void expandBufferSizes() {
-        acceptLargeFragments = true;
-    }
-
-    /**
-     * Gets the current size of the largest SSL/TLS packet that is expected
-     * when using this session.
-     */
-    public synchronized int getPacketBufferSize() {
-        return acceptLargeFragments ?
-                Record.maxLargeRecordSize : Record.maxRecordSize;
-    }
-
-    /**
-     * Gets the current size of the largest application data that is
-     * expected when using this session.
-     */
-    public synchronized int getApplicationBufferSize() {
-        return getPacketBufferSize() - Record.headerSize;
-    }
-
-    /**
-     * Gets an array of supported signature algorithms that the local side is
-     * willing to verify.
-     */
-    public String[] getLocalSupportedSignatureAlgorithms() {
-        if (localSupportedSignAlgs != null) {
-            return localSupportedSignAlgs.clone();
-        }
-
-        return new String[0];
-    }
-
-    /**
-     * Gets an array of supported signature algorithms that the peer is
-     * able to verify.
-     */
-    public String[] getPeerSupportedSignatureAlgorithms() {
-        if (peerSupportedSignAlgs != null) {
-            return peerSupportedSignAlgs.clone();
-        }
-
-        return new String[0];
-    }
-
-    /** Returns a string representation of this SSL session */
-    public String toString() {
-        return "[Session-" + sessionCount
-            + ", " + getCipherSuite()
-            + "]";
-    }
-
-    /**
-     * When SSL sessions are finalized, all values bound to
-     * them are removed.
-     */
-    public void finalize() {
-        String[] names = getValueNames();
-        for (int i = 0; i < names.length; i++) {
-            removeValue(names[i]);
-        }
-    }
-}
-
-
-/**
- * This "struct" class serves as a Hash Key that combines an
- * application-specific key and a security context.
- */
-class SecureKey {
-    private static Object       nullObject = new Object();
-    private Object        appKey;
-    private Object      securityCtx;
-
-    static Object getCurrentSecurityContext() {
-        SecurityManager sm = System.getSecurityManager();
-        Object context = null;
-
-        if (sm != null)
-            context = sm.getSecurityContext();
-        if (context == null)
-            context = nullObject;
-        return context;
-    }
-
-    SecureKey(Object key) {
-        this.appKey = key;
-        this.securityCtx = getCurrentSecurityContext();
-    }
-
-    Object getAppKey() {
-        return appKey;
-    }
-
-    Object getSecurityContext() {
-        return securityCtx;
-    }
-
-    public int hashCode() {
-        return appKey.hashCode() ^ securityCtx.hashCode();
-    }
-
-    public boolean equals(Object o) {
-        return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
-                        && ((SecureKey)o).securityCtx.equals(securityCtx);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java
deleted file mode 100755
index 135b462..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.SSLSocket;
-
-
-/**
- * Implementation of an SSL socket factory.  This provides the public
- * hooks to create SSL sockets, using a "high level" programming
- * interface which encapsulates system security policy defaults rather than
- * offering application flexibility.  In particular, it uses a configurable
- * authentication context (and the keys held there) rather than offering
- * any flexibility about which keys to use; that context defaults to the
- * process-default context, but may be explicitly specified.
- *
- * @author David Brownell
- */
-final public class SSLSocketFactoryImpl extends SSLSocketFactory {
-
-    private static SSLContextImpl defaultContext;
-    private SSLContextImpl context;
-
-    /**
-     * Constructor used to instantiate the default factory. This method is
-     * only called if the old "ssl.SocketFactory.provider" property in the
-     * java.security file is set.
-     */
-    public SSLSocketFactoryImpl() throws Exception {
-        this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
-    }
-
-    /**
-     * Constructs an SSL socket factory.
-     */
-    SSLSocketFactoryImpl(SSLContextImpl context) {
-        this.context = context;
-    }
-
-    /**
-     * Creates an unconnected socket.
-     *
-     * @return the unconnected socket
-     * @see java.net.Socket#connect(java.net.SocketAddress, int)
-     */
-    public Socket createSocket() {
-        return new SSLSocketImpl(context);
-    }
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port.
-     * This acts as the SSL client, and may authenticate itself or rejoin
-     * existing SSL sessions allowed by the authentication context which
-     * has been configured.
-     *
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     */
-    public Socket createSocket(String host, int port)
-    throws IOException, UnknownHostException
-    {
-        return new SSLSocketImpl(context, host, port);
-    }
-
-    /**
-     * Returns a socket layered over an existing socket to a
-     * ServerSocket on the named host, at the given port.  This
-     * constructor can be used when tunneling SSL through a proxy. The
-     * host and port refer to the logical destination server.  This
-     * socket is configured using the socket options established for
-     * this factory.
-     *
-     * @param s the existing socket
-     * @param host the server host
-     * @param port the server port
-     * @param autoClose close the underlying socket when this socket is closed
-     *
-     * @exception IOException if the connection can't be established
-     * @exception UnknownHostException if the host is not known
-     */
-    public Socket createSocket(Socket s, String host, int port,
-            boolean autoClose) throws IOException {
-        return new SSLSocketImpl(context, s, host, port, autoClose);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a server at a specified address
-     * and TCP port.  This acts as the SSL client, and may authenticate
-     * itself or rejoin existing SSL sessions allowed by the authentication
-     * context which has been configured.
-     *
-     * @param address the server's host
-     * @param port its port
-     */
-    public Socket createSocket(InetAddress address, int port)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, address, port);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port.
-     * This acts as the SSL client, and may authenticate itself or rejoin
-     * existing SSL sessions allowed by the authentication context which
-     * has been configured. The socket will also bind() to the local
-     * address and port supplied.
-     */
-    public Socket createSocket(String host, int port,
-        InetAddress clientAddress, int clientPort)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, host, port,
-                clientAddress, clientPort);
-    }
-
-    /**
-     * Constructs an SSL connection to a server at a specified address
-     * and TCP port.  This acts as the SSL client, and may authenticate
-     * itself or rejoin existing SSL sessions allowed by the authentication
-     * context which has been configured. The socket will also bind() to
-     * the local address and port supplied.
-     */
-    public Socket createSocket(InetAddress address, int port,
-        InetAddress clientAddress, int clientPort)
-    throws IOException
-    {
-        return new SSLSocketImpl(context, address, port,
-                clientAddress, clientPort);
-    }
-
-
-    /**
-     * Returns the subset of the supported cipher suites which are
-     * enabled by default.  These cipher suites all provide a minimum
-     * quality of service whereby the server authenticates itself
-     * (preventing person-in-the-middle attacks) and where traffic
-     * is encrypted to provide confidentiality.
-     */
-    public String[] getDefaultCipherSuites() {
-        return context.getDefaultCipherSuiteList(false).toStringArray();
-    }
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     */
-    public String[] getSupportedCipherSuites() {
-        return context.getSupportedCipherSuiteList().toStringArray();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java
deleted file mode 100755
index 37158fb..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java
+++ /dev/null
@@ -1,2545 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import java.security.GeneralSecurityException;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.PrivilegedAction;
-import java.security.AlgorithmConstraints;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
-/**
- * Implementation of an SSL socket.  This is a normal connection type
- * socket, implementing SSL over some lower level socket, such as TCP.
- * Because it is layered over some lower level socket, it MUST override
- * all default socket methods.
- *
- * <P> This API offers a non-traditional option for establishing SSL
- * connections.  You may first establish the connection directly, then pass
- * that connection to the SSL socket constructor with a flag saying which
- * role should be taken in the handshake protocol.  (The two ends of the
- * connection must not choose the same role!)  This allows setup of SSL
- * proxying or tunneling, and also allows the kind of "role reversal"
- * that is required for most FTP data transfers.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLServerSocket
- *
- * @author David Brownell
- */
-final public class SSLSocketImpl extends BaseSSLSocketImpl {
-
-    /*
-     * ERROR HANDLING GUIDELINES
-     * (which exceptions to throw and catch and which not to throw and catch)
-     *
-     * . if there is an IOException (SocketException) when accessing the
-     *   underlying Socket, pass it through
-     *
-     * . do not throw IOExceptions, throw SSLExceptions (or a subclass)
-     *
-     * . for internal errors (things that indicate a bug in JSSE or a
-     *   grossly misconfigured J2RE), throw either an SSLException or
-     *   a RuntimeException at your convenience.
-     *
-     * . handshaking code (Handshaker or HandshakeMessage) should generally
-     *   pass through exceptions, but can handle them if they know what to
-     *   do.
-     *
-     * . exception chaining should be used for all new code. If you happen
-     *   to touch old code that does not use chaining, you should change it.
-     *
-     * . there is a top level exception handler that sits at all entry
-     *   points from application code to SSLSocket read/write code. It
-     *   makes sure that all errors are handled (see handleException()).
-     *
-     * . JSSE internal code should generally not call close(), call
-     *   closeInternal().
-     */
-
-    /*
-     * There's a state machine associated with each connection, which
-     * among other roles serves to negotiate session changes.
-     *
-     * - START with constructor, until the TCP connection's around.
-     * - HANDSHAKE picks session parameters before allowing traffic.
-     *          There are many substates due to sequencing requirements
-     *          for handshake messages.
-     * - DATA may be transmitted.
-     * - RENEGOTIATE state allows concurrent data and handshaking
-     *          traffic ("same" substates as HANDSHAKE), and terminates
-     *          in selection of new session (and connection) parameters
-     * - ERROR state immediately precedes abortive disconnect.
-     * - SENT_CLOSE sent a close_notify to the peer. For layered,
-     *          non-autoclose socket, must now read close_notify
-     *          from peer before closing the connection. For nonlayered or
-     *          non-autoclose socket, close connection and go onto
-     *          cs_CLOSED state.
-     * - CLOSED after sending close_notify alert, & socket is closed.
-     *          SSL connection objects are not reused.
-     * - APP_CLOSED once the application calls close(). Then it behaves like
-     *          a closed socket, e.g.. getInputStream() throws an Exception.
-     *
-     * State affects what SSL record types may legally be sent:
-     *
-     * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
-     * - App Data ... only in DATA and RENEGOTIATE states
-     * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
-     *
-     * Re what may be received:  same as what may be sent, except that
-     * HandshakeRequest handshaking messages can come from servers even
-     * in the application data state, to request entry to RENEGOTIATE.
-     *
-     * The state machine within HANDSHAKE and RENEGOTIATE states controls
-     * the pending session, not the connection state, until the change
-     * cipher spec and "Finished" handshake messages are processed and
-     * make the "new" session become the current one.
-     *
-     * NOTE: details of the SMs always need to be nailed down better.
-     * The text above illustrates the core ideas.
-     *
-     *                +---->-------+------>--------->-------+
-     *                |            |                        |
-     *     <-----<    ^            ^  <-----<               v
-     *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE  SENT_CLOSE
-     *                v            v               v        |   |
-     *                |            |               |        |   v
-     *                +------------+---------------+        v ERROR
-     *                |                                     |   |
-     *                v                                     |   |
-     *               ERROR>------>----->CLOSED<--------<----+-- +
-     *                                     |
-     *                                     v
-     *                                 APP_CLOSED
-     *
-     * ALSO, note that the the purpose of handshaking (renegotiation is
-     * included) is to assign a different, and perhaps new, session to
-     * the connection.  The SSLv3 spec is a bit confusing on that new
-     * protocol feature.
-     */
-    private static final int    cs_START = 0;
-    private static final int    cs_HANDSHAKE = 1;
-    private static final int    cs_DATA = 2;
-    private static final int    cs_RENEGOTIATE = 3;
-    private static final int    cs_ERROR = 4;
-    private static final int   cs_SENT_CLOSE = 5;
-    private static final int    cs_CLOSED = 6;
-    private static final int    cs_APP_CLOSED = 7;
-
-
-    /*
-     * Client authentication be off, requested, or required.
-     *
-     * Migrated to SSLEngineImpl:
-     *    clauth_none/cl_auth_requested/clauth_required
-     */
-
-    /*
-     * Drives the protocol state machine.
-     */
-    private int                 connectionState;
-
-    /*
-     * Flag indicating if the next record we receive MUST be a Finished
-     * message. Temporarily set during the handshake to ensure that
-     * a change cipher spec message is followed by a finished message.
-     */
-    private boolean             expectingFinished;
-
-    /*
-     * For improved diagnostics, we detail connection closure
-     * If the socket is closed (connectionState >= cs_ERROR),
-     * closeReason != null indicates if the socket was closed
-     * because of an error or because or normal shutdown.
-     */
-    private SSLException        closeReason;
-
-    /*
-     * Per-connection private state that doesn't change when the
-     * session is changed.
-     */
-    private byte                doClientAuth;
-    private boolean             roleIsServer;
-    private boolean             enableSessionCreation = true;
-    private String              host;
-    private boolean             autoClose = true;
-    private AccessControlContext acc;
-
-    /*
-     * We cannot use the hostname resolved from name services.  For
-     * virtual hosting, multiple hostnames may be bound to the same IP
-     * address, so the hostname resolved from name services is not
-     * reliable.
-     */
-    private String              rawHostname;
-
-    // The cipher suites enabled for use on this connection.
-    private CipherSuiteList     enabledCipherSuites;
-
-    // The endpoint identification protocol
-    private String              identificationProtocol = null;
-
-    // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
-
-    /*
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
-     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
-     *
-     * There are several locks here.
-     *
-     * The primary lock is the per-instance lock used by
-     * synchronized(this) and the synchronized methods.  It controls all
-     * access to things such as the connection state and variables which
-     * affect handshaking.  If we are inside a synchronized method, we
-     * can access the state directly, otherwise, we must use the
-     * synchronized equivalents.
-     *
-     * The handshakeLock is used to ensure that only one thread performs
-     * the *complete initial* handshake.  If someone is handshaking, any
-     * stray application or startHandshake() requests who find the
-     * connection state is cs_HANDSHAKE will stall on handshakeLock
-     * until handshaking is done.  Once the handshake is done, we either
-     * succeeded or failed, but we can never go back to the cs_HANDSHAKE
-     * or cs_START state again.
-     *
-     * Note that the read/write() calls here in SSLSocketImpl are not
-     * obviously synchronized.  In fact, it's very nonintuitive, and
-     * requires careful examination of code paths.  Grab some coffee,
-     * and be careful with any code changes.
-     *
-     * There can be only three threads active at a time in the I/O
-     * subsection of this class.
-     *    1.  startHandshake
-     *    2.  AppInputStream
-     *    3.  AppOutputStream
-     * One thread could call startHandshake().
-     * AppInputStream/AppOutputStream read() and write() calls are each
-     * synchronized on 'this' in their respective classes, so only one
-     * app. thread will be doing a SSLSocketImpl.read() or .write()'s at
-     * a time.
-     *
-     * If handshaking is required (state cs_HANDSHAKE), and
-     * getConnectionState() for some/all threads returns cs_HANDSHAKE,
-     * only one can grab the handshakeLock, and the rest will stall
-     * either on getConnectionState(), or on the handshakeLock if they
-     * happen to successfully race through the getConnectionState().
-     *
-     * If a writer is doing the initial handshaking, it must create a
-     * temporary reader to read the responses from the other side.  As a
-     * side-effect, the writer's reader will have priority over any
-     * other reader.  However, the writer's reader is not allowed to
-     * consume any application data.  When handshakeLock is finally
-     * released, we either have a cs_DATA connection, or a
-     * cs_CLOSED/cs_ERROR socket.
-     *
-     * The writeLock is held while writing on a socket connection and
-     * also to protect the MAC and cipher for their direction.  The
-     * writeLock is package private for Handshaker which holds it while
-     * writing the ChangeCipherSpec message.
-     *
-     * To avoid the problem of a thread trying to change operational
-     * modes on a socket while handshaking is going on, we synchronize
-     * on 'this'.  If handshaking has not started yet, we tell the
-     * handshaker to change its mode.  If handshaking has started,
-     * we simply store that request until the next pending session
-     * is created, at which time the new handshaker's state is set.
-     *
-     * The readLock is held during readRecord(), which is responsible
-     * for reading an InputRecord, decrypting it, and processing it.
-     * The readLock ensures that these three steps are done atomically
-     * and that once started, no other thread can block on InputRecord.read.
-     * This is necessary so that processing of close_notify alerts
-     * from the peer are handled properly.
-     */
-    final private Object        handshakeLock = new Object();
-    final ReentrantLock         writeLock = new ReentrantLock();
-    final private Object        readLock = new Object();
-
-    private InputRecord         inrec;
-
-    /*
-     * Crypto state that's reinitialized when the session changes.
-     */
-    private MAC                 readMAC, writeMAC;
-    private CipherBox           readCipher, writeCipher;
-    // NOTE: compression state would be saved here
-
-    /*
-     * security parameters for secure renegotiation.
-     */
-    private boolean             secureRenegotiation;
-    private byte[]              clientVerifyData;
-    private byte[]              serverVerifyData;
-
-    /*
-     * The authentication context holds all information used to establish
-     * who this end of the connection is (certificate chains, private keys,
-     * etc) and who is trusted (e.g. as CAs or websites).
-     */
-    private SSLContextImpl      sslContext;
-
-
-    /*
-     * This connection is one of (potentially) many associated with
-     * any given session.  The output of the handshake protocol is a
-     * new session ... although all the protocol description talks
-     * about changing the cipher spec (and it does change), in fact
-     * that's incidental since it's done by changing everything that
-     * is associated with a session at the same time.  (TLS/IETF may
-     * change that to add client authentication w/o new key exchg.)
-     */
-    private Handshaker                  handshaker;
-    private SSLSessionImpl              sess;
-    private volatile SSLSessionImpl     handshakeSession;
-
-
-    /*
-     * If anyone wants to get notified about handshake completions,
-     * they'll show up on this list.
-     */
-    private HashMap<HandshakeCompletedListener, AccessControlContext>
-                                                        handshakeListeners;
-
-    /*
-     * Reuse the same internal input/output streams.
-     */
-    private InputStream         sockInput;
-    private OutputStream        sockOutput;
-
-
-    /*
-     * These input and output streams block their data in SSL records,
-     * and usually arrange integrity and privacy protection for those
-     * records.  The guts of the SSL protocol are wrapped up in these
-     * streams, and in the handshaking that establishes the details of
-     * that integrity and privacy protection.
-     */
-    private AppInputStream      input;
-    private AppOutputStream     output;
-
-    /*
-     * The protocol versions enabled for use on this connection.
-     *
-     * Note: we support a pseudo protocol called SSLv2Hello which when
-     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
-     * or TLS (version 3.1, 3.2, etc.) version info.
-     */
-    private ProtocolList enabledProtocols;
-
-    /*
-     * The SSL version associated with this connection.
-     */
-    private ProtocolVersion     protocolVersion = ProtocolVersion.DEFAULT;
-
-    /* Class and subclass dynamic debugging support */
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    /*
-     * Is it the first application record to write?
-     */
-    private boolean isFirstAppOutputRecord = true;
-
-    /*
-     * If AppOutputStream needs to delay writes of small packets, we
-     * will use this to store the data until we actually do the write.
-     */
-    private ByteArrayOutputStream heldRecordBuffer = null;
-
-    //
-    // CONSTRUCTORS AND INITIALIZATION CODE
-    //
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port,
-     * using the authentication context provided.  This endpoint acts as
-     * the client, and may rejoin an existing SSL session if appropriate.
-     *
-     * @param context authentication context to use
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     */
-    SSLSocketImpl(SSLContextImpl context, String host, int port)
-            throws IOException, UnknownHostException {
-        super();
-        this.host = host;
-        this.rawHostname = host;
-        init(context, false);
-        SocketAddress socketAddress =
-               host != null ? new InetSocketAddress(host, port) :
-               new InetSocketAddress(InetAddress.getByName(null), port);
-        connect(socketAddress, 0);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a server at a specified address.
-     * and TCP port, using the authentication context provided.  This
-     * endpoint acts as the client, and may rejoin an existing SSL session
-     * if appropriate.
-     *
-     * @param context authentication context to use
-     * @param address the server's host
-     * @param port its port
-     */
-    SSLSocketImpl(SSLContextImpl context, InetAddress host, int port)
-            throws IOException {
-        super();
-        init(context, false);
-        SocketAddress socketAddress = new InetSocketAddress(host, port);
-        connect(socketAddress, 0);
-    }
-
-    /**
-     * Constructs an SSL connection to a named host at a specified port,
-     * using the authentication context provided.  This endpoint acts as
-     * the client, and may rejoin an existing SSL session if appropriate.
-     *
-     * @param context authentication context to use
-     * @param host name of the host with which to connect
-     * @param port number of the server's port
-     * @param localAddr the local address the socket is bound to
-     * @param localPort the local port the socket is bound to
-     */
-    SSLSocketImpl(SSLContextImpl context, String host, int port,
-            InetAddress localAddr, int localPort)
-            throws IOException, UnknownHostException {
-        super();
-        this.host = host;
-        this.rawHostname = host;
-        init(context, false);
-        bind(new InetSocketAddress(localAddr, localPort));
-        SocketAddress socketAddress =
-               host != null ? new InetSocketAddress(host, port) :
-               new InetSocketAddress(InetAddress.getByName(null), port);
-        connect(socketAddress, 0);
-    }
-
-
-    /**
-     * Constructs an SSL connection to a server at a specified address.
-     * and TCP port, using the authentication context provided.  This
-     * endpoint acts as the client, and may rejoin an existing SSL session
-     * if appropriate.
-     *
-     * @param context authentication context to use
-     * @param address the server's host
-     * @param port its port
-     * @param localAddr the local address the socket is bound to
-     * @param localPort the local port the socket is bound to
-     */
-    SSLSocketImpl(SSLContextImpl context, InetAddress host, int port,
-            InetAddress localAddr, int localPort)
-            throws IOException {
-        super();
-        init(context, false);
-        bind(new InetSocketAddress(localAddr, localPort));
-        SocketAddress socketAddress = new InetSocketAddress(host, port);
-        connect(socketAddress, 0);
-    }
-
-    /*
-     * Package-private constructor used ONLY by SSLServerSocket.  The
-     * java.net package accepts the TCP connection after this call is
-     * made.  This just initializes handshake state to use "server mode",
-     * giving control over the use of SSL client authentication.
-     */
-    SSLSocketImpl(SSLContextImpl context, boolean serverMode,
-            CipherSuiteList suites, byte clientAuth,
-            boolean sessionCreation, ProtocolList protocols,
-            String identificationProtocol,
-            AlgorithmConstraints algorithmConstraints) throws IOException {
-
-        super();
-        doClientAuth = clientAuth;
-        enableSessionCreation = sessionCreation;
-        this.identificationProtocol = identificationProtocol;
-        this.algorithmConstraints = algorithmConstraints;
-        init(context, serverMode);
-
-        /*
-         * Override what was picked out for us.
-         */
-        enabledCipherSuites = suites;
-        enabledProtocols = protocols;
-    }
-
-
-    /**
-     * Package-private constructor used to instantiate an unconnected
-     * socket. The java.net package will connect it, either when the
-     * connect() call is made by the application.  This instance is
-     * meant to set handshake state to use "client mode".
-     */
-    SSLSocketImpl(SSLContextImpl context) {
-        super();
-        init(context, false);
-    }
-
-
-    /**
-     * Layer SSL traffic over an existing connection, rather than creating
-     * a new connection.  The existing connection may be used only for SSL
-     * traffic (using this SSLSocket) until the SSLSocket.close() call
-     * returns. However, if a protocol error is detected, that existing
-     * connection is automatically closed.
-     *
-     * <P> This particular constructor always uses the socket in the
-     * role of an SSL client. It may be useful in cases which start
-     * using SSL after some initial data transfers, for example in some
-     * SSL tunneling applications or as part of some kinds of application
-     * protocols which negotiate use of a SSL based security.
-     *
-     * @param sock the existing connection
-     * @param context the authentication context to use
-     */
-    SSLSocketImpl(SSLContextImpl context, Socket sock, String host,
-            int port, boolean autoClose) throws IOException {
-        super(sock);
-        // We always layer over a connected socket
-        if (!sock.isConnected()) {
-            throw new SocketException("Underlying socket is not connected");
-        }
-        this.host = host;
-        this.rawHostname = host;
-        init(context, false);
-        this.autoClose = autoClose;
-        doneConnect();
-    }
-
-    /**
-     * Initializes the client socket.
-     */
-    private void init(SSLContextImpl context, boolean isServer) {
-        sslContext = context;
-        sess = SSLSessionImpl.nullSession;
-        handshakeSession = null;
-
-        /*
-         * role is as specified, state is START until after
-         * the low level connection's established.
-         */
-        roleIsServer = isServer;
-        connectionState = cs_START;
-
-        /*
-         * default read and write side cipher and MAC support
-         *
-         * Note:  compression support would go here too
-         */
-        readCipher = CipherBox.NULL;
-        readMAC = MAC.NULL;
-        writeCipher = CipherBox.NULL;
-        writeMAC = MAC.NULL;
-
-        // initial security parameters for secure renegotiation
-        secureRenegotiation = false;
-        clientVerifyData = new byte[0];
-        serverVerifyData = new byte[0];
-
-        enabledCipherSuites =
-                sslContext.getDefaultCipherSuiteList(roleIsServer);
-        enabledProtocols =
-                sslContext.getDefaultProtocolList(roleIsServer);
-
-        inrec = null;
-
-        // save the acc
-        acc = AccessController.getContext();
-
-        input = new AppInputStream(this);
-        output = new AppOutputStream(this);
-    }
-
-    /**
-     * Connects this socket to the server with a specified timeout
-     * value.
-     *
-     * This method is either called on an unconnected SSLSocketImpl by the
-     * application, or it is called in the constructor of a regular
-     * SSLSocketImpl. If we are layering on top on another socket, then
-     * this method should not be called, because we assume that the
-     * underlying socket is already connected by the time it is passed to
-     * us.
-     *
-     * @param   endpoint the <code>SocketAddress</code>
-     * @param   timeout  the timeout value to be used, 0 is no timeout
-     * @throws  IOException if an error occurs during the connection
-     * @throws  SocketTimeoutException if timeout expires before connecting
-     */
-    public void connect(SocketAddress endpoint, int timeout)
-            throws IOException {
-
-        if (self != this) {
-            throw new SocketException("Already connected");
-        }
-
-        if (!(endpoint instanceof InetSocketAddress)) {
-            throw new SocketException(
-                                  "Cannot handle non-Inet socket addresses.");
-        }
-
-        super.connect(endpoint, timeout);
-        doneConnect();
-    }
-
-    /**
-     * Initialize the handshaker and socket streams.
-     *
-     * Called by connect, the layered constructor, and SSLServerSocket.
-     */
-    void doneConnect() throws IOException {
-        /*
-         * Save the input and output streams.  May be done only after
-         * java.net actually connects using the socket "self", else
-         * we get some pretty bizarre failure modes.
-         */
-        if (self == this) {
-            sockInput = super.getInputStream();
-            sockOutput = super.getOutputStream();
-        } else {
-            sockInput = self.getInputStream();
-            sockOutput = self.getOutputStream();
-        }
-
-        /*
-         * Move to handshaking state, with pending session initialized
-         * to defaults and the appropriate kind of handshaker set up.
-         */
-        initHandshaker();
-    }
-
-    synchronized private int getConnectionState() {
-        return connectionState;
-    }
-
-    synchronized private void setConnectionState(int state) {
-        connectionState = state;
-    }
-
-    AccessControlContext getAcc() {
-        return acc;
-    }
-
-    //
-    // READING AND WRITING RECORDS
-    //
-
-    /*
-     * AppOutputStream calls may need to buffer multiple outbound
-     * application packets.
-     *
-     * All other writeRecord() calls will not buffer, so do not hold
-     * these records.
-     */
-    void writeRecord(OutputRecord r) throws IOException {
-        writeRecord(r, false);
-    }
-
-    /*
-     * Record Output. Application data can't be sent until the first
-     * handshake establishes a session.
-     *
-     * NOTE:  we let empty records be written as a hook to force some
-     * TCP-level activity, notably handshaking, to occur.
-     */
-    void writeRecord(OutputRecord r, boolean holdRecord) throws IOException {
-        /*
-         * The loop is in case of HANDSHAKE --> ERROR transitions, etc
-         */
-    loop:
-        while (r.contentType() == Record.ct_application_data) {
-            /*
-             * Not all states support passing application data.  We
-             * synchronize access to the connection state, so that
-             * synchronous handshakes can complete cleanly.
-             */
-            switch (getConnectionState()) {
-
-            /*
-             * We've deferred the initial handshaking till just now,
-             * when presumably a thread's decided it's OK to block for
-             * longish periods of time for I/O purposes (as well as
-             * configured the cipher suites it wants to use).
-             */
-            case cs_HANDSHAKE:
-                performInitialHandshake();
-                break;
-
-            case cs_DATA:
-            case cs_RENEGOTIATE:
-                break loop;
-
-            case cs_ERROR:
-                fatal(Alerts.alert_close_notify,
-                    "error while writing to socket");
-                break; // dummy
-
-            case cs_SENT_CLOSE:
-            case cs_CLOSED:
-            case cs_APP_CLOSED:
-                // we should never get here (check in AppOutputStream)
-                // this is just a fallback
-                if (closeReason != null) {
-                    throw closeReason;
-                } else {
-                    throw new SocketException("Socket closed");
-                }
-
-            /*
-             * Else something's goofy in this state machine's use.
-             */
-            default:
-                throw new SSLProtocolException("State error, send app data");
-            }
-        }
-
-        //
-        // Don't bother to really write empty records.  We went this
-        // far to drive the handshake machinery, for correctness; not
-        // writing empty records improves performance by cutting CPU
-        // time and network resource usage.  However, some protocol
-        // implementations are fragile and don't like to see empty
-        // records, so this also increases robustness.
-        //
-        if (!r.isEmpty()) {
-
-            // If the record is a close notify alert, we need to honor
-            // socket option SO_LINGER. Note that we will try to send
-            // the close notify even if the SO_LINGER set to zero.
-            if (r.isAlert(Alerts.alert_close_notify) && getSoLinger() >= 0) {
-
-                // keep and clear the current thread interruption status.
-                boolean interrupted = Thread.interrupted();
-                try {
-                    if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
-                        try {
-                            writeRecordInternal(r, holdRecord);
-                        } finally {
-                            writeLock.unlock();
-                        }
-                    } else {
-                        SSLException ssle = new SSLException(
-                                "SO_LINGER timeout," +
-                                " close_notify message cannot be sent.");
-
-
-                        // For layered, non-autoclose sockets, we are not
-                        // able to bring them into a usable state, so we
-                        // treat it as fatal error.
-                        if (self != this && !autoClose) {
-                            // Note that the alert description is
-                            // specified as -1, so no message will be send
-                            // to peer anymore.
-                            fatal((byte)(-1), ssle);
-                        } else if ((debug != null) && Debug.isOn("ssl")) {
-                            System.out.println(threadName() +
-                                ", received Exception: " + ssle);
-                        }
-
-                        // RFC2246 requires that the session becomes
-                        // unresumable if any connection is terminated
-                        // without proper close_notify messages with
-                        // level equal to warning.
-                        //
-                        // RFC4346 no longer requires that a session not be
-                        // resumed if failure to properly close a connection.
-                        //
-                        // We choose to make the session unresumable if
-                        // failed to send the close_notify message.
-                        //
-                        sess.invalidate();
-                    }
-                } catch (InterruptedException ie) {
-                    // keep interrupted status
-                    interrupted = true;
-                }
-
-                // restore the interrupted status
-                if (interrupted) {
-                    Thread.currentThread().interrupt();
-                }
-            } else {
-                writeLock.lock();
-                try {
-                    writeRecordInternal(r, holdRecord);
-                } finally {
-                    writeLock.unlock();
-                }
-            }
-        }
-    }
-
-    private void writeRecordInternal(OutputRecord r,
-            boolean holdRecord) throws IOException {
-        // r.compress(c);
-        r.addMAC(writeMAC);
-        r.encrypt(writeCipher);
-
-        if (holdRecord) {
-            // If we were requested to delay the record due to possibility
-            // of Nagle's being active when finally got to writing, and
-            // it's actually not, we don't really need to delay it.
-            if (getTcpNoDelay()) {
-                holdRecord = false;
-            } else {
-                // We need to hold the record, so let's provide
-                // a per-socket place to do it.
-                if (heldRecordBuffer == null) {
-                    // Likely only need 37 bytes.
-                    heldRecordBuffer = new ByteArrayOutputStream(40);
-                }
-            }
-        }
-        r.write(sockOutput, holdRecord, heldRecordBuffer);
-
-        /*
-         * Check the sequence number state
-         *
-         * Note that in order to maintain the connection I/O
-         * properly, we check the sequence number after the last
-         * record writing process. As we request renegotiation
-         * or close the connection for wrapped sequence number
-         * when there is enough sequence number space left to
-         * handle a few more records, so the sequence number
-         * of the last record cannot be wrapped.
-         */
-        if (connectionState < cs_ERROR) {
-            checkSequenceNumber(writeMAC, r.contentType());
-        }
-
-        // turn off the flag of the first application record
-        if (isFirstAppOutputRecord &&
-                r.contentType() == Record.ct_application_data) {
-            isFirstAppOutputRecord = false;
-        }
-    }
-
-    /*
-     * Need to split the payload except the following cases:
-     *
-     * 1. protocol version is TLS 1.1 or later;
-     * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
-     * 3. the payload is the first application record of a freshly
-     *    negotiated TLS session.
-     * 4. the CBC protection is disabled;
-     *
-     * More details, please refer to AppOutputStream.write(byte[], int, int).
-     */
-    boolean needToSplitPayload() {
-        writeLock.lock();
-        try {
-            return (protocolVersion.v <= ProtocolVersion.TLS10.v) &&
-                    writeCipher.isCBCMode() && !isFirstAppOutputRecord &&
-                    Record.enableCBCProtection;
-        } finally {
-            writeLock.unlock();
-        }
-    }
-
-    /*
-     * Read an application data record.  Alerts and handshake
-     * messages are handled directly.
-     */
-    void readDataRecord(InputRecord r) throws IOException {
-        if (getConnectionState() == cs_HANDSHAKE) {
-            performInitialHandshake();
-        }
-        readRecord(r, true);
-    }
-
-
-    /*
-     * Clear the pipeline of records from the peer, optionally returning
-     * application data.   Caller is responsible for knowing that it's
-     * possible to do this kind of clearing, if they don't want app
-     * data -- e.g. since it's the initial SSL handshake.
-     *
-     * Don't synchronize (this) during a blocking read() since it
-     * protects data which is accessed on the write side as well.
-     */
-    private void readRecord(InputRecord r, boolean needAppData)
-            throws IOException {
-        int state;
-
-        // readLock protects reading and processing of an InputRecord.
-        // It keeps the reading from sockInput and processing of the record
-        // atomic so that no two threads can be blocked on the
-        // read from the same input stream at the same time.
-        // This is required for example when a reader thread is
-        // blocked on the read and another thread is trying to
-        // close the socket. For a non-autoclose, layered socket,
-        // the thread performing the close needs to read the close_notify.
-        //
-        // Use readLock instead of 'this' for locking because
-        // 'this' also protects data accessed during writing.
-      synchronized (readLock) {
-        /*
-         * Read and handle records ... return application data
-         * ONLY if it's needed.
-         */
-
-        while (((state = getConnectionState()) != cs_CLOSED) &&
-                (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
-            /*
-             * Read a record ... maybe emitting an alert if we get a
-             * comprehensible but unsupported "hello" message during
-             * format checking (e.g. V2).
-             */
-            try {
-                r.setAppDataValid(false);
-                r.read(sockInput, sockOutput);
-            } catch (SSLProtocolException e) {
-                try {
-                    fatal(Alerts.alert_unexpected_message, e);
-                } catch (IOException x) {
-                    // discard this exception
-                }
-                throw e;
-            } catch (EOFException eof) {
-                boolean handshaking = (getConnectionState() <= cs_HANDSHAKE);
-                boolean rethrow = requireCloseNotify || handshaking;
-                if ((debug != null) && Debug.isOn("ssl")) {
-                    System.out.println(threadName() +
-                        ", received EOFException: "
-                        + (rethrow ? "error" : "ignored"));
-                }
-                if (rethrow) {
-                    SSLException e;
-                    if (handshaking) {
-                        e = new SSLHandshakeException
-                            ("Remote host closed connection during handshake");
-                    } else {
-                        e = new SSLProtocolException
-                            ("Remote host closed connection incorrectly");
-                    }
-                    e.initCause(eof);
-                    throw e;
-                } else {
-                    // treat as if we had received a close_notify
-                    closeInternal(false);
-                    continue;
-                }
-            }
-
-
-            /*
-             * The basic SSLv3 record protection involves (optional)
-             * encryption for privacy, and an integrity check ensuring
-             * data origin authentication.  We do them both here, and
-             * throw a fatal alert if the integrity check fails.
-             */
-            try {
-                r.decrypt(readMAC, readCipher);
-            } catch (BadPaddingException e) {
-                byte alertType = (r.contentType() == Record.ct_handshake)
-                                        ? Alerts.alert_handshake_failure
-                                        : Alerts.alert_bad_record_mac;
-                fatal(alertType, e.getMessage(), e);
-            }
-
-            // if (!r.decompress(c))
-            //     fatal(Alerts.alert_decompression_failure,
-            //         "decompression failure");
-
-            /*
-             * Process the record.
-             */
-            synchronized (this) {
-              switch (r.contentType()) {
-                case Record.ct_handshake:
-                    /*
-                     * Handshake messages always go to a pending session
-                     * handshaker ... if there isn't one, create one.  This
-                     * must work asynchronously, for renegotiation.
-                     *
-                     * NOTE that handshaking will either resume a session
-                     * which was in the cache (and which might have other
-                     * connections in it already), or else will start a new
-                     * session (new keys exchanged) with just this connection
-                     * in it.
-                     */
-                    initHandshaker();
-                    if (!handshaker.activated()) {
-                        // prior to handshaking, activate the handshake
-                        if (connectionState == cs_RENEGOTIATE) {
-                            // don't use SSLv2Hello when renegotiating
-                            handshaker.activate(protocolVersion);
-                        } else {
-                            handshaker.activate(null);
-                        }
-                    }
-
-                    /*
-                     * process the handshake record ... may contain just
-                     * a partial handshake message or multiple messages.
-                     *
-                     * The handshaker state machine will ensure that it's
-                     * a finished message.
-                     */
-                    handshaker.process_record(r, expectingFinished);
-                    expectingFinished = false;
-
-                    if (handshaker.invalidated) {
-                        handshaker = null;
-                        // if state is cs_RENEGOTIATE, revert it to cs_DATA
-                        if (connectionState == cs_RENEGOTIATE) {
-                            connectionState = cs_DATA;
-                        }
-                    } else if (handshaker.isDone()) {
-                        // reset the parameters for secure renegotiation.
-                        secureRenegotiation =
-                                        handshaker.isSecureRenegotiation();
-                        clientVerifyData = handshaker.getClientVerifyData();
-                        serverVerifyData = handshaker.getServerVerifyData();
-
-                        sess = handshaker.getSession();
-                        handshakeSession = null;
-                        handshaker = null;
-                        connectionState = cs_DATA;
-
-                        //
-                        // Tell folk about handshake completion, but do
-                        // it in a separate thread.
-                        //
-                        if (handshakeListeners != null) {
-                            HandshakeCompletedEvent event =
-                                new HandshakeCompletedEvent(this, sess);
-
-                            Thread t = new NotifyHandshakeThread(
-                                handshakeListeners.entrySet(), event);
-                            t.start();
-                        }
-                    }
-
-                    if (needAppData || connectionState != cs_DATA) {
-                        continue;
-                    }
-                    break;
-
-                case Record.ct_application_data:
-                    // Pass this right back up to the application.
-                    if (connectionState != cs_DATA
-                            && connectionState != cs_RENEGOTIATE
-                            && connectionState != cs_SENT_CLOSE) {
-                        throw new SSLProtocolException(
-                            "Data received in non-data state: " +
-                            connectionState);
-                    }
-                    if (expectingFinished) {
-                        throw new SSLProtocolException
-                                ("Expecting finished message, received data");
-                    }
-                    if (!needAppData) {
-                        throw new SSLException("Discarding app data");
-                    }
-
-                    r.setAppDataValid(true);
-                    break;
-
-                case Record.ct_alert:
-                    recvAlert(r);
-                    continue;
-
-                case Record.ct_change_cipher_spec:
-                    if ((connectionState != cs_HANDSHAKE
-                                && connectionState != cs_RENEGOTIATE)
-                            || r.available() != 1
-                            || r.read() != 1) {
-                        fatal(Alerts.alert_unexpected_message,
-                            "illegal change cipher spec msg, state = "
-                            + connectionState);
-                    }
-
-                    //
-                    // The first message after a change_cipher_spec
-                    // record MUST be a "Finished" handshake record,
-                    // else it's a protocol violation.  We force this
-                    // to be checked by a minor tweak to the state
-                    // machine.
-                    //
-                    changeReadCiphers();
-                    // next message MUST be a finished message
-                    expectingFinished = true;
-                    continue;
-
-                default:
-                    //
-                    // TLS requires that unrecognized records be ignored.
-                    //
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(threadName() +
-                            ", Received record type: "
-                            + r.contentType());
-                    }
-                    continue;
-              } // switch
-
-              /*
-               * Check the sequence number state
-               *
-               * Note that in order to maintain the connection I/O
-               * properly, we check the sequence number after the last
-               * record reading process. As we request renegotiation
-               * or close the connection for wrapped sequence number
-               * when there is enough sequence number space left to
-               * handle a few more records, so the sequence number
-               * of the last record cannot be wrapped.
-               */
-              if (connectionState < cs_ERROR) {
-                  checkSequenceNumber(readMAC, r.contentType());
-              }
-
-              return;
-            } // synchronized (this)
-        }
-
-        //
-        // couldn't read, due to some kind of error
-        //
-        r.close();
-        return;
-      }  // synchronized (readLock)
-    }
-
-    /**
-     * Check the sequence number state
-     *
-     * RFC 4346 states that, "Sequence numbers are of type uint64 and
-     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead."
-     */
-    private void checkSequenceNumber(MAC mac, byte type)
-            throws IOException {
-
-        /*
-         * Don't bother to check the sequence number for error or
-         * closed connections, or NULL MAC.
-         */
-        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
-            return;
-        }
-
-        /*
-         * Conservatively, close the connection immediately when the
-         * sequence number is close to overflow
-         */
-        if (mac.seqNumOverflow()) {
-            /*
-             * TLS protocols do not define a error alert for sequence
-             * number overflow. We use handshake_failure error alert
-             * for handshaking and bad_record_mac for other records.
-             */
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", sequence number extremely close to overflow " +
-                    "(2^64-1 packets). Closing connection.");
-
-            }
-
-            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
-        }
-
-        /*
-         * Ask for renegotiation when need to renew sequence number.
-         *
-         * Don't bother to kickstart the renegotiation when the local is
-         * asking for it.
-         */
-        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() + ", request renegotiation " +
-                        "to avoid sequence number overflow");
-            }
-
-            startHandshake();
-        }
-    }
-
-    //
-    // HANDSHAKE RELATED CODE
-    //
-
-    /**
-     * Return the AppInputStream. For use by Handshaker only.
-     */
-    AppInputStream getAppInputStream() {
-        return input;
-    }
-
-    /**
-     * Return the AppOutputStream. For use by Handshaker only.
-     */
-    AppOutputStream getAppOutputStream() {
-        return output;
-    }
-
-    /**
-     * Initialize the handshaker object. This means:
-     *
-     *  . if a handshake is already in progress (state is cs_HANDSHAKE
-     *    or cs_RENEGOTIATE), do nothing and return
-     *
-     *  . if the socket is already closed, throw an Exception (internal error)
-     *
-     *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, and advance the connection state (to cs_HANDSHAKE or
-     *    cs_RENEGOTIATE, respectively).
-     *
-     * This method is called right after a new socket is created, when
-     * starting renegotiation, or when changing client/ server mode of the
-     * socket.
-     */
-    private void initHandshaker() {
-        switch (connectionState) {
-
-        //
-        // Starting a new handshake.
-        //
-        case cs_START:
-        case cs_DATA:
-            break;
-
-        //
-        // We're already in the middle of a handshake.
-        //
-        case cs_HANDSHAKE:
-        case cs_RENEGOTIATE:
-            return;
-
-        //
-        // Anyone allowed to call this routine is required to
-        // do so ONLY if the connection state is reasonable...
-        //
-        default:
-            throw new IllegalStateException("Internal error");
-        }
-
-        // state is either cs_START or cs_DATA
-        if (connectionState == cs_START) {
-            connectionState = cs_HANDSHAKE;
-        } else { // cs_DATA
-            connectionState = cs_RENEGOTIATE;
-        }
-        if (roleIsServer) {
-            handshaker = new ServerHandshaker(this, sslContext,
-                    enabledProtocols, doClientAuth,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-        } else {
-            handshaker = new ClientHandshaker(this, sslContext,
-                    enabledProtocols,
-                    protocolVersion, connectionState == cs_HANDSHAKE,
-                    secureRenegotiation, clientVerifyData, serverVerifyData);
-        }
-        handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        handshaker.setEnableSessionCreation(enableSessionCreation);
-    }
-
-    /**
-     * Synchronously perform the initial handshake.
-     *
-     * If the handshake is already in progress, this method blocks until it
-     * is completed. If the initial handshake has already been completed,
-     * it returns immediately.
-     */
-    private void performInitialHandshake() throws IOException {
-        // use handshakeLock and the state check to make sure only
-        // one thread performs the handshake
-        synchronized (handshakeLock) {
-            if (getConnectionState() == cs_HANDSHAKE) {
-                kickstartHandshake();
-
-                /*
-                 * All initial handshaking goes through this
-                 * InputRecord until we have a valid SSL connection.
-                 * Once initial handshaking is finished, AppInputStream's
-                 * InputRecord can handle any future renegotiation.
-                 *
-                 * Keep this local so that it goes out of scope and is
-                 * eventually GC'd.
-                 */
-                if (inrec == null) {
-                    inrec = new InputRecord();
-
-                    /*
-                     * Grab the characteristics already assigned to
-                     * AppInputStream's InputRecord.  Enable checking for
-                     * SSLv2 hellos on this first handshake.
-                     */
-                    inrec.setHandshakeHash(input.r.getHandshakeHash());
-                    inrec.setHelloVersion(input.r.getHelloVersion());
-                    inrec.enableFormatChecks();
-                }
-
-                readRecord(inrec, false);
-                inrec = null;
-            }
-        }
-    }
-
-    /**
-     * Starts an SSL handshake on this connection.
-     */
-    public void startHandshake() throws IOException {
-        // start an ssl handshake that could be resumed from timeout exception
-        startHandshake(true);
-    }
-
-    /**
-     * Starts an ssl handshake on this connection.
-     *
-     * @param resumable indicates the handshake process is resumable from a
-     *          certain exception. If <code>resumable</code>, the socket will
-     *          be reserved for exceptions like timeout; otherwise, the socket
-     *          will be closed, no further communications could be done.
-     */
-    private void startHandshake(boolean resumable) throws IOException {
-        checkWrite();
-        try {
-            if (getConnectionState() == cs_HANDSHAKE) {
-                // do initial handshake
-                performInitialHandshake();
-            } else {
-                // start renegotiation
-                kickstartHandshake();
-            }
-        } catch (Exception e) {
-            // shutdown and rethrow (wrapped) exception as appropriate
-            handleException(e, resumable);
-        }
-    }
-
-    /**
-     * Kickstart the handshake if it is not already in progress.
-     * This means:
-     *
-     *  . if handshaking is already underway, do nothing and return
-     *
-     *  . if the socket is not connected or already closed, throw an
-     *    Exception.
-     *
-     *  . otherwise, call initHandshake() to initialize the handshaker
-     *    object and progress the state. Then, send the initial
-     *    handshaking message if appropriate (always on clients and
-     *    on servers when renegotiating).
-     */
-    private synchronized void kickstartHandshake() throws IOException {
-
-        switch (connectionState) {
-
-        case cs_HANDSHAKE:
-            // handshaker already setup, proceed
-            break;
-
-        case cs_DATA:
-            if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
-                throw new SSLHandshakeException(
-                        "Insecure renegotiation is not allowed");
-            }
-
-            if (!secureRenegotiation) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                        "Warning: Using insecure renegotiation");
-                }
-            }
-
-            // initialize the handshaker, move to cs_RENEGOTIATE
-            initHandshaker();
-            break;
-
-        case cs_RENEGOTIATE:
-            // handshaking already in progress, return
-            return;
-
-        /*
-         * The only way to get a socket in the state is when
-         * you have an unconnected socket.
-         */
-        case cs_START:
-            throw new SocketException(
-                "handshaking attempted on unconnected socket");
-
-        default:
-            throw new SocketException("connection is closed");
-        }
-
-        //
-        // Kickstart handshake state machine if we need to ...
-        //
-        // Note that handshaker.kickstart() writes the message
-        // to its HandshakeOutStream, which calls back into
-        // SSLSocketImpl.writeRecord() to send it.
-        //
-        if (!handshaker.activated()) {
-             // prior to handshaking, activate the handshake
-            if (connectionState == cs_RENEGOTIATE) {
-                // don't use SSLv2Hello when renegotiating
-                handshaker.activate(protocolVersion);
-            } else {
-                handshaker.activate(null);
-            }
-
-            if (handshaker instanceof ClientHandshaker) {
-                // send client hello
-                handshaker.kickstart();
-            } else {
-                if (connectionState == cs_HANDSHAKE) {
-                    // initial handshake, no kickstart message to send
-                } else {
-                    // we want to renegotiate, send hello request
-                    handshaker.kickstart();
-                    // hello request is not included in the handshake
-                    // hashes, reset them
-                    handshaker.handshakeHash.reset();
-                }
-            }
-        }
-    }
-
-    //
-    // CLOSURE RELATED CALLS
-    //
-
-    /**
-     * Return whether the socket has been explicitly closed by the application.
-     */
-    public boolean isClosed() {
-        return getConnectionState() == cs_APP_CLOSED;
-    }
-
-    /**
-     * Return whether we have reached end-of-file.
-     *
-     * If the socket is not connected, has been shutdown because of an error
-     * or has been closed, throw an Exception.
-     */
-    boolean checkEOF() throws IOException {
-        switch (getConnectionState()) {
-        case cs_START:
-            throw new SocketException("Socket is not connected");
-
-        case cs_HANDSHAKE:
-        case cs_DATA:
-        case cs_RENEGOTIATE:
-        case cs_SENT_CLOSE:
-            return false;
-
-        case cs_APP_CLOSED:
-            throw new SocketException("Socket is closed");
-
-        case cs_ERROR:
-        case cs_CLOSED:
-        default:
-            // either closed because of error, or normal EOF
-            if (closeReason == null) {
-                return true;
-            }
-            IOException e = new SSLException
-                        ("Connection has been shutdown: " + closeReason);
-            e.initCause(closeReason);
-            throw e;
-
-        }
-    }
-
-    /**
-     * Check if we can write data to this socket. If not, throw an IOException.
-     */
-    void checkWrite() throws IOException {
-        if (checkEOF() || (getConnectionState() == cs_SENT_CLOSE)) {
-            // we are at EOF, write must throw Exception
-            throw new SocketException("Connection closed by remote host");
-        }
-    }
-
-    protected void closeSocket() throws IOException {
-
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeSocket()");
-        }
-        if (self == this) {
-            super.close();
-        } else {
-            self.close();
-        }
-    }
-
-    private void closeSocket(boolean selfInitiated) throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeSocket(selfInitiated)");
-        }
-        if (self == this) {
-            super.close();
-        } else if (autoClose) {
-            self.close();
-        } else if (selfInitiated) {
-            // layered && non-autoclose
-            // read close_notify alert to clear input stream
-            waitForClose(false);
-        }
-    }
-
-    /*
-     * Closing the connection is tricky ... we can't officially close the
-     * connection until we know the other end is ready to go away too,
-     * and if ever the connection gets aborted we must forget session
-     * state (it becomes invalid).
-     */
-
-    /**
-     * Closes the SSL connection.  SSL includes an application level
-     * shutdown handshake; you should close SSL sockets explicitly
-     * rather than leaving it for finalization, so that your remote
-     * peer does not experience a protocol error.
-     */
-    public void close() throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called close()");
-        }
-        closeInternal(true);  // caller is initiating close
-        setConnectionState(cs_APP_CLOSED);
-    }
-
-    /**
-     * Don't synchronize the whole method because waitForClose()
-     * (which calls readRecord()) might be called.
-     *
-     * @param selfInitiated Indicates which party initiated the close.
-     * If selfInitiated, this side is initiating a close; for layered and
-     * non-autoclose socket, wait for close_notify response.
-     * If !selfInitiated, peer sent close_notify; we reciprocate but
-     * no need to wait for response.
-     */
-    private void closeInternal(boolean selfInitiated) throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeInternal("
-                + selfInitiated + ")");
-        }
-
-        int state = getConnectionState();
-        boolean closeSocketCalled = false;
-        Throwable cachedThrowable = null;
-        try {
-            switch (state) {
-            case cs_START:
-                // unconnected socket or handshaking has not been initialized
-                closeSocket(selfInitiated);
-                break;
-
-            /*
-             * If we're closing down due to error, we already sent (or else
-             * received) the fatal alert ... no niceties, blow the connection
-             * away as quickly as possible (even if we didn't allocate the
-             * socket ourselves; it's unusable, regardless).
-             */
-            case cs_ERROR:
-                closeSocket();
-                break;
-
-            /*
-             * Sometimes close() gets called more than once.
-             */
-            case cs_CLOSED:
-            case cs_APP_CLOSED:
-                 break;
-
-            /*
-             * Otherwise we indicate clean termination.
-             */
-            // case cs_HANDSHAKE:
-            // case cs_DATA:
-            // case cs_RENEGOTIATE:
-            // case cs_SENT_CLOSE:
-            default:
-                synchronized (this) {
-                    if (((state = getConnectionState()) == cs_CLOSED) ||
-                       (state == cs_ERROR) || (state == cs_APP_CLOSED)) {
-                        return;  // connection was closed while we waited
-                    }
-                    if (state != cs_SENT_CLOSE) {
-                        try {
-                            warning(Alerts.alert_close_notify);
-                            connectionState = cs_SENT_CLOSE;
-                        } catch (Throwable th) {
-                            // we need to ensure socket is closed out
-                            // if we encounter any errors.
-                            connectionState = cs_ERROR;
-                            // cache this for later use
-                            cachedThrowable = th;
-                            closeSocketCalled = true;
-                            closeSocket(selfInitiated);
-                        }
-                    }
-                }
-                // If state was cs_SENT_CLOSE before, we don't do the actual
-                // closing since it is already in progress.
-                if (state == cs_SENT_CLOSE) {
-                    if (debug != null && Debug.isOn("ssl")) {
-                        System.out.println(threadName() +
-                            ", close invoked again; state = " +
-                            getConnectionState());
-                    }
-                    if (selfInitiated == false) {
-                        // We were called because a close_notify message was
-                        // received. This may be due to another thread calling
-                        // read() or due to our call to waitForClose() below.
-                        // In either case, just return.
-                        return;
-                    }
-                    // Another thread explicitly called close(). We need to
-                    // wait for the closing to complete before returning.
-                    synchronized (this) {
-                        while (connectionState < cs_CLOSED) {
-                            try {
-                                this.wait();
-                            } catch (InterruptedException e) {
-                                // ignore
-                            }
-                        }
-                    }
-                    if ((debug != null) && Debug.isOn("ssl")) {
-                        System.out.println(threadName() +
-                            ", after primary close; state = " +
-                            getConnectionState());
-                    }
-                    return;
-                }
-
-                if (!closeSocketCalled)  {
-                    closeSocketCalled = true;
-                    closeSocket(selfInitiated);
-                }
-
-                break;
-            }
-        } finally {
-            synchronized (this) {
-                // Upon exit from this method, the state is always >= cs_CLOSED
-                connectionState = (connectionState == cs_APP_CLOSED)
-                                ? cs_APP_CLOSED : cs_CLOSED;
-                // notify any threads waiting for the closing to finish
-                this.notifyAll();
-            }
-            if (closeSocketCalled) {
-                // Dispose of ciphers since we've closed socket
-                disposeCiphers();
-            }
-            if (cachedThrowable != null) {
-               /*
-                * Rethrow the error to the calling method
-                * The Throwable caught can only be an Error or RuntimeException
-                */
-                if (cachedThrowable instanceof Error)
-                    throw (Error) cachedThrowable;
-                if (cachedThrowable instanceof RuntimeException)
-                    throw (RuntimeException) cachedThrowable;
-            }
-        }
-    }
-
-    /**
-     * Reads a close_notify or a fatal alert from the input stream.
-     * Keep reading records until we get a close_notify or until
-     * the connection is otherwise closed.  The close_notify or alert
-     * might be read by another reader,
-     * which will then process the close and set the connection state.
-     */
-    void waitForClose(boolean rethrow) throws IOException {
-        if (debug != null && Debug.isOn("ssl")) {
-            System.out.println(threadName() +
-                ", waiting for close_notify or alert: state "
-                + getConnectionState());
-        }
-
-        try {
-            int state;
-
-            while (((state = getConnectionState()) != cs_CLOSED) &&
-                   (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
-                // create the InputRecord if it isn't intialized.
-                if (inrec == null) {
-                    inrec = new InputRecord();
-                }
-
-                // Ask for app data and then throw it away
-                try {
-                    readRecord(inrec, true);
-                } catch (SocketTimeoutException e) {
-                    // if time out, ignore the exception and continue
-                }
-            }
-            inrec = null;
-        } catch (IOException e) {
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", Exception while waiting for close " +e);
-            }
-            if (rethrow) {
-                throw e; // pass exception up
-            }
-        }
-    }
-
-    /**
-     * Called by closeInternal() only. Be sure to consider the
-     * synchronization locks carefully before calling it elsewhere.
-     */
-    private void disposeCiphers() {
-        // See comment in changeReadCiphers()
-        synchronized (readLock) {
-            readCipher.dispose();
-        }
-        // See comment in changeReadCiphers()
-        writeLock.lock();
-        try {
-            writeCipher.dispose();
-        } finally {
-            writeLock.unlock();
-        }
-    }
-
-    //
-    // EXCEPTION AND ALERT HANDLING
-    //
-
-    /**
-     * Handle an exception. This method is called by top level exception
-     * handlers (in read(), write()) to make sure we always shutdown the
-     * connection correctly and do not pass runtime exception to the
-     * application.
-     */
-    void handleException(Exception e) throws IOException {
-        handleException(e, true);
-    }
-
-    /**
-     * Handle an exception. This method is called by top level exception
-     * handlers (in read(), write(), startHandshake()) to make sure we
-     * always shutdown the connection correctly and do not pass runtime
-     * exception to the application.
-     *
-     * This method never returns normally, it always throws an IOException.
-     *
-     * We first check if the socket has already been shutdown because of an
-     * error. If so, we just rethrow the exception. If the socket has not
-     * been shutdown, we sent a fatal alert and remember the exception.
-     *
-     * @param e the Exception
-     * @param resumable indicates the caller process is resumable from the
-     *          exception. If <code>resumable</code>, the socket will be
-     *          reserved for exceptions like timeout; otherwise, the socket
-     *          will be closed, no further communications could be done.
-     */
-    synchronized private void handleException(Exception e, boolean resumable)
-        throws IOException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName()
-                        + ", handling exception: " + e.toString());
-        }
-
-        // don't close the Socket in case of timeouts or interrupts if
-        // the process is resumable.
-        if (e instanceof InterruptedIOException && resumable) {
-            throw (IOException)e;
-        }
-
-        // if we've already shutdown because of an error,
-        // there is nothing to do except rethrow the exception
-        if (closeReason != null) {
-            if (e instanceof IOException) { // includes SSLException
-                throw (IOException)e;
-            } else {
-                // this is odd, not an IOException.
-                // normally, this should not happen
-                // if closeReason has been already been set
-                throw Alerts.getSSLException(Alerts.alert_internal_error, e,
-                                      "Unexpected exception");
-            }
-        }
-
-        // need to perform error shutdown
-        boolean isSSLException = (e instanceof SSLException);
-        if ((isSSLException == false) && (e instanceof IOException)) {
-            // IOException from the socket
-            // this means the TCP connection is already dead
-            // we call fatal just to set the error status
-            try {
-                fatal(Alerts.alert_unexpected_message, e);
-            } catch (IOException ee) {
-                // ignore (IOException wrapped in SSLException)
-            }
-            // rethrow original IOException
-            throw (IOException)e;
-        }
-
-        // must be SSLException or RuntimeException
-        byte alertType;
-        if (isSSLException) {
-            if (e instanceof SSLHandshakeException) {
-                alertType = Alerts.alert_handshake_failure;
-            } else {
-                alertType = Alerts.alert_unexpected_message;
-            }
-        } else {
-            alertType = Alerts.alert_internal_error;
-        }
-        fatal(alertType, e);
-    }
-
-    /*
-     * Send a warning alert.
-     */
-    void warning(byte description) {
-        sendAlert(Alerts.alert_warning, description);
-    }
-
-    synchronized void fatal(byte description, String diagnostic)
-            throws IOException {
-        fatal(description, diagnostic, null);
-    }
-
-    synchronized void fatal(byte description, Throwable cause)
-            throws IOException {
-        fatal(description, null, cause);
-    }
-
-    /*
-     * Send a fatal alert, and throw an exception so that callers will
-     * need to stand on their heads to accidentally continue processing.
-     */
-    synchronized void fatal(byte description, String diagnostic,
-            Throwable cause) throws IOException {
-        if ((input != null) && (input.r != null)) {
-            input.r.close();
-        }
-        sess.invalidate();
-        if (handshakeSession != null) {
-            handshakeSession.invalidate();
-        }
-
-        int oldState = connectionState;
-        if (connectionState < cs_ERROR) {
-            connectionState = cs_ERROR;
-        }
-
-        /*
-         * Has there been an error received yet?  If not, remember it.
-         * By RFC 2246, we don't bother waiting for a response.
-         * Fatal errors require immediate shutdown.
-         */
-        if (closeReason == null) {
-            /*
-             * Try to clear the kernel buffer to avoid TCP connection resets.
-             */
-            if (oldState == cs_HANDSHAKE) {
-                sockInput.skip(sockInput.available());
-            }
-
-            // If the description equals -1, the alert won't be sent to peer.
-            if (description != -1) {
-                sendAlert(Alerts.alert_fatal, description);
-            }
-            if (cause instanceof SSLException) { // only true if != null
-                closeReason = (SSLException)cause;
-            } else {
-                closeReason =
-                    Alerts.getSSLException(description, cause, diagnostic);
-            }
-        }
-
-        /*
-         * Clean up our side.
-         */
-        closeSocket();
-        // Another thread may have disposed the ciphers during closing
-        if (connectionState < cs_CLOSED) {
-            connectionState = (oldState == cs_APP_CLOSED) ? cs_APP_CLOSED
-                                                              : cs_CLOSED;
-
-            // We should lock readLock and writeLock if no deadlock risks.
-            // See comment in changeReadCiphers()
-            readCipher.dispose();
-            writeCipher.dispose();
-        }
-
-        throw closeReason;
-    }
-
-
-    /*
-     * Process an incoming alert ... caller must already have synchronized
-     * access to "this".
-     */
-    private void recvAlert(InputRecord r) throws IOException {
-        byte level = (byte)r.read();
-        byte description = (byte)r.read();
-        if (description == -1) { // check for short message
-            fatal(Alerts.alert_illegal_parameter, "Short alert message");
-        }
-
-        if (debug != null && (Debug.isOn("record") ||
-                Debug.isOn("handshake"))) {
-            synchronized (System.out) {
-                System.out.print(threadName());
-                System.out.print(", RECV " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level " + (0x0ff & level) + ">, ");
-                }
-                System.out.println(Alerts.alertDescription(description));
-            }
-        }
-
-        if (level == Alerts.alert_warning) {
-            if (description == Alerts.alert_close_notify) {
-                if (connectionState == cs_HANDSHAKE) {
-                    fatal(Alerts.alert_unexpected_message,
-                                "Received close_notify during handshake");
-                } else {
-                    closeInternal(false);  // reply to close
-                }
-            } else {
-
-                //
-                // The other legal warnings relate to certificates,
-                // e.g. no_certificate, bad_certificate, etc; these
-                // are important to the handshaking code, which can
-                // also handle illegal protocol alerts if needed.
-                //
-                if (handshaker != null) {
-                    handshaker.handshakeAlert(description);
-                }
-            }
-        } else { // fatal or unknown level
-            String reason = "Received fatal alert: "
-                + Alerts.alertDescription(description);
-            if (closeReason == null) {
-                closeReason = Alerts.getSSLException(description, reason);
-            }
-            fatal(Alerts.alert_unexpected_message, reason);
-        }
-    }
-
-
-    /*
-     * Emit alerts.  Caller must have synchronized with "this".
-     */
-    private void sendAlert(byte level, byte description) {
-        // the connectionState cannot be cs_START
-        if (connectionState >= cs_SENT_CLOSE) {
-            return;
-        }
-
-        // For initial handshaking, don't send alert message to peer if
-        // handshaker has not started.
-        if (connectionState == cs_HANDSHAKE &&
-            (handshaker == null || !handshaker.started())) {
-            return;
-        }
-
-        OutputRecord r = new OutputRecord(Record.ct_alert);
-        r.setVersion(protocolVersion);
-
-        boolean useDebug = debug != null && Debug.isOn("ssl");
-        if (useDebug) {
-            synchronized (System.out) {
-                System.out.print(threadName());
-                System.out.print(", SEND " + protocolVersion + " ALERT:  ");
-                if (level == Alerts.alert_fatal) {
-                    System.out.print("fatal, ");
-                } else if (level == Alerts.alert_warning) {
-                    System.out.print("warning, ");
-                } else {
-                    System.out.print("<level = " + (0x0ff & level) + ">, ");
-                }
-                System.out.println("description = "
-                        + Alerts.alertDescription(description));
-            }
-        }
-
-        r.write(level);
-        r.write(description);
-        try {
-            writeRecord(r);
-        } catch (IOException e) {
-            if (useDebug) {
-                System.out.println(threadName() +
-                    ", Exception sending alert: " + e);
-            }
-        }
-    }
-
-    //
-    // VARIOUS OTHER METHODS
-    //
-
-    /*
-     * When a connection finishes handshaking by enabling use of a newly
-     * negotiated session, each end learns about it in two halves (read,
-     * and write).  When both read and write ciphers have changed, and the
-     * last handshake message has been read, the connection has joined
-     * (rejoined) the new session.
-     *
-     * NOTE:  The SSLv3 spec is rather unclear on the concepts here.
-     * Sessions don't change once they're established (including cipher
-     * suite and master secret) but connections can join them (and leave
-     * them).  They're created by handshaking, though sometime handshaking
-     * causes connections to join up with pre-established sessions.
-     */
-    private void changeReadCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create decompressor
-
-        CipherBox oldCipher = readCipher;
-
-        try {
-            readCipher = handshaker.newReadCipher();
-            readMAC = handshaker.newReadMAC();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw (SSLException)new SSLException
-                                ("Algorithm missing:  ").initCause(e);
-        }
-
-        /*
-         * Dispose of any intermediate state in the underlying cipher.
-         * For PKCS11 ciphers, this will release any attached sessions,
-         * and thus make finalization faster.
-         *
-         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
-         * not necessary to do the same with MAC's.
-         */
-        oldCipher.dispose();
-    }
-
-    // used by Handshaker
-    void changeWriteCiphers() throws SSLException {
-        if (connectionState != cs_HANDSHAKE
-                && connectionState != cs_RENEGOTIATE) {
-            throw new SSLProtocolException(
-                "State error, change cipher specs");
-        }
-
-        // ... create compressor
-
-        CipherBox oldCipher = writeCipher;
-
-        try {
-            writeCipher = handshaker.newWriteCipher();
-            writeMAC = handshaker.newWriteMAC();
-        } catch (GeneralSecurityException e) {
-            // "can't happen"
-            throw (SSLException)new SSLException
-                                ("Algorithm missing:  ").initCause(e);
-        }
-
-        // See comment above.
-        oldCipher.dispose();
-
-        // reset the flag of the first application record
-        isFirstAppOutputRecord = true;
-    }
-
-    /*
-     * Updates the SSL version associated with this connection.
-     * Called from Handshaker once it has determined the negotiated version.
-     */
-    synchronized void setVersion(ProtocolVersion protocolVersion) {
-        this.protocolVersion = protocolVersion;
-        output.r.setVersion(protocolVersion);
-    }
-
-    synchronized String getHost() {
-        // Note that the host may be null or empty for localhost.
-        if (host == null || host.length() == 0) {
-            host = getInetAddress().getHostName();
-        }
-        return host;
-    }
-
-    synchronized String getRawHostname() {
-        return rawHostname;
-    }
-
-    // ONLY used by HttpsClient to setup the URI specified hostname
-    synchronized public void setHost(String host) {
-        this.host = host;
-        this.rawHostname = host;
-    }
-
-    /**
-     * Gets an input stream to read from the peer on the other side.
-     * Data read from this stream was always integrity protected in
-     * transit, and will usually have been confidentiality protected.
-     */
-    synchronized public InputStream getInputStream() throws IOException {
-        if (isClosed()) {
-            throw new SocketException("Socket is closed");
-        }
-
-        /*
-         * Can't call isConnected() here, because the Handshakers
-         * do some initialization before we actually connect.
-         */
-        if (connectionState == cs_START) {
-            throw new SocketException("Socket is not connected");
-        }
-
-        return input;
-    }
-
-    /**
-     * Gets an output stream to write to the peer on the other side.
-     * Data written on this stream is always integrity protected, and
-     * will usually be confidentiality protected.
-     */
-    synchronized public OutputStream getOutputStream() throws IOException {
-        if (isClosed()) {
-            throw new SocketException("Socket is closed");
-        }
-
-        /*
-         * Can't call isConnected() here, because the Handshakers
-         * do some initialization before we actually connect.
-         */
-        if (connectionState == cs_START) {
-            throw new SocketException("Socket is not connected");
-        }
-
-        return output;
-    }
-
-    /**
-     * Returns the the SSL Session in use by this connection.  These can
-     * be long lived, and frequently correspond to an entire login session
-     * for some user.
-     */
-    public SSLSession getSession() {
-        /*
-         * Force a synchronous handshake, if appropriate.
-         */
-        if (getConnectionState() == cs_HANDSHAKE) {
-            try {
-                // start handshaking, if failed, the connection will be closed.
-                startHandshake(false);
-            } catch (IOException e) {
-                // handshake failed. log and return a nullSession
-                if (debug != null && Debug.isOn("handshake")) {
-                      System.out.println(threadName() +
-                          ", IOException in getSession():  " + e);
-                }
-            }
-        }
-        synchronized (this) {
-            return sess;
-        }
-    }
-
-    @Override
-    synchronized public SSLSession getHandshakeSession() {
-        return handshakeSession;
-    }
-
-    synchronized void setHandshakeSession(SSLSessionImpl session) {
-        handshakeSession = session;
-    }
-
-    /**
-     * Controls whether new connections may cause creation of new SSL
-     * sessions.
-     *
-     * As long as handshaking has not started, we can change
-     * whether we enable session creations.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setEnableSessionCreation(boolean flag) {
-        enableSessionCreation = flag;
-
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnableSessionCreation(enableSessionCreation);
-        }
-    }
-
-    /**
-     * Returns true if new connections may cause creation of new SSL
-     * sessions.
-     */
-    synchronized public boolean getEnableSessionCreation() {
-        return enableSessionCreation;
-    }
-
-
-    /**
-     * Sets the flag controlling whether a server mode socket
-     * *REQUIRES* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is needed.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setNeedClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    synchronized public boolean getNeedClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_required);
-    }
-
-    /**
-     * Sets the flag controlling whether a server mode socket
-     * *REQUESTS* SSL client authentication.
-     *
-     * As long as handshaking has not started, we can change
-     * whether client authentication is requested.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    synchronized public void setWantClientAuth(boolean flag) {
-        doClientAuth = (flag ?
-            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
-        if ((handshaker != null) &&
-                (handshaker instanceof ServerHandshaker) &&
-                !handshaker.activated()) {
-            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
-        }
-    }
-
-    synchronized public boolean getWantClientAuth() {
-        return (doClientAuth == SSLEngineImpl.clauth_requested);
-    }
-
-
-    /**
-     * Sets the flag controlling whether the socket is in SSL
-     * client or server mode.  Must be called before any SSL
-     * traffic has started.
-     */
-    synchronized public void setUseClientMode(boolean flag) {
-        switch (connectionState) {
-
-        case cs_START:
-            /*
-             * If we need to change the socket mode and the enabled
-             * protocols haven't specifically been set by the user,
-             * change them to the corresponding default ones.
-             */
-            if (roleIsServer != (!flag) &&
-                    sslContext.isDefaultProtocolList(enabledProtocols)) {
-                enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-            }
-            roleIsServer = !flag;
-            break;
-
-        case cs_HANDSHAKE:
-            /*
-             * If we have a handshaker, but haven't started
-             * SSL traffic, we can throw away our current
-             * handshaker, and start from scratch.  Don't
-             * need to call doneConnect() again, we already
-             * have the streams.
-             */
-            assert(handshaker != null);
-            if (!handshaker.activated()) {
-                /*
-                 * If we need to change the socket mode and the enabled
-                 * protocols haven't specifically been set by the user,
-                 * change them to the corresponding default ones.
-                 */
-                if (roleIsServer != (!flag) &&
-                        sslContext.isDefaultProtocolList(enabledProtocols)) {
-                    enabledProtocols = sslContext.getDefaultProtocolList(!flag);
-                }
-                roleIsServer = !flag;
-                connectionState = cs_START;
-                initHandshaker();
-                break;
-            }
-
-            // If handshake has started, that's an error.  Fall through...
-
-        default:
-            if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(threadName() +
-                    ", setUseClientMode() invoked in state = " +
-                    connectionState);
-            }
-            throw new IllegalArgumentException(
-                "Cannot change mode after SSL traffic has started");
-        }
-    }
-
-    synchronized public boolean getUseClientMode() {
-        return !roleIsServer;
-    }
-
-
-    /**
-     * Returns the names of the cipher suites which could be enabled for use
-     * on an SSL connection.  Normally, only a subset of these will actually
-     * be enabled by default, since this list may include cipher suites which
-     * do not support the mutual authentication of servers and clients, or
-     * which do not protect data confidentiality.  Servers may also need
-     * certain kinds of certificates to use certain cipher suites.
-     *
-     * @return an array of cipher suite names
-     */
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSupportedCipherSuiteList().toStringArray();
-    }
-
-    /**
-     * Controls which particular cipher suites are enabled for use on
-     * this connection.  The cipher suites must have been listed by
-     * getCipherSuites() as being supported.  Even if a suite has been
-     * enabled, it might never be used if no peer supports it or the
-     * requisite certificates (and private keys) are not available.
-     *
-     * @param suites Names of all the cipher suites to enable.
-     */
-    synchronized public void setEnabledCipherSuites(String[] suites) {
-        enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledCipherSuites(enabledCipherSuites);
-        }
-    }
-
-    /**
-     * Returns the names of the SSL cipher suites which are currently enabled
-     * for use on this connection.  When an SSL socket is first created,
-     * all enabled cipher suites <em>(a)</em> protect data confidentiality,
-     * by traffic encryption, and <em>(b)</em> can mutually authenticate
-     * both clients and servers.  Thus, in some environments, this value
-     * might be empty.
-     *
-     * @return an array of cipher suite names
-     */
-    synchronized public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites.toStringArray();
-    }
-
-
-    /**
-     * Returns the protocols that are supported by this implementation.
-     * A subset of the supported protocols may be enabled for this connection
-     * @return an array of protocol names.
-     */
-    public String[] getSupportedProtocols() {
-        return sslContext.getSuportedProtocolList().toStringArray();
-    }
-
-    /**
-     * Controls which protocols are enabled for use on
-     * this connection.  The protocols must have been listed by
-     * getSupportedProtocols() as being supported.
-     *
-     * @param protocols protocols to enable.
-     * @exception IllegalArgumentException when one of the protocols
-     *  named by the parameter is not supported.
-     */
-    synchronized public void setEnabledProtocols(String[] protocols) {
-        enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.activated()) {
-            handshaker.setEnabledProtocols(enabledProtocols);
-        }
-    }
-
-    synchronized public String[] getEnabledProtocols() {
-        return enabledProtocols.toStringArray();
-    }
-
-    /**
-     * Assigns the socket timeout.
-     * @see java.net.Socket#setSoTimeout
-     */
-    public void setSoTimeout(int timeout) throws SocketException {
-        if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() +
-                ", setSoTimeout(" + timeout + ") called");
-        }
-        if (self == this) {
-            super.setSoTimeout(timeout);
-        } else {
-            self.setSoTimeout(timeout);
-        }
-    }
-
-    /**
-     * Registers an event listener to receive notifications that an
-     * SSL handshake has completed on this connection.
-     */
-    public synchronized void addHandshakeCompletedListener(
-            HandshakeCompletedListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener is null");
-        }
-        if (handshakeListeners == null) {
-            handshakeListeners = new
-                HashMap<HandshakeCompletedListener, AccessControlContext>(4);
-        }
-        handshakeListeners.put(listener, AccessController.getContext());
-    }
-
-
-    /**
-     * Removes a previously registered handshake completion listener.
-     */
-    public synchronized void removeHandshakeCompletedListener(
-            HandshakeCompletedListener listener) {
-        if (handshakeListeners == null) {
-            throw new IllegalArgumentException("no listeners");
-        }
-        if (handshakeListeners.remove(listener) == null) {
-            throw new IllegalArgumentException("listener not registered");
-        }
-        if (handshakeListeners.isEmpty()) {
-            handshakeListeners = null;
-        }
-    }
-
-    /**
-     * Returns the SSLParameters in effect for this SSLSocket.
-     */
-    synchronized public SSLParameters getSSLParameters() {
-        SSLParameters params = super.getSSLParameters();
-
-        // the super implementation does not handle the following parameters
-        params.setEndpointIdentificationAlgorithm(identificationProtocol);
-        params.setAlgorithmConstraints(algorithmConstraints);
-
-        return params;
-    }
-
-    /**
-     * Applies SSLParameters to this socket.
-     */
-    synchronized public void setSSLParameters(SSLParameters params) {
-        super.setSSLParameters(params);
-
-        // the super implementation does not handle the following parameters
-        identificationProtocol = params.getEndpointIdentificationAlgorithm();
-        algorithmConstraints = params.getAlgorithmConstraints();
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.setIdentificationProtocol(identificationProtocol);
-            handshaker.setAlgorithmConstraints(algorithmConstraints);
-        }
-    }
-
-    //
-    // We allocate a separate thread to deliver handshake completion
-    // events.  This ensures that the notifications don't block the
-    // protocol state machine.
-    //
-    private static class NotifyHandshakeThread extends Thread {
-
-        private Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
-                targets;        // who gets notified
-        private HandshakeCompletedEvent event;          // the notification
-
-        NotifyHandshakeThread(
-            Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
-            entrySet, HandshakeCompletedEvent e) {
-
-            super("HandshakeCompletedNotify-Thread");
-            targets = new HashSet<>(entrySet);          // clone the entry set
-            event = e;
-        }
-
-        public void run() {
-            // Don't need to synchronize, as it only runs in one thread.
-            for (Map.Entry<HandshakeCompletedListener,AccessControlContext>
-                entry : targets) {
-
-                final HandshakeCompletedListener l = entry.getKey();
-                AccessControlContext acc = entry.getValue();
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                    public Void run() {
-                        l.handshakeCompleted(event);
-                        return null;
-                    }
-                }, acc);
-            }
-        }
-    }
-
-    /**
-     * Return the name of the current thread. Utility method.
-     */
-    private static String threadName() {
-        return Thread.currentThread().getName();
-    }
-
-    /**
-     * Returns a printable representation of this end of the connection.
-     */
-    public String toString() {
-        StringBuffer retval = new StringBuffer(80);
-
-        retval.append(Integer.toHexString(hashCode()));
-        retval.append("[");
-        retval.append(sess.getCipherSuite());
-        retval.append(": ");
-
-        if (self == this) {
-            retval.append(super.toString());
-        } else {
-            retval.append(self.toString());
-        }
-        retval.append("]");
-
-        return retval.toString();
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java b/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java
deleted file mode 100755
index c651b44..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java
+++ /dev/null
@@ -1,1682 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.interfaces.*;
-import java.security.spec.ECParameterSpec;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-import sun.security.ssl.SignatureAndHashAlgorithm.*;
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * ServerHandshaker does the protocol handshaking from the point
- * of view of a server.  It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ServerHandshaker extends Handshaker {
-
-    // is the server going to require the client to authenticate?
-    private byte                doClientAuth;
-
-    // our authentication info
-    private X509Certificate[]   certs;
-    private PrivateKey          privateKey;
-
-    private SecretKey[]       kerberosKeys;
-
-    // flag to check for clientCertificateVerify message
-    private boolean             needClientVerify = false;
-
-    /*
-     * For exportable ciphersuites using non-exportable key sizes, we use
-     * ephemeral RSA keys. We could also do anonymous RSA in the same way
-     * but there are no such ciphersuites currently defined.
-     */
-    private PrivateKey          tempPrivateKey;
-    private PublicKey           tempPublicKey;
-
-    /*
-     * For anonymous and ephemeral Diffie-Hellman key exchange, we use
-     * ephemeral Diffie-Hellman keys.
-     */
-    private DHCrypt dh;
-
-    // Helper for ECDH based key exchanges
-    private ECDHCrypt ecdh;
-
-    // version request by the client in its ClientHello
-    // we remember it for the RSA premaster secret version check
-    private ProtocolVersion clientRequestedVersion;
-
-    private SupportedEllipticCurvesExtension supportedCurves;
-
-    // the preferable signature algorithm used by ServerKeyExchange message
-    SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
-    /*
-     * Constructor ... use the keys found in the auth context.
-     */
-    ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
-            ProtocolList enabledProtocols, byte clientAuth,
-            ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
-            boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(socket, context, enabledProtocols,
-                (clientAuth != SSLEngineImpl.clauth_none), false,
-                activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-                clientVerifyData, serverVerifyData);
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * Constructor ... use the keys found in the auth context.
-     */
-    ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
-            ProtocolList enabledProtocols, byte clientAuth,
-            ProtocolVersion activeProtocolVersion,
-            boolean isInitialHandshake, boolean secureRenegotiation,
-            byte[] clientVerifyData, byte[] serverVerifyData) {
-
-        super(engine, context, enabledProtocols,
-                (clientAuth != SSLEngineImpl.clauth_none), false,
-                activeProtocolVersion, isInitialHandshake, secureRenegotiation,
-                clientVerifyData, serverVerifyData);
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * As long as handshaking has not started, we can change
-     * whether client authentication is required.  Otherwise,
-     * we will need to wait for the next handshake.
-     */
-    void setClientAuth(byte clientAuth) {
-        doClientAuth = clientAuth;
-    }
-
-    /*
-     * This routine handles all the server side handshake messages, one at
-     * a time.  Given the message type (and in some cases the pending cipher
-     * spec) it parses the type-specific message.  Then it calls a function
-     * that handles that specific message.
-     *
-     * It updates the state machine as each message is processed, and writes
-     * responses as needed using the connection in the constructor.
-     */
-    void processMessage(byte type, int message_len)
-            throws IOException {
-        //
-        // In SSLv3 and TLS, messages follow strictly increasing
-        // numerical order _except_ for one annoying special case.
-        //
-        if ((state >= type)
-                && (state != HandshakeMessage.ht_client_key_exchange
-                    && type != HandshakeMessage.ht_certificate_verify)) {
-            throw new SSLProtocolException(
-                    "Handshake message sequence violation, state = " + state
-                    + ", type = " + type);
-        }
-
-        switch (type) {
-            case HandshakeMessage.ht_client_hello:
-                ClientHello ch = new ClientHello(input, message_len);
-                /*
-                 * send it off for processing.
-                 */
-                this.clientHello(ch);
-                break;
-
-            case HandshakeMessage.ht_certificate:
-                if (doClientAuth == SSLEngineImpl.clauth_none) {
-                    fatalSE(Alerts.alert_unexpected_message,
-                                "client sent unsolicited cert chain");
-                    // NOTREACHED
-                }
-                this.clientCertificate(new CertificateMsg(input));
-                break;
-
-            case HandshakeMessage.ht_client_key_exchange:
-                SecretKey preMasterSecret;
-                switch (keyExchange) {
-                case K_RSA:
-                case K_RSA_EXPORT:
-                    /*
-                     * The client's pre-master secret is decrypted using
-                     * either the server's normal private RSA key, or the
-                     * temporary one used for non-export or signing-only
-                     * certificates/keys.
-                     */
-                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
-                            protocolVersion, clientRequestedVersion,
-                            sslContext.getSecureRandom(), input,
-                            message_len, privateKey);
-                    preMasterSecret = this.clientKeyExchange(pms);
-                    break;
-                case K_KRB5:
-                case K_KRB5_EXPORT:
-                    preMasterSecret = this.clientKeyExchange(
-                        new KerberosClientKeyExchange(protocolVersion,
-                            clientRequestedVersion,
-                            sslContext.getSecureRandom(),
-                            input,
-                            kerberosKeys));
-                    break;
-                case K_DHE_RSA:
-                case K_DHE_DSS:
-                case K_DH_ANON:
-                    /*
-                     * The pre-master secret is derived using the normal
-                     * Diffie-Hellman calculation.   Note that the main
-                     * protocol difference in these five flavors is in how
-                     * the ServerKeyExchange message was constructed!
-                     */
-                    preMasterSecret = this.clientKeyExchange(
-                            new DHClientKeyExchange(input));
-                    break;
-                case K_ECDH_RSA:
-                case K_ECDH_ECDSA:
-                case K_ECDHE_RSA:
-                case K_ECDHE_ECDSA:
-                case K_ECDH_ANON:
-                    preMasterSecret = this.clientKeyExchange
-                                            (new ECDHClientKeyExchange(input));
-                    break;
-                default:
-                    throw new SSLProtocolException
-                        ("Unrecognized key exchange: " + keyExchange);
-                }
-
-                //
-                // All keys are calculated from the premaster secret
-                // and the exchanged nonces in the same way.
-                //
-                calculateKeys(preMasterSecret, clientRequestedVersion);
-                break;
-
-            case HandshakeMessage.ht_certificate_verify:
-                this.clientCertificateVerify(new CertificateVerify(input,
-                            localSupportedSignAlgs, protocolVersion));
-                break;
-
-            case HandshakeMessage.ht_finished:
-                this.clientFinished(
-                    new Finished(protocolVersion, input, cipherSuite));
-                break;
-
-            default:
-                throw new SSLProtocolException(
-                        "Illegal server handshake msg, " + type);
-        }
-
-        //
-        // Move state machine forward if the message handling
-        // code didn't already do so
-        //
-        if (state < type) {
-            if(type == HandshakeMessage.ht_certificate_verify) {
-                state = type + 2;    // an annoying special case
-            } else {
-                state = type;
-            }
-        }
-    }
-
-
-    /*
-     * ClientHello presents the server with a bunch of options, to which the
-     * server replies with a ServerHello listing the ones which this session
-     * will use.  If needed, it also writes its Certificate plus in some cases
-     * a ServerKeyExchange message.  It may also write a CertificateRequest,
-     * to elicit a client certificate.
-     *
-     * All these messages are terminated by a ServerHelloDone message.  In
-     * most cases, all this can be sent in a single Record.
-     */
-    private void clientHello(ClientHello mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // Does the message include security renegotiation indication?
-        boolean renegotiationIndicated = false;
-
-        // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-        CipherSuiteList cipherSuites = mesg.getCipherSuites();
-        if (cipherSuites.contains(CipherSuite.C_SCSV)) {
-            renegotiationIndicated = true;
-            if (isInitialHandshake) {
-                secureRenegotiation = true;
-            } else {
-                // abort the handshake with a fatal handshake_failure alert
-                if (secureRenegotiation) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The SCSV is present in a secure renegotiation");
-                } else {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The SCSV is present in a insecure renegotiation");
-                }
-            }
-        }
-
-        // check the "renegotiation_info" extension
-        RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
-                    mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
-        if (clientHelloRI != null) {
-            renegotiationIndicated = true;
-            if (isInitialHandshake) {
-                // verify the length of the "renegotiated_connection" field
-                if (!clientHelloRI.isEmpty()) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info field is not empty");
-                }
-
-                secureRenegotiation = true;
-            } else {
-                if (!secureRenegotiation) {
-                    // unexpected RI extension for insecure renegotiation,
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "The renegotiation_info is present in a insecure " +
-                        "renegotiation");
-                }
-
-                // verify the client_verify_data value
-                if (!Arrays.equals(clientVerifyData,
-                                clientHelloRI.getRenegotiatedConnection())) {
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Incorrect verify data in ClientHello " +
-                        "renegotiation_info message");
-                }
-            }
-        } else if (!isInitialHandshake && secureRenegotiation) {
-           // if the connection's "secure_renegotiation" flag is set to TRUE
-           // and the "renegotiation_info" extension is not present, abort
-           // the handshake.
-            fatalSE(Alerts.alert_handshake_failure,
-                        "Inconsistent secure renegotiation indication");
-        }
-
-        // if there is no security renegotiation indication or the previous
-        // handshake is insecure.
-        if (!renegotiationIndicated || !secureRenegotiation) {
-            if (isInitialHandshake) {
-                if (!allowLegacyHelloMessages) {
-                    // abort the handshake with a fatal handshake_failure alert
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Failed to negotiate the use of secure renegotiation");
-                }
-
-                // continue with legacy ClientHello
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println("Warning: No renegotiation " +
-                        "indication in ClientHello, allow legacy ClientHello");
-                }
-            } else if (!allowUnsafeRenegotiation) {
-                // abort the handshake
-                if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
-                    // response with a no_renegotiation warning,
-                    warningSE(Alerts.alert_no_renegotiation);
-
-                    // invalidate the handshake so that the caller can
-                    // dispose this object.
-                    invalidated = true;
-
-                    // If there is still unread block in the handshake
-                    // input stream, it would be truncated with the disposal
-                    // and the next handshake message will become incomplete.
-                    //
-                    // However, according to SSL/TLS specifications, no more
-                    // handshake message could immediately follow ClientHello
-                    // or HelloRequest. But in case of any improper messages,
-                    // we'd better check to ensure there is no remaining bytes
-                    // in the handshake input stream.
-                    if (input.available() > 0) {
-                        fatalSE(Alerts.alert_unexpected_message,
-                            "ClientHello followed by an unexpected  " +
-                            "handshake message");
-                    }
-
-                    return;
-                } else {
-                    // For SSLv3, send the handshake_failure fatal error.
-                    // Note that SSLv3 does not define a no_renegotiation
-                    // alert like TLSv1. However we cannot ignore the message
-                    // simply, otherwise the other side was waiting for a
-                    // response that would never come.
-                    fatalSE(Alerts.alert_handshake_failure,
-                        "Renegotiation is not allowed");
-                }
-            } else {   // !isInitialHandshake && allowUnsafeRenegotiation
-                // continue with unsafe renegotiation.
-                if (debug != null && Debug.isOn("handshake")) {
-                    System.out.println(
-                            "Warning: continue with insecure renegotiation");
-                }
-            }
-        }
-
-        /*
-         * Always make sure this entire record has been digested before we
-         * start emitting output, to ensure correct digesting order.
-         */
-        input.digestNow();
-
-        /*
-         * FIRST, construct the ServerHello using the options and priorities
-         * from the ClientHello.  Update the (pending) cipher spec as we do
-         * so, and save the client's version to protect against rollback
-         * attacks.
-         *
-         * There are a bunch of minor tasks here, and one major one: deciding
-         * if the short or the full handshake sequence will be used.
-         */
-        ServerHello m1 = new ServerHello();
-
-        clientRequestedVersion = mesg.protocolVersion;
-
-        // select a proper protocol version.
-        ProtocolVersion selectedVersion =
-               selectProtocolVersion(clientRequestedVersion);
-        if (selectedVersion == null ||
-                selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "Client requested protocol " + clientRequestedVersion +
-                " not enabled or not supported");
-        }
-
-        handshakeHash.protocolDetermined(selectedVersion);
-        setVersion(selectedVersion);
-
-        m1.protocolVersion = protocolVersion;
-
-        //
-        // random ... save client and server values for later use
-        // in computing the master secret (from pre-master secret)
-        // and thence the other crypto keys.
-        //
-        // NOTE:  this use of three inputs to generating _each_ set
-        // of ciphers slows things down, but it does increase the
-        // security since each connection in the session can hold
-        // its own authenticated (and strong) keys.  One could make
-        // creation of a session a rare thing...
-        //
-        clnt_random = mesg.clnt_random;
-        svr_random = new RandomCookie(sslContext.getSecureRandom());
-        m1.svr_random = svr_random;
-
-        session = null; // forget about the current session
-        //
-        // Here we go down either of two paths:  (a) the fast one, where
-        // the client's asked to rejoin an existing session, and the server
-        // permits this; (b) the other one, where a new session is created.
-        //
-        if (mesg.sessionId.length() != 0) {
-            // client is trying to resume a session, let's see...
-
-            SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
-                        .engineGetServerSessionContext())
-                        .get(mesg.sessionId.getId());
-            //
-            // Check if we can use the fast path, resuming a session.  We
-            // can do so iff we have a valid record for that session, and
-            // the cipher suite for that session was on the list which the
-            // client requested, and if we're not forgetting any needed
-            // authentication on the part of the client.
-            //
-            if (previous != null) {
-                resumingSession = previous.isRejoinable();
-
-                if (resumingSession) {
-                    ProtocolVersion oldVersion = previous.getProtocolVersion();
-                    // cannot resume session with different version
-                    if (oldVersion != protocolVersion) {
-                        resumingSession = false;
-                    }
-                }
-
-                if (resumingSession &&
-                        (doClientAuth == SSLEngineImpl.clauth_required)) {
-                    try {
-                        previous.getPeerPrincipal();
-                    } catch (SSLPeerUnverifiedException e) {
-                        resumingSession = false;
-                    }
-                }
-
-                // validate subject identity
-                if (resumingSession) {
-                    CipherSuite suite = previous.getSuite();
-                    if (suite.keyExchange == K_KRB5 ||
-                        suite.keyExchange == K_KRB5_EXPORT) {
-                        Principal localPrincipal = previous.getLocalPrincipal();
-
-                        Subject subject = null;
-                        try {
-                            subject = AccessController.doPrivileged(
-                                new PrivilegedExceptionAction<Subject>() {
-                                public Subject run() throws Exception {
-                                    return
-                                        Krb5Helper.getServerSubject(getAccSE());
-                            }});
-                        } catch (PrivilegedActionException e) {
-                            subject = null;
-                            if (debug != null && Debug.isOn("session")) {
-                                System.out.println("Attempt to obtain" +
-                                                " subject failed!");
-                            }
-                        }
-
-                        if (subject != null) {
-                            // Eliminate dependency on KerberosPrincipal
-                            Set<Principal> principals =
-                                subject.getPrincipals(Principal.class);
-                            if (!principals.contains(localPrincipal)) {
-                                resumingSession = false;
-                                if (debug != null && Debug.isOn("session")) {
-                                    System.out.println("Subject identity" +
-                                                        " is not the same");
-                                }
-                            } else {
-                                if (debug != null && Debug.isOn("session"))
-                                    System.out.println("Subject identity" +
-                                                        " is same");
-                            }
-                        } else {
-                            resumingSession = false;
-                            if (debug != null && Debug.isOn("session"))
-                                System.out.println("Kerberos credentials are" +
-                                    " not present in the current Subject;" +
-                                    " check if " +
-                                    " javax.security.auth.useSubjectAsCreds" +
-                                    " system property has been set to false");
-                        }
-                    }
-                }
-
-                if (resumingSession) {
-                    CipherSuite suite = previous.getSuite();
-                    // verify that the ciphersuite from the cached session
-                    // is in the list of client requested ciphersuites and
-                    // we have it enabled
-                    if ((isNegotiable(suite) == false) ||
-                            (mesg.getCipherSuites().contains(suite) == false)) {
-                        resumingSession = false;
-                    } else {
-                        // everything looks ok, set the ciphersuite
-                        // this should be done last when we are sure we
-                        // will resume
-                        setCipherSuite(suite);
-                    }
-                }
-
-                if (resumingSession) {
-                    session = previous;
-                    if (debug != null &&
-                        (Debug.isOn("handshake") || Debug.isOn("session"))) {
-                        System.out.println("%% Resuming " + session);
-                    }
-                }
-            }
-        } // else client did not try to resume
-
-        //
-        // If client hasn't specified a session we can resume, start a
-        // new one and choose its cipher suite and compression options.
-        // Unless new session creation is disabled for this connection!
-        //
-        if (session == null) {
-            if (!enableNewSession) {
-                throw new SSLException("Client did not resume a session");
-            }
-
-            supportedCurves = (SupportedEllipticCurvesExtension)
-                        mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
-
-            // We only need to handle the "signature_algorithm" extension
-            // for full handshakes and TLS 1.2 or later.
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                SignatureAlgorithmsExtension signAlgs =
-                    (SignatureAlgorithmsExtension)mesg.extensions.get(
-                                    ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-                if (signAlgs != null) {
-                    Collection<SignatureAndHashAlgorithm> peerSignAlgs =
-                                            signAlgs.getSignAlgorithms();
-                    if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
-                        throw new SSLHandshakeException(
-                            "No peer supported signature algorithms");
-                    }
-
-                    Collection<SignatureAndHashAlgorithm>
-                        supportedPeerSignAlgs =
-                            SignatureAndHashAlgorithm.getSupportedAlgorithms(
-                                                            peerSignAlgs);
-                    if (supportedPeerSignAlgs.isEmpty()) {
-                        throw new SSLHandshakeException(
-                            "No supported signature and hash algorithm " +
-                            "in common");
-                    }
-
-                    setPeerSupportedSignAlgs(supportedPeerSignAlgs);
-                } // else, need to use peer implicit supported signature algs
-            }
-
-            session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
-                        getLocalSupportedSignAlgs(),
-                        sslContext.getSecureRandom(),
-                        getHostAddressSE(), getPortSE());
-
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (peerSupportedSignAlgs != null) {
-                    session.setPeerSupportedSignatureAlgorithms(
-                            peerSupportedSignAlgs);
-                }   // else, we will set the implicit peer supported signature
-                    // algorithms in chooseCipherSuite()
-            }
-
-            // set the handshake session
-            setHandshakeSessionSE(session);
-
-            // choose cipher suite and corresponding private key
-            chooseCipherSuite(mesg);
-
-            session.setSuite(cipherSuite);
-            session.setLocalPrivateKey(privateKey);
-
-            // chooseCompression(mesg);
-        } else {
-            // set the handshake session
-            setHandshakeSessionSE(session);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (resumingSession) {
-                handshakeHash.setCertificateVerifyAlg(null);
-            }
-            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
-        }
-
-        m1.cipherSuite = cipherSuite;
-        m1.sessionId = session.getSessionId();
-        m1.compression_method = session.getCompression();
-
-        if (secureRenegotiation) {
-            // For ServerHellos that are initial handshakes, then the
-            // "renegotiated_connection" field in "renegotiation_info"
-            // extension is of zero length.
-            //
-            // For ServerHellos that are renegotiating, this field contains
-            // the concatenation of client_verify_data and server_verify_data.
-            //
-            // Note that for initial handshakes, both the clientVerifyData
-            // variable and serverVerifyData variable are of zero length.
-            HelloExtension serverHelloRI = new RenegotiationInfoExtension(
-                                        clientVerifyData, serverVerifyData);
-            m1.extensions.add(serverHelloRI);
-        }
-
-        if (debug != null && Debug.isOn("handshake")) {
-            m1.print(System.out);
-            System.out.println("Cipher suite:  " + session.getSuite());
-        }
-        m1.write(output);
-
-        //
-        // If we are resuming a session, we finish writing handshake
-        // messages right now and then finish.
-        //
-        if (resumingSession) {
-            calculateConnectionKeys(session.getMasterSecret());
-            sendChangeCipherAndFinish(false);
-            return;
-        }
-
-
-        /*
-         * SECOND, write the server Certificate(s) if we need to.
-         *
-         * NOTE:  while an "anonymous RSA" mode is explicitly allowed by
-         * the protocol, we can't support it since all of the SSL flavors
-         * defined in the protocol spec are explicitly stated to require
-         * using RSA certificates.
-         */
-        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-            // Server certificates are omitted for Kerberos ciphers
-
-        } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
-            if (certs == null) {
-                throw new RuntimeException("no certificates");
-            }
-
-            CertificateMsg m2 = new CertificateMsg(certs);
-
-            /*
-             * Set local certs in the SSLSession, output
-             * debug info, and then actually write to the client.
-             */
-            session.setLocalCertificates(certs);
-            if (debug != null && Debug.isOn("handshake")) {
-                m2.print(System.out);
-            }
-            m2.write(output);
-
-            // XXX has some side effects with OS TCP buffering,
-            // leave it out for now
-
-            // let client verify chain in the meantime...
-            // output.flush();
-        } else {
-            if (certs != null) {
-                throw new RuntimeException("anonymous keyexchange with certs");
-            }
-        }
-
-        /*
-         * THIRD, the ServerKeyExchange message ... iff it's needed.
-         *
-         * It's usually needed unless there's an encryption-capable
-         * RSA cert, or a D-H cert.  The notable exception is that
-         * exportable ciphers used with big RSA keys need to downgrade
-         * to use short RSA keys, even when the key/cert encrypts OK.
-         */
-
-        ServerKeyExchange m3;
-        switch (keyExchange) {
-        case K_RSA:
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            // no server key exchange for RSA or KRB5 ciphersuites
-            m3 = null;
-            break;
-        case K_RSA_EXPORT:
-            if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                try {
-                    m3 = new RSA_ServerKeyExchange(
-                        tempPublicKey, privateKey,
-                        clnt_random, svr_random,
-                        sslContext.getSecureRandom());
-                    privateKey = tempPrivateKey;
-                } catch (GeneralSecurityException e) {
-                    throwSSLException
-                        ("Error generating RSA server key exchange", e);
-                    m3 = null; // make compiler happy
-                }
-            } else {
-                // RSA_EXPORT with short key, don't need ServerKeyExchange
-                m3 = null;
-            }
-            break;
-        case K_DHE_RSA:
-        case K_DHE_DSS:
-            try {
-                m3 = new DH_ServerKeyExchange(dh,
-                    privateKey,
-                    clnt_random.random_bytes,
-                    svr_random.random_bytes,
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm,
-                    protocolVersion);
-            } catch (GeneralSecurityException e) {
-                throwSSLException("Error generating DH server key exchange", e);
-                m3 = null; // make compiler happy
-            }
-            break;
-        case K_DH_ANON:
-            m3 = new DH_ServerKeyExchange(dh, protocolVersion);
-            break;
-        case K_ECDHE_RSA:
-        case K_ECDHE_ECDSA:
-        case K_ECDH_ANON:
-            try {
-                m3 = new ECDH_ServerKeyExchange(ecdh,
-                    privateKey,
-                    clnt_random.random_bytes,
-                    svr_random.random_bytes,
-                    sslContext.getSecureRandom(),
-                    preferableSignatureAlgorithm,
-                    protocolVersion);
-            } catch (GeneralSecurityException e) {
-                throwSSLException(
-                    "Error generating ECDH server key exchange", e);
-                m3 = null; // make compiler happy
-            }
-            break;
-        case K_ECDH_RSA:
-        case K_ECDH_ECDSA:
-            // ServerKeyExchange not used for fixed ECDH
-            m3 = null;
-            break;
-        default:
-            throw new RuntimeException("internal error: " + keyExchange);
-        }
-        if (m3 != null) {
-            if (debug != null && Debug.isOn("handshake")) {
-                m3.print(System.out);
-            }
-            m3.write(output);
-        }
-
-        //
-        // FOURTH, the CertificateRequest message.  The details of
-        // the message can be affected by the key exchange algorithm
-        // in use.  For example, certs with fixed Diffie-Hellman keys
-        // are only useful with the DH_DSS and DH_RSA key exchange
-        // algorithms.
-        //
-        // Needed only if server requires client to authenticate self.
-        // Illegal for anonymous flavors, so we need to check that.
-        //
-        // CertificateRequest is omitted for Kerberos ciphers
-        if (doClientAuth != SSLEngineImpl.clauth_none &&
-                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&
-                keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {
-
-            CertificateRequest m4;
-            X509Certificate caCerts[];
-
-            Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                // We currently use all local upported signature and hash
-                // algorithms. However, to minimize the computation cost
-                // of requested hash algorithms, we may use a restricted
-                // set of signature algorithms in the future.
-                localSignAlgs = getLocalSupportedSignAlgs();
-                if (localSignAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                }
-
-                Set<String> localHashAlgs =
-                    SignatureAndHashAlgorithm.getHashAlgorithmNames(
-                        localSignAlgs);
-                if (localHashAlgs.isEmpty()) {
-                    throw new SSLHandshakeException(
-                            "No supported signature algorithm");
-                }
-                handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs);
-            }
-
-            caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
-            m4 = new CertificateRequest(caCerts, keyExchange,
-                                            localSignAlgs, protocolVersion);
-
-            if (debug != null && Debug.isOn("handshake")) {
-                m4.print(System.out);
-            }
-            m4.write(output);
-        } else {
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                handshakeHash.setCertificateVerifyAlg(null);
-            }
-        }
-
-        /*
-         * FIFTH, say ServerHelloDone.
-         */
-        ServerHelloDone m5 = new ServerHelloDone();
-
-        if (debug != null && Debug.isOn("handshake")) {
-            m5.print(System.out);
-        }
-        m5.write(output);
-
-        /*
-         * Flush any buffered messages so the client will see them.
-         * Ideally, all the messages above go in a single network level
-         * message to the client.  Without big Certificate chains, it's
-         * going to be the common case.
-         */
-        output.flush();
-    }
-
-    /*
-     * Choose cipher suite from among those supported by client. Sets
-     * the cipherSuite and keyExchange variables.
-     */
-    private void chooseCipherSuite(ClientHello mesg) throws IOException {
-        for (CipherSuite suite : mesg.getCipherSuites().collection()) {
-            if (isNegotiable(suite) == false) {
-                continue;
-            }
-
-            if (doClientAuth == SSLEngineImpl.clauth_required) {
-                if ((suite.keyExchange == K_DH_ANON) ||
-                    (suite.keyExchange == K_ECDH_ANON)) {
-                    continue;
-                }
-            }
-            if (trySetCipherSuite(suite) == false) {
-                continue;
-            }
-            return;
-        }
-        fatalSE(Alerts.alert_handshake_failure,
-                    "no cipher suites in common");
-    }
-
-    /**
-     * Set the given CipherSuite, if possible. Return the result.
-     * The call succeeds if the CipherSuite is available and we have
-     * the necessary certificates to complete the handshake. We don't
-     * check if the CipherSuite is actually enabled.
-     *
-     * If successful, this method also generates ephemeral keys if
-     * required for this ciphersuite. This may take some time, so this
-     * method should only be called if you really want to use the
-     * CipherSuite.
-     *
-     * This method is called from chooseCipherSuite() in this class.
-     */
-    boolean trySetCipherSuite(CipherSuite suite) {
-        /*
-         * If we're resuming a session we know we can
-         * support this key exchange algorithm and in fact
-         * have already cached the result of it in
-         * the session state.
-         */
-        if (resumingSession) {
-            return true;
-        }
-
-        if (suite.isNegotiable() == false) {
-            return false;
-        }
-
-        // must not negotiate the obsoleted weak cipher suites.
-        if (protocolVersion.v >= suite.obsoleted) {
-            return false;
-        }
-
-        // must not negotiate unsupported cipher suites.
-        if (protocolVersion.v < suite.supported) {
-            return false;
-        }
-
-        KeyExchange keyExchange = suite.keyExchange;
-
-        // null out any existing references
-        privateKey = null;
-        certs = null;
-        dh = null;
-        tempPrivateKey = null;
-        tempPublicKey = null;
-
-        Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (peerSupportedSignAlgs != null) {
-                supportedSignAlgs = peerSupportedSignAlgs;
-            } else {
-                SignatureAndHashAlgorithm algorithm = null;
-
-                // we may optimize the performance
-                switch (keyExchange) {
-                    // If the negotiated key exchange algorithm is one of
-                    // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),
-                    // behave as if client had sent the value {sha1,rsa}.
-                    case K_RSA:
-                    case K_DHE_RSA:
-                    case K_DH_RSA:
-                    // case K_RSA_PSK:
-                    case K_ECDH_RSA:
-                    case K_ECDHE_RSA:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.RSA.value, 0);
-                        break;
-                    // If the negotiated key exchange algorithm is one of
-                    // (DHE_DSS, DH_DSS), behave as if the client had
-                    // sent the value {sha1,dsa}.
-                    case K_DHE_DSS:
-                    case K_DH_DSS:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.DSA.value, 0);
-                        break;
-                    // If the negotiated key exchange algorithm is one of
-                    // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client
-                    // had sent value {sha1,ecdsa}.
-                    case K_ECDH_ECDSA:
-                    case K_ECDHE_ECDSA:
-                        algorithm = SignatureAndHashAlgorithm.valueOf(
-                                HashAlgorithm.SHA1.value,
-                                SignatureAlgorithm.ECDSA.value, 0);
-                        break;
-                    default:
-                        // no peer supported signature algorithms
-                }
-
-                if (algorithm == null) {
-                    supportedSignAlgs =
-                        Collections.<SignatureAndHashAlgorithm>emptySet();
-                } else {
-                    supportedSignAlgs =
-                        new ArrayList<SignatureAndHashAlgorithm>(1);
-                    supportedSignAlgs.add(algorithm);
-                }
-
-                // Sets the peer supported signature algorithm to use in KM
-                // temporarily.
-                session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
-            }
-        }
-
-        switch (keyExchange) {
-        case K_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-            break;
-        case K_RSA_EXPORT:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            try {
-               if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                    if (!setupEphemeralRSAKeys(suite.exportable)) {
-                        return false;
-                    }
-               }
-            } catch (RuntimeException e) {
-                // could not determine keylength, ignore key
-                return false;
-            }
-            break;
-        case K_DHE_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                        supportedSignAlgs, "RSA", privateKey);
-                if (preferableSignatureAlgorithm == null) {
-                    return false;
-                }
-            }
-
-            setupEphemeralDHKeys(suite.exportable);
-            break;
-        case K_ECDHE_RSA:
-            // need RSA certs for authentication
-            if (setupPrivateKeyAndChain("RSA") == false) {
-                return false;
-            }
-
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                        supportedSignAlgs, "RSA", privateKey);
-                if (preferableSignatureAlgorithm == null) {
-                    return false;
-                }
-            }
-
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        case K_DHE_DSS:
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                                supportedSignAlgs, "DSA");
-                if (preferableSignatureAlgorithm == null) {
-                    return false;
-                }
-            }
-
-            // need DSS certs for authentication
-            if (setupPrivateKeyAndChain("DSA") == false) {
-                return false;
-            }
-            setupEphemeralDHKeys(suite.exportable);
-            break;
-        case K_ECDHE_ECDSA:
-            // get preferable peer signature algorithm for server key exchange
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                preferableSignatureAlgorithm =
-                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                                            supportedSignAlgs, "ECDSA");
-                if (preferableSignatureAlgorithm == null) {
-                    return false;
-                }
-            }
-
-            // need EC cert signed using EC
-            if (setupPrivateKeyAndChain("EC_EC") == false) {
-                return false;
-            }
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        case K_ECDH_RSA:
-            // need EC cert signed using RSA
-            if (setupPrivateKeyAndChain("EC_RSA") == false) {
-                return false;
-            }
-            setupStaticECDHKeys();
-            break;
-        case K_ECDH_ECDSA:
-            // need EC cert signed using EC
-            if (setupPrivateKeyAndChain("EC_EC") == false) {
-                return false;
-            }
-            setupStaticECDHKeys();
-            break;
-        case K_KRB5:
-        case K_KRB5_EXPORT:
-            // need Kerberos Key
-            if (!setupKerberosKeys()) {
-                return false;
-            }
-            break;
-        case K_DH_ANON:
-            // no certs needed for anonymous
-            setupEphemeralDHKeys(suite.exportable);
-            break;
-        case K_ECDH_ANON:
-            // no certs needed for anonymous
-            if (setupEphemeralECDHKeys() == false) {
-                return false;
-            }
-            break;
-        default:
-            // internal error, unknown key exchange
-            throw new RuntimeException("Unrecognized cipherSuite: " + suite);
-        }
-        setCipherSuite(suite);
-
-        // set the peer implicit supported signature algorithms
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            if (peerSupportedSignAlgs == null) {
-                setPeerSupportedSignAlgs(supportedSignAlgs);
-                // we had alreay update the session
-            }
-        }
-        return true;
-    }
-
-    /*
-     * Get some "ephemeral" RSA keys for this context. This means
-     * generating them if it's not already been done.
-     *
-     * Note that we currently do not implement any ciphersuites that use
-     * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
-     * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
-     * This means that export is always true and 512 bit keys are generated.
-     */
-    private boolean setupEphemeralRSAKeys(boolean export) {
-        KeyPair kp = sslContext.getEphemeralKeyManager().
-                        getRSAKeyPair(export, sslContext.getSecureRandom());
-        if (kp == null) {
-            return false;
-        } else {
-            tempPublicKey = kp.getPublic();
-            tempPrivateKey = kp.getPrivate();
-            return true;
-        }
-    }
-
-    /*
-     * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
-     * We don't reuse these, for improved forward secrecy.
-     */
-    private void setupEphemeralDHKeys(boolean export) {
-        /*
-         * Diffie-Hellman keys ... we use 768 bit private keys due
-         * to the "use twice as many key bits as bits you want secret"
-         * rule of thumb, assuming we want the same size premaster
-         * secret with Diffie-Hellman and RSA key exchanges.  Except
-         * that exportable ciphers max out at 512 bits modulus values.
-         */
-        dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
-    }
-
-    // Setup the ephemeral ECDH parameters.
-    // If we cannot continue because we do not support any of the curves that
-    // the client requested, return false. Otherwise (all is well), return true.
-    private boolean setupEphemeralECDHKeys() {
-        int index = -1;
-        if (supportedCurves != null) {
-            // if the client sent the supported curves extension, pick the
-            // first one that we support;
-            for (int curveId : supportedCurves.curveIds()) {
-                if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
-                    index = curveId;
-                    break;
-                }
-            }
-            if (index < 0) {
-                // no match found, cannot use this ciphersuite
-                return false;
-            }
-        } else {
-            // pick our preference
-            index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
-        }
-        String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
-        ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
-        return true;
-    }
-
-    private void setupStaticECDHKeys() {
-        // don't need to check whether the curve is supported, already done
-        // in setupPrivateKeyAndChain().
-        ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
-    }
-
-    /**
-     * Retrieve the server key and certificate for the specified algorithm
-     * from the KeyManager and set the instance variables.
-     *
-     * @return true if successful, false if not available or invalid
-     */
-    private boolean setupPrivateKeyAndChain(String algorithm) {
-        X509ExtendedKeyManager km = sslContext.getX509KeyManager();
-        String alias;
-        if (conn != null) {
-            alias = km.chooseServerAlias(algorithm, null, conn);
-        } else {
-            alias = km.chooseEngineServerAlias(algorithm, null, engine);
-        }
-        if (alias == null) {
-            return false;
-        }
-        PrivateKey tempPrivateKey = km.getPrivateKey(alias);
-        if (tempPrivateKey == null) {
-            return false;
-        }
-        X509Certificate[] tempCerts = km.getCertificateChain(alias);
-        if ((tempCerts == null) || (tempCerts.length == 0)) {
-            return false;
-        }
-        String keyAlgorithm = algorithm.split("_")[0];
-        PublicKey publicKey = tempCerts[0].getPublicKey();
-        if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
-                || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
-            return false;
-        }
-        // For ECC certs, check whether we support the EC domain parameters.
-        // If the client sent a SupportedEllipticCurves ClientHello extension,
-        // check against that too.
-        if (keyAlgorithm.equals("EC")) {
-            if (publicKey instanceof ECPublicKey == false) {
-                return false;
-            }
-            ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
-            int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
-            if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
-                return false;
-            }
-            if ((supportedCurves != null) && !supportedCurves.contains(index)) {
-                return false;
-            }
-        }
-        this.privateKey = tempPrivateKey;
-        this.certs = tempCerts;
-        return true;
-    }
-
-    /**
-     * Retrieve the Kerberos key for the specified server principal
-     * from the JAAS configuration file.
-     *
-     * @return true if successful, false if not available or invalid
-     */
-    private boolean setupKerberosKeys() {
-        if (kerberosKeys != null) {
-            return true;
-        }
-        try {
-            final AccessControlContext acc = getAccSE();
-            kerberosKeys = AccessController.doPrivileged(
-                // Eliminate dependency on KerberosKey
-                new PrivilegedExceptionAction<SecretKey[]>() {
-                public SecretKey[] run() throws Exception {
-                    // get kerberos key for the default principal
-                    return Krb5Helper.getServerKeys(acc);
-                        }});
-
-            // check permission to access and use the secret key of the
-            // Kerberized "host" service
-            if (kerberosKeys != null && kerberosKeys.length > 0) {
-                if (debug != null && Debug.isOn("handshake")) {
-                    for (SecretKey k: kerberosKeys) {
-                        System.out.println("Using Kerberos key: " +
-                            k);
-                    }
-                }
-
-                String serverPrincipal =
-                    Krb5Helper.getServerPrincipalName(kerberosKeys[0]);
-                SecurityManager sm = System.getSecurityManager();
-                try {
-                   if (sm != null) {
-                      // Eliminate dependency on ServicePermission
-                      sm.checkPermission(Krb5Helper.getServicePermission(
-                          serverPrincipal, "accept"), acc);
-                   }
-                } catch (SecurityException se) {
-                   kerberosKeys = null;
-                   // %%% destroy keys? or will that affect Subject?
-                   if (debug != null && Debug.isOn("handshake"))
-                      System.out.println("Permission to access Kerberos"
-                                + " secret key denied");
-                   return false;
-                }
-            }
-            return (kerberosKeys != null && kerberosKeys.length > 0);
-        } catch (PrivilegedActionException e) {
-            // Likely exception here is LoginExceptin
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Attempt to obtain Kerberos key failed: "
-                                + e.toString());
-            }
-            return false;
-        }
-    }
-
-    /*
-     * For Kerberos ciphers, the premaster secret is encrypted using
-     * the session key. See RFC 2712.
-     */
-    private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
-        throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        // Record the principals involved in exchange
-        session.setPeerPrincipal(mesg.getPeerPrincipal());
-        session.setLocalPrincipal(mesg.getLocalPrincipal());
-
-        byte[] b = mesg.getUnencryptedPreMasterSecret();
-        return new SecretKeySpec(b, "TlsPremasterSecret");
-    }
-
-    /*
-     * Diffie Hellman key exchange is used when the server presented
-     * D-H parameters in its certificate (signed using RSA or DSS/DSA),
-     * or else the server presented no certificate but sent D-H params
-     * in a ServerKeyExchange message.  Use of D-H is specified by the
-     * cipher suite chosen.
-     *
-     * The message optionally contains the client's D-H public key (if
-     * it wasn't not sent in a client certificate).  As always with D-H,
-     * if a client and a server have each other's D-H public keys and
-     * they use common algorithm parameters, they have a shared key
-     * that's derived via the D-H calculation.  That key becomes the
-     * pre-master secret.
-     */
-    private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
-    }
-
-    private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        return ecdh.getAgreedSecret(mesg.getEncodedPoint());
-    }
-
-    /*
-     * Client wrote a message to verify the certificate it sent earlier.
-     *
-     * Note that this certificate isn't involved in key exchange.  Client
-     * authentication messages are included in the checksums used to
-     * validate the handshake (e.g. Finished messages).  Other than that,
-     * the _exact_ identity of the client is less fundamental to protocol
-     * security than its role in selecting keys via the pre-master secret.
-     */
-    private void clientCertificateVerify(CertificateVerify mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-            SignatureAndHashAlgorithm signAlg =
-                mesg.getPreferableSignatureAlgorithm();
-            if (signAlg == null) {
-                throw new SSLHandshakeException(
-                        "Illegal CertificateVerify message");
-            }
-
-            String hashAlg =
-                SignatureAndHashAlgorithm.getHashAlgorithmName(signAlg);
-            if (hashAlg == null || hashAlg.length() == 0) {
-                throw new SSLHandshakeException(
-                        "No supported hash algorithm");
-            }
-
-            handshakeHash.setCertificateVerifyAlg(hashAlg);
-        }
-
-        try {
-            PublicKey publicKey =
-                session.getPeerCertificates()[0].getPublicKey();
-
-            boolean valid = mesg.verify(protocolVersion, handshakeHash,
-                                        publicKey, session.getMasterSecret());
-            if (valid == false) {
-                fatalSE(Alerts.alert_bad_certificate,
-                            "certificate verify message signature error");
-            }
-        } catch (GeneralSecurityException e) {
-            fatalSE(Alerts.alert_bad_certificate,
-                "certificate verify format error", e);
-        }
-
-        // reset the flag for clientCertificateVerify message
-        needClientVerify = false;
-    }
-
-
-    /*
-     * Client writes "finished" at the end of its handshake, after cipher
-     * spec is changed.   We verify it and then send ours.
-     *
-     * When we're resuming a session, we'll have already sent our own
-     * Finished message so just the verification is needed.
-     */
-    private void clientFinished(Finished mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        /*
-         * Verify if client did send the certificate when client
-         * authentication was required, otherwise server should not proceed
-         */
-        if (doClientAuth == SSLEngineImpl.clauth_required) {
-           // get X500Principal of the end-entity certificate for X509-based
-           // ciphersuites, or Kerberos principal for Kerberos ciphersuites
-           session.getPeerPrincipal();
-        }
-
-        /*
-         * Verify if client did send clientCertificateVerify message following
-         * the client Certificate, otherwise server should not proceed
-         */
-        if (needClientVerify) {
-                fatalSE(Alerts.alert_handshake_failure,
-                        "client did not send certificate verify message");
-        }
-
-        /*
-         * Verify the client's message with the "before" digest of messages,
-         * and forget about continuing to use that digest.
-         */
-        boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
-            session.getMasterSecret());
-
-        if (!verified) {
-            fatalSE(Alerts.alert_handshake_failure,
-                        "client 'finished' message doesn't verify");
-            // NOTREACHED
-        }
-
-        /*
-         * save client verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            clientVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * OK, it verified.  If we're doing the full handshake, add that
-         * "Finished" message to the hash of handshake messages, then send
-         * the change_cipher_spec and Finished message.
-         */
-        if (!resumingSession) {
-            input.digestNow();
-            sendChangeCipherAndFinish(true);
-        }
-
-        /*
-         * Update the session cache only after the handshake completed, else
-         * we're open to an attack against a partially completed handshake.
-         */
-        session.setLastAccessedTime(System.currentTimeMillis());
-        if (!resumingSession && session.isRejoinable()) {
-            ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
-                .put(session);
-            if (debug != null && Debug.isOn("session")) {
-                System.out.println(
-                    "%% Cached server session: " + session);
-            }
-        } else if (!resumingSession &&
-                debug != null && Debug.isOn("session")) {
-            System.out.println(
-                "%% Didn't cache non-resumable server session: "
-                + session);
-        }
-    }
-
-    /*
-     * Compute finished message with the "server" digest (and then forget
-     * about that digest, it can't be used again).
-     */
-    private void sendChangeCipherAndFinish(boolean finishedTag)
-            throws IOException {
-
-        output.flush();
-
-        Finished mesg = new Finished(protocolVersion, handshakeHash,
-            Finished.SERVER, session.getMasterSecret(), cipherSuite);
-
-        /*
-         * Send the change_cipher_spec record; then our Finished handshake
-         * message will be the last handshake message.  Flush, and now we
-         * are ready for application data!!
-         */
-        sendChangeCipherSpec(mesg, finishedTag);
-
-        /*
-         * save server verify data for secure renegotiation
-         */
-        if (secureRenegotiation) {
-            serverVerifyData = mesg.getVerifyData();
-        }
-
-        /*
-         * Update state machine so client MUST send 'finished' next
-         * The update should only take place if it is not in the fast
-         * handshake mode since the server has to wait for a finished
-         * message from the client.
-         */
-        if (finishedTag) {
-            state = HandshakeMessage.ht_finished;
-        }
-    }
-
-
-    /*
-     * Returns a HelloRequest message to kickstart renegotiations
-     */
-    HandshakeMessage getKickstartMessage() {
-        return new HelloRequest();
-    }
-
-
-    /*
-     * Fault detected during handshake.
-     */
-    void handshakeAlert(byte description) throws SSLProtocolException {
-
-        String message = Alerts.alertDescription(description);
-
-        if (debug != null && Debug.isOn("handshake")) {
-            System.out.println("SSL -- handshake alert:  "
-                + message);
-        }
-
-        /*
-         * It's ok to get a no_certificate alert from a client of which
-         * we *requested* authentication information.
-         * However, if we *required* it, then this is not acceptable.
-         *
-         * Anyone calling getPeerCertificates() on the
-         * session will get an SSLPeerUnverifiedException.
-         */
-        if ((description == Alerts.alert_no_certificate) &&
-                (doClientAuth == SSLEngineImpl.clauth_requested)) {
-            return;
-        }
-
-        throw new SSLProtocolException("handshake alert: " + message);
-    }
-
-    /*
-     * RSA key exchange is normally used.  The client encrypts a "pre-master
-     * secret" with the server's public key, from the Certificate (or else
-     * ServerKeyExchange) message that was sent to it by the server.  That's
-     * decrypted using the private key before we get here.
-     */
-    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
-            throws IOException {
-
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-        return mesg.preMaster;
-    }
-
-    /*
-     * Verify the certificate sent by the client. We'll only get one if we
-     * sent a CertificateRequest to request client authentication. If we
-     * are in TLS mode, the client may send a message with no certificates
-     * to indicate it does not have an appropriate chain. (In SSLv3 mode,
-     * it would send a no certificate alert).
-     */
-    private void clientCertificate(CertificateMsg mesg) throws IOException {
-        if (debug != null && Debug.isOn("handshake")) {
-            mesg.print(System.out);
-        }
-
-        X509Certificate[] peerCerts = mesg.getCertificateChain();
-
-        if (peerCerts.length == 0) {
-            /*
-             * If the client authentication is only *REQUESTED* (e.g.
-             * not *REQUIRED*, this is an acceptable condition.)
-             */
-            if (doClientAuth == SSLEngineImpl.clauth_requested) {
-                // Smart (aka stupid) to forecast that no CertificateVerify
-                // message will be received.
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    handshakeHash.setCertificateVerifyAlg(null);
-                }
-                return;
-            } else {
-                fatalSE(Alerts.alert_bad_certificate,
-                    "null cert chain");
-            }
-        }
-
-        // ask the trust manager to verify the chain
-        X509TrustManager tm = sslContext.getX509TrustManager();
-
-        try {
-            // find out the types of client authentication used
-            PublicKey key = peerCerts[0].getPublicKey();
-            String keyAlgorithm = key.getAlgorithm();
-            String authType;
-            if (keyAlgorithm.equals("RSA")) {
-                authType = "RSA";
-            } else if (keyAlgorithm.equals("DSA")) {
-                authType = "DSA";
-            } else if (keyAlgorithm.equals("EC")) {
-                authType = "EC";
-            } else {
-                // unknown public key type
-                authType = "UNKNOWN";
-            }
-
-            if (tm instanceof X509ExtendedTrustManager) {
-                if (conn != null) {
-                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        peerCerts.clone(),
-                        authType,
-                        conn);
-                } else {
-                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        peerCerts.clone(),
-                        authType,
-                        engine);
-                }
-            } else {
-                // Unlikely to happen, because we have wrapped the old
-                // X509TrustManager with the new X509ExtendedTrustManager.
-                throw new CertificateException(
-                    "Improper X509TrustManager implementation");
-            }
-        } catch (CertificateException e) {
-            // This will throw an exception, so include the original error.
-            fatalSE(Alerts.alert_certificate_unknown, e);
-        }
-        // set the flag for clientCertificateVerify message
-        needClientVerify = true;
-
-        session.setPeerCertificates(peerCerts);
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SessionId.java b/ojluni/src/main/java/sun/security/ssl/SessionId.java
deleted file mode 100755
index 1707d42..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SessionId.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.SecureRandom;
-
-/**
- * Encapsulates an SSL session ID.  SSL Session IDs are not reused by
- * servers during the lifetime of any sessions it created.  Sessions may
- * be used by many connections, either concurrently (for example, two
- * connections to a web server at the same time) or sequentially (over as
- * long a time period as is allowed by a given server).
- *
- * @author Satish Dharmaraj
- * @author David Brownell
- */
-final
-class SessionId
-{
-    private byte sessionId [];          // max 32 bytes
-
-    /** Constructs a new session ID ... perhaps for a rejoinable session */
-    SessionId (boolean isRejoinable, SecureRandom generator)
-    {
-        if (isRejoinable)
-            // this will be unique, it's a timestamp plus much randomness
-            sessionId = new RandomCookie (generator).random_bytes;
-        else
-            sessionId = new byte [0];
-    }
-
-    /** Constructs a session ID from a byte array (max size 32 bytes) */
-    SessionId (byte sessionId [])
-        { this.sessionId = sessionId; }
-
-    /** Returns the length of the ID, in bytes */
-    int length ()
-        { return sessionId.length; }
-
-    /** Returns the bytes in the ID.  May be an empty array.  */
-    byte [] getId ()
-    {
-        return sessionId.clone ();
-    }
-
-    /** Returns the ID as a string */
-    public String toString ()
-    {
-        int             len = sessionId.length;
-        StringBuffer    s = new StringBuffer (10 + 2 * len);
-
-        s.append ("{");
-        for (int i = 0; i < len; i++) {
-            s.append (0x0ff & sessionId [i]);
-            if (i != (len - 1))
-                s.append (", ");
-        }
-        s.append ("}");
-        return s.toString ();
-    }
-
-
-    /** Returns a value which is the same for session IDs which are equal */
-    public int hashCode ()
-    {
-        int     retval = 0;
-
-        for (int i = 0; i < sessionId.length; i++)
-            retval += sessionId [i];
-        return retval;
-    }
-
-    /** Returns true if the parameter is the same session ID */
-    public boolean equals (Object obj)
-    {
-        if (!(obj instanceof SessionId))
-            return false;
-
-        SessionId s = (SessionId) obj;
-        byte b [] = s.getId ();
-
-        if (b.length != sessionId.length)
-            return false;
-        for (int i = 0; i < sessionId.length; i++) {
-            if (b [i] != sessionId [i])
-                return false;
-        }
-        return true;
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java b/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java
deleted file mode 100755
index 043b9b1..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.PrivateKey;
-
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.EnumSet;
-import java.util.TreeMap;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ArrayList;
-
-import sun.security.util.KeyUtil;
-
-/**
- * Signature and hash algorithm.
- *
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures.  The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- *     enum {
- *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *         sha512(6), (255)
- *     } HashAlgorithm;
- *
- *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *       SignatureAlgorithm;
- *
- *     struct {
- *           HashAlgorithm hash;
- *           SignatureAlgorithm signature;
- *     } SignatureAndHashAlgorithm;
- */
-final class SignatureAndHashAlgorithm {
-
-    // minimum priority for default enabled algorithms
-    final static int SUPPORTED_ALG_PRIORITY_MAX_NUM = 0x00F0;
-
-    // performance optimization
-    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
-                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
-
-    // supported pairs of signature and hash algorithm
-    private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
-    private final static Map<Integer, SignatureAndHashAlgorithm> priorityMap;
-
-    // the hash algorithm
-    private HashAlgorithm hash;
-
-    // the signature algorithm
-    private SignatureAlgorithm signature;
-
-    // id in 16 bit MSB format, i.e. 0x0603 for SHA512withECDSA
-    private int id;
-
-    // the standard algorithm name, for example "SHA512withECDSA"
-    private String algorithm;
-
-    // Priority for the preference order. The lower the better.
-    //
-    // If the algorithm is unsupported, its priority should be bigger
-    // than SUPPORTED_ALG_PRIORITY_MAX_NUM.
-    private int priority;
-
-    // constructor for supported algorithm
-    private SignatureAndHashAlgorithm(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-        this.hash = hash;
-        this.signature = signature;
-        this.algorithm = algorithm;
-        this.id = ((hash.value & 0xFF) << 8) | (signature.value & 0xFF);
-        this.priority = priority;
-    }
-
-    // constructor for unsupported algorithm
-    private SignatureAndHashAlgorithm(String algorithm, int id, int sequence) {
-        this.hash = HashAlgorithm.valueOf((id >> 8) & 0xFF);
-        this.signature = SignatureAlgorithm.valueOf(id & 0xFF);
-        this.algorithm = algorithm;
-        this.id = id;
-
-        // add one more to the sequece number, in case that the number is zero
-        this.priority = SUPPORTED_ALG_PRIORITY_MAX_NUM + sequence + 1;
-    }
-
-    // Note that we do not use the sequence argument for supported algorithms,
-    // so please don't sort by comparing the objects read from handshake
-    // messages.
-    static SignatureAndHashAlgorithm valueOf(int hash,
-            int signature, int sequence) {
-        hash &= 0xFF;
-        signature &= 0xFF;
-
-        int id = (hash << 8) | signature;
-        SignatureAndHashAlgorithm signAlg = supportedMap.get(id);
-        if (signAlg == null) {
-            // unsupported algorithm
-            signAlg = new SignatureAndHashAlgorithm(
-                "Unknown (hash:0x" + Integer.toString(hash, 16) +
-                ", signature:0x" + Integer.toString(signature, 16) + ")",
-                id, sequence);
-        }
-
-        return signAlg;
-    }
-
-    int getHashValue() {
-        return (id >> 8) & 0xFF;
-    }
-
-    int getSignatureValue() {
-        return id & 0xFF;
-    }
-
-    String getAlgorithmName() {
-        return algorithm;
-    }
-
-    // return the size of a SignatureAndHashAlgorithm structure in TLS record
-    static int sizeInRecord() {
-        return 2;
-    }
-
-    // Get local supported algorithm collection complying to
-    // algorithm constraints
-    static Collection<SignatureAndHashAlgorithm>
-            getSupportedAlgorithms(AlgorithmConstraints constraints) {
-
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        synchronized (priorityMap) {
-            for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
-                if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                        constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                                sigAlg.algorithm, null)) {
-                    supported.add(sigAlg);
-                }
-            }
-        }
-
-        return supported;
-    }
-
-    // Get supported algorithm collection from an untrusted collection
-    static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
-            Collection<SignatureAndHashAlgorithm> algorithms ) {
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
-                supported.add(sigAlg);
-            }
-        }
-
-        return supported;
-    }
-
-    static String[] getAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        ArrayList<String> algorithmNames = new ArrayList<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                algorithmNames.add(sigAlg.algorithm);
-            }
-        }
-
-        String[] array = new String[algorithmNames.size()];
-        return algorithmNames.toArray(array);
-    }
-
-    static Set<String> getHashAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        Set<String> algorithmNames = new HashSet<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                if (sigAlg.hash.value > 0) {
-                    algorithmNames.add(sigAlg.hash.standardName);
-                }
-            }
-        }
-
-        return algorithmNames;
-    }
-
-    static String getHashAlgorithmName(SignatureAndHashAlgorithm algorithm) {
-        return algorithm.hash.standardName;
-    }
-
-    private static void supports(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-
-        SignatureAndHashAlgorithm pair =
-            new SignatureAndHashAlgorithm(hash, signature, algorithm, priority);
-        if (supportedMap.put(pair.id, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, id: " +
-                pair.id);
-        }
-        if (priorityMap.put(pair.priority, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, priority: " +
-                pair.priority);
-        }
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-        Collection<SignatureAndHashAlgorithm> algorithms, String expected) {
-
-        return SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                algorithms, expected, null);
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-        Collection<SignatureAndHashAlgorithm> algorithms,
-        String expected, PrivateKey signingKey) {
-
-        if (expected == null && !algorithms.isEmpty()) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
-                    return sigAlg;
-                }
-            }
-
-            return null;  // no supported algorithm
-        }
-
-        if (expected == null ) {
-            return null;  // no expected algorithm, no supported algorithm
-        }
-
-        /*
-         * Need to check RSA key length to match the length of hash value
-         */
-        int maxDigestLength = Integer.MAX_VALUE;
-        if (signingKey != null &&
-                "rsa".equalsIgnoreCase(signingKey.getAlgorithm()) &&
-                expected.equalsIgnoreCase("rsa")) {
-            /*
-             * RSA keys of 512 bits have been shown to be practically
-             * breakable, it does not make much sense to use the strong
-             * hash algorithm for keys whose key size less than 512 bits.
-             * So it is not necessary to caculate the required max digest
-             * length exactly.
-             *
-             * If key size is greater than or equals to 768, there is no max
-             * digest length limitation in currect implementation.
-             *
-             * If key size is greater than or equals to 512, but less than
-             * 768, the digest length should be less than or equal to 32 bytes.
-             *
-             * If key size is less than 512, the  digest length should be
-             * less than or equal to 20 bytes.
-             */
-            int keySize = KeyUtil.getKeySize(signingKey);
-            if (keySize >= 768) {
-                maxDigestLength = HashAlgorithm.SHA512.length;
-            } else if ((keySize >= 512) && (keySize < 768)) {
-                maxDigestLength = HashAlgorithm.SHA256.length;
-            } else if ((keySize > 0) && (keySize < 512)) {
-                maxDigestLength = HashAlgorithm.SHA1.length;
-            }   // Otherwise, cannot determine the key size, prefer the most
-                // perferable hash algorithm.
-        }
-
-        for (SignatureAndHashAlgorithm algorithm : algorithms) {
-            int signValue = algorithm.id & 0xFF;
-            if (expected.equalsIgnoreCase("rsa") &&
-                    signValue == SignatureAlgorithm.RSA.value) {
-                if (algorithm.hash.length <= maxDigestLength) {
-                    return algorithm;
-                }
-            } else if (
-                    (expected.equalsIgnoreCase("dsa") &&
-                        signValue == SignatureAlgorithm.DSA.value) ||
-                    (expected.equalsIgnoreCase("ecdsa") &&
-                        signValue == SignatureAlgorithm.ECDSA.value) ||
-                    (expected.equalsIgnoreCase("ec") &&
-                        signValue == SignatureAlgorithm.ECDSA.value)) {
-                return algorithm;
-            }
-        }
-
-        return null;
-    }
-
-    static enum HashAlgorithm {
-        UNDEFINED("undefined",        "", -1, -1),
-        NONE(          "none",    "NONE",  0, -1),
-        MD5(            "md5",     "MD5",  1, 16),
-        SHA1(          "sha1",   "SHA-1",  2, 20),
-        SHA224(      "sha224", "SHA-224",  3, 28),
-        SHA256(      "sha256", "SHA-256",  4, 32),
-        SHA384(      "sha384", "SHA-384",  5, 48),
-        SHA512(      "sha512", "SHA-512",  6, 64);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final String standardName; // the standard MessageDigest algorithm name
-        final int value;
-        final int length;   // digest length in bytes, -1 means not applicable
-
-        private HashAlgorithm(String name, String standardName,
-                int value, int length) {
-            this.name = name;
-            this.standardName = standardName;
-            this.value = value;
-            this.length = length;
-        }
-
-        static HashAlgorithm valueOf(int value) {
-            HashAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = NONE;
-                    break;
-                case 1:
-                    algorithm = MD5;
-                    break;
-                case 2:
-                    algorithm = SHA1;
-                    break;
-                case 3:
-                    algorithm = SHA224;
-                    break;
-                case 4:
-                    algorithm = SHA256;
-                    break;
-                case 5:
-                    algorithm = SHA384;
-                    break;
-                case 6:
-                    algorithm = SHA512;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static enum SignatureAlgorithm {
-        UNDEFINED("undefined", -1),
-        ANONYMOUS("anonymous",  0),
-        RSA(            "rsa",  1),
-        DSA(            "dsa",  2),
-        ECDSA(        "ecdsa",  3);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final int value;
-
-        private SignatureAlgorithm(String name, int value) {
-            this.name = name;
-            this.value = value;
-        }
-
-        static SignatureAlgorithm valueOf(int value) {
-            SignatureAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = ANONYMOUS;
-                    break;
-                case 1:
-                    algorithm = RSA;
-                    break;
-                case 2:
-                    algorithm = DSA;
-                    break;
-                case 3:
-                    algorithm = ECDSA;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static {
-        supportedMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-        priorityMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-
-        synchronized (supportedMap) {
-            int p = SUPPORTED_ALG_PRIORITY_MAX_NUM;
-            supports(HashAlgorithm.MD5,         SignatureAlgorithm.RSA,
-                    "MD5withRSA",           --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.DSA,
-                    "SHA1withDSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.RSA,
-                    "SHA1withRSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.ECDSA,
-                    "SHA1withECDSA",        --p);
-            supports(HashAlgorithm.SHA224,      SignatureAlgorithm.RSA,
-                    "SHA224withRSA",        --p);
-            supports(HashAlgorithm.SHA224,      SignatureAlgorithm.ECDSA,
-                    "SHA224withECDSA",      --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.RSA,
-                    "SHA256withRSA",        --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.ECDSA,
-                    "SHA256withECDSA",      --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.RSA,
-                    "SHA384withRSA",        --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.ECDSA,
-                    "SHA384withECDSA",      --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.RSA,
-                    "SHA512withRSA",        --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.ECDSA,
-                    "SHA512withECDSA",      --p);
-        }
-    }
-}
-
diff --git a/ojluni/src/main/java/sun/security/ssl/SunJSSE.java b/ojluni/src/main/java/sun/security/ssl/SunJSSE.java
deleted file mode 100755
index 16cb35c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SunJSSE.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.*;
-
-/**
- * The JSSE provider.
- *
- * The RSA implementation has been removed from JSSE, but we still need to
- * register the same algorithms for compatibility. We just point to the RSA
- * implementation in the SunRsaSign provider. This works because all classes
- * are in the bootclasspath and therefore loaded by the same classloader.
- *
- * SunJSSE now supports an experimental FIPS compliant mode when used with an
- * appropriate FIPS certified crypto provider. In FIPS mode, we:
- *  . allow only TLS 1.0 or later
- *  . allow only FIPS approved ciphersuites
- *  . perform all crypto in the FIPS crypto provider
- *
- * It is currently not possible to use both FIPS compliant SunJSSE and
- * standard JSSE at the same time because of the various static data structures
- * we use.
- *
- * However, we do want to allow FIPS mode to be enabled at runtime and without
- * editing the java.security file. That means we need to allow
- * Security.removeProvider("SunJSSE") to work, which creates an instance of
- * this class in non-FIPS mode. That is why we delay the selection of the mode
- * as long as possible. This is until we open an SSL/TLS connection and the
- * data structures need to be initialized or until SunJSSE is initialized in
- * FIPS mode.
- *
- */
-public abstract class SunJSSE extends java.security.Provider {
-
-    private static final long serialVersionUID = 3231825739635378733L;
-
-    private static String info = "Sun JSSE provider" +
-        "(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)";
-
-    private static String fipsInfo =
-        "Sun JSSE provider (FIPS mode, crypto provider ";
-
-    // tri-valued flag:
-    // null  := no final decision made
-    // false := data structures initialized in non-FIPS mode
-    // true  := data structures initialized in FIPS mode
-    private static Boolean fips;
-
-    // the FIPS certificate crypto provider that we use to perform all crypto
-    // operations. null in non-FIPS mode
-    static java.security.Provider cryptoProvider;
-
-    protected static synchronized boolean isFIPS() {
-        if (fips == null) {
-            fips = false;
-        }
-        return fips;
-    }
-
-    // ensure we can use FIPS mode using the specified crypto provider.
-    // enable FIPS mode if not already enabled.
-    private static synchronized void ensureFIPS(java.security.Provider p) {
-        if (fips == null) {
-            fips = true;
-            cryptoProvider = p;
-        } else {
-            if (fips == false) {
-                throw new ProviderException
-                    ("SunJSSE already initialized in non-FIPS mode");
-            }
-            if (cryptoProvider != p) {
-                throw new ProviderException
-                    ("SunJSSE already initialized with FIPS crypto provider "
-                    + cryptoProvider);
-            }
-        }
-    }
-
-    // standard constructor
-    protected SunJSSE() {
-        super("SunJSSE", 1.7d, info);
-        subclassCheck();
-        if (Boolean.TRUE.equals(fips)) {
-            throw new ProviderException
-                ("SunJSSE is already initialized in FIPS mode");
-        }
-        registerAlgorithms(false);
-    }
-
-    // prefered constructor to enable FIPS mode at runtime
-    protected SunJSSE(java.security.Provider cryptoProvider){
-        this(checkNull(cryptoProvider), cryptoProvider.getName());
-    }
-
-    // constructor to enable FIPS mode from java.security file
-    protected SunJSSE(String cryptoProvider){
-        this(null, checkNull(cryptoProvider));
-    }
-
-    private static <T> T checkNull(T t) {
-        if (t == null) {
-            throw new ProviderException("cryptoProvider must not be null");
-        }
-        return t;
-    }
-
-    private SunJSSE(java.security.Provider cryptoProvider,
-            String providerName) {
-        super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
-        subclassCheck();
-        if (cryptoProvider == null) {
-            // Calling Security.getProvider() will cause other providers to be
-            // loaded. That is not good but unavoidable here.
-            cryptoProvider = Security.getProvider(providerName);
-            if (cryptoProvider == null) {
-                throw new ProviderException
-                    ("Crypto provider not installed: " + providerName);
-            }
-        }
-        ensureFIPS(cryptoProvider);
-        registerAlgorithms(true);
-    }
-
-    private void registerAlgorithms(final boolean isfips) {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                doRegister(isfips);
-                return null;
-            }
-        });
-    }
-
-    private void doRegister(boolean isfips) {
-        if (isfips == false) {
-            put("KeyFactory.RSA",
-                "sun.security.rsa.RSAKeyFactory");
-            put("Alg.Alias.KeyFactory.1.2.840.113549.1.1", "RSA");
-            put("Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1", "RSA");
-
-            put("KeyPairGenerator.RSA",
-                "sun.security.rsa.RSAKeyPairGenerator");
-            put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
-            put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
-
-            put("Signature.MD2withRSA",
-                "sun.security.rsa.RSASignature$MD2withRSA");
-            put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
-            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2",
-                "MD2withRSA");
-
-            put("Signature.MD5withRSA",
-                "sun.security.rsa.RSASignature$MD5withRSA");
-            put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
-            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4",
-                "MD5withRSA");
-
-            put("Signature.SHA1withRSA",
-                "sun.security.rsa.RSASignature$SHA1withRSA");
-            put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
-            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5",
-                "SHA1withRSA");
-            put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
-            put("Alg.Alias.Signature.OID.1.3.14.3.2.29", "SHA1withRSA");
-
-        }
-        put("Signature.MD5andSHA1withRSA",
-            "sun.security.ssl.RSASignature");
-
-        put("KeyManagerFactory.SunX509",
-            "sun.security.ssl.KeyManagerFactoryImpl$SunX509");
-        put("KeyManagerFactory.NewSunX509",
-            "sun.security.ssl.KeyManagerFactoryImpl$X509");
-        put("Alg.Alias.KeyManagerFactory.PKIX", "NewSunX509");
-
-        put("TrustManagerFactory.SunX509",
-            "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
-        put("TrustManagerFactory.PKIX",
-            "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory");
-        put("Alg.Alias.TrustManagerFactory.SunPKIX", "PKIX");
-        put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
-        put("Alg.Alias.TrustManagerFactory.X.509", "PKIX");
-
-        put("SSLContext.TLSv1",
-            "sun.security.ssl.SSLContextImpl$TLS10Context");
-        put("Alg.Alias.SSLContext.TLS", "TLSv1");
-        if (isfips == false) {
-            put("Alg.Alias.SSLContext.SSL", "TLSv1");
-            put("Alg.Alias.SSLContext.SSLv3", "TLSv1");
-        }
-
-        put("SSLContext.TLSv1.1",
-            "sun.security.ssl.SSLContextImpl$TLS11Context");
-        put("SSLContext.TLSv1.2",
-            "sun.security.ssl.SSLContextImpl$TLS12Context");
-        put("SSLContext.Default",
-            "sun.security.ssl.SSLContextImpl$DefaultSSLContext");
-
-        /*
-         * KeyStore
-         */
-        put("KeyStore.PKCS12",
-            "sun.security.pkcs12.PKCS12KeyStore");
-    }
-
-    private void subclassCheck() {
-        if (getClass() != com.sun.net.ssl.internal.ssl.Provider.class) {
-            throw new AssertionError("Illegal subclass: " + getClass());
-        }
-    }
-
-    @Override
-    protected final void finalize() throws Throwable {
-        // empty
-        super.finalize();
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java
deleted file mode 100755
index bdf113d..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.net.Socket;
-
-import javax.security.auth.x500.X500Principal;
-
-
-/**
- * An implemention of X509KeyManager backed by a KeyStore.
- *
- * The backing KeyStore is inspected when this object is constructed.
- * All key entries containing a PrivateKey and a non-empty chain of
- * X509Certificate are then copied into an internal store. This means
- * that subsequent modifications of the KeyStore have no effect on the
- * X509KeyManagerImpl object.
- *
- * Note that this class assumes that all keys are protected by the same
- * password.
- *
- * The JSSE handshake code currently calls into this class via
- * chooseClientAlias() and chooseServerAlias() to find the certificates to
- * use. As implemented here, both always return the first alias returned by
- * getClientAliases() and getServerAliases(). In turn, these methods are
- * implemented by calling getAliases(), which performs the actual lookup.
- *
- * Note that this class currently implements no checking of the local
- * certificates. In particular, it is *not* guaranteed that:
- *  . the certificates are within their validity period and not revoked
- *  . the signatures verify
- *  . they form a PKIX compliant chain.
- *  . the certificate extensions allow the certificate to be used for
- *    the desired purpose.
- *
- * Chains that fail any of these criteria will probably be rejected by
- * the remote peer.
- *
- */
-final class SunX509KeyManagerImpl extends X509ExtendedKeyManager {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private static final String[] STRING0 = new String[0];
-
-    /*
-     * The credentials from the KeyStore as
-     * Map: String(alias) -> X509Credentials(credentials)
-     */
-    private Map<String,X509Credentials> credentialsMap;
-
-    /*
-     * Cached server aliases for the case issuers == null.
-     * (in the current JSSE implementation, issuers are always null for
-     * server certs). See chooseServerAlias() for details.
-     *
-     * Map: String(keyType) -> String[](alias)
-     */
-    private Map<String,String[]> serverAliasCache;
-
-    /*
-     * Basic container for credentials implemented as an inner class.
-     */
-    private static class X509Credentials {
-        PrivateKey privateKey;
-        X509Certificate[] certificates;
-        private Set<X500Principal> issuerX500Principals;
-
-        X509Credentials(PrivateKey privateKey, X509Certificate[] certificates) {
-            // assert privateKey and certificates != null
-            this.privateKey = privateKey;
-            this.certificates = certificates;
-        }
-
-        synchronized Set<X500Principal> getIssuerX500Principals() {
-            // lazy initialization
-            if (issuerX500Principals == null) {
-                issuerX500Principals = new HashSet<X500Principal>();
-                for (int i = 0; i < certificates.length; i++) {
-                    issuerX500Principals.add(
-                                certificates[i].getIssuerX500Principal());
-                }
-            }
-            return issuerX500Principals;
-        }
-    }
-
-    SunX509KeyManagerImpl(KeyStore ks, char[] password) throws KeyStoreException,
-            NoSuchAlgorithmException, UnrecoverableKeyException {
-
-        credentialsMap = new HashMap<String,X509Credentials>();
-        serverAliasCache = new HashMap<String,String[]>();
-        if (ks == null) {
-            return;
-        }
-
-        for (Enumeration<String> aliases = ks.aliases();
-                                        aliases.hasMoreElements(); ) {
-            String alias = aliases.nextElement();
-            if (!ks.isKeyEntry(alias)) {
-                continue;
-            }
-            Key key = ks.getKey(alias, password);
-            if (key instanceof PrivateKey == false) {
-                continue;
-            }
-            Certificate[] certs = ks.getCertificateChain(alias);
-            if ((certs == null) || (certs.length == 0) ||
-                    !(certs[0] instanceof X509Certificate)) {
-                continue;
-            }
-            if (!(certs instanceof X509Certificate[])) {
-                Certificate[] tmp = new X509Certificate[certs.length];
-                System.arraycopy(certs, 0, tmp, 0, certs.length);
-                certs = tmp;
-            }
-
-            X509Credentials cred = new X509Credentials((PrivateKey)key,
-                (X509Certificate[])certs);
-            credentialsMap.put(alias, cred);
-            if (debug != null && Debug.isOn("keymanager")) {
-                System.out.println("***");
-                System.out.println("found key for : " + alias);
-                for (int i = 0; i < certs.length; i++) {
-                    System.out.println("chain [" + i + "] = "
-                    + certs[i]);
-                }
-                System.out.println("***");
-            }
-        }
-    }
-
-    /*
-     * Returns the certificate chain associated with the given alias.
-     *
-     * @return the certificate chain (ordered with the user's certificate first
-     * and the root certificate authority last)
-     */
-    public X509Certificate[] getCertificateChain(String alias) {
-        if (alias == null) {
-            return null;
-        }
-        X509Credentials cred = credentialsMap.get(alias);
-        if (cred == null) {
-            return null;
-        } else {
-            return cred.certificates.clone();
-        }
-    }
-
-    /*
-     * Returns the key associated with the given alias
-     */
-    public PrivateKey getPrivateKey(String alias) {
-        if (alias == null) {
-            return null;
-        }
-        X509Credentials cred = credentialsMap.get(alias);
-        if (cred == null) {
-            return null;
-        } else {
-            return cred.privateKey;
-        }
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        /*
-         * We currently don't do anything with socket, but
-         * someday we might.  It might be a useful hint for
-         * selecting one of the aliases we get back from
-         * getClientAliases().
-         */
-
-        if (keyTypes == null) {
-            return null;
-        }
-
-        for (int i = 0; i < keyTypes.length; i++) {
-            String[] aliases = getClientAliases(keyTypes[i], issuers);
-            if ((aliases != null) && (aliases.length > 0)) {
-                return aliases[0];
-            }
-        }
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the client side of an
-     * <code>SSLEngine</code> connection given the public key type
-     * and the list of certificate issuer authorities recognized by
-     * the peer (if any).
-     *
-     * @since 1.5
-     */
-    public String chooseEngineClientAlias(String[] keyType,
-            Principal[] issuers, SSLEngine engine) {
-        /*
-         * If we ever start using socket as a selection criteria,
-         * we'll need to adjust this.
-         */
-        return chooseClientAlias(keyType, issuers, null);
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String chooseServerAlias(String keyType,
-            Principal[] issuers, Socket socket) {
-        /*
-         * We currently don't do anything with socket, but
-         * someday we might.  It might be a useful hint for
-         * selecting one of the aliases we get back from
-         * getServerAliases().
-         */
-        if (keyType == null) {
-            return null;
-        }
-
-        String[] aliases;
-
-        if (issuers == null || issuers.length == 0) {
-            aliases = serverAliasCache.get(keyType);
-            if (aliases == null) {
-                aliases = getServerAliases(keyType, issuers);
-                // Cache the result (positive and negative lookups)
-                if (aliases == null) {
-                    aliases = STRING0;
-                }
-                serverAliasCache.put(keyType, aliases);
-            }
-        } else {
-            aliases = getServerAliases(keyType, issuers);
-        }
-        if ((aliases != null) && (aliases.length > 0)) {
-            return aliases[0];
-        }
-        return null;
-    }
-
-    /*
-     * Choose an alias to authenticate the server side of an
-     * <code>SSLEngine</code> connection given the public key type
-     * and the list of certificate issuer authorities recognized by
-     * the peer (if any).
-     *
-     * @since 1.5
-     */
-    public String chooseEngineServerAlias(String keyType,
-            Principal[] issuers, SSLEngine engine) {
-        /*
-         * If we ever start using socket as a selection criteria,
-         * we'll need to adjust this.
-         */
-        return chooseServerAlias(keyType, issuers, null);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the client side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the server side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     */
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers);
-    }
-
-    /*
-     * Get the matching aliases for authenticating the either side of a secure
-     * socket given the public key type and the list of
-     * certificate issuer authorities recognized by the peer (if any).
-     *
-     * Issuers comes to us in the form of X500Principal[].
-     */
-    private String[] getAliases(String keyType, Principal[] issuers) {
-        if (keyType == null) {
-            return null;
-        }
-        if (issuers == null) {
-            issuers = new X500Principal[0];
-        }
-        if (issuers instanceof X500Principal[] == false) {
-            // normally, this will never happen but try to recover if it does
-            issuers = convertPrincipals(issuers);
-        }
-        String sigType;
-        if (keyType.contains("_")) {
-            int k = keyType.indexOf("_");
-            sigType = keyType.substring(k + 1);
-            keyType = keyType.substring(0, k);
-        } else {
-            sigType = null;
-        }
-
-        X500Principal[] x500Issuers = (X500Principal[])issuers;
-        // the algorithm below does not produce duplicates, so avoid Set
-        List<String> aliases = new ArrayList<>();
-
-        for (Map.Entry<String,X509Credentials> entry :
-                                                credentialsMap.entrySet()) {
-
-            String alias = entry.getKey();
-            X509Credentials credentials = entry.getValue();
-            X509Certificate[] certs = credentials.certificates;
-
-            if (!keyType.equals(certs[0].getPublicKey().getAlgorithm())) {
-                continue;
-            }
-            if (sigType != null) {
-                if (certs.length > 1) {
-                    // if possible, check the public key in the issuer cert
-                    if (!sigType.equals(certs[1].getPublicKey().getAlgorithm())) {
-                        continue;
-                    }
-                } else {
-                    // Check the signature algorithm of the certificate itself.
-                    // Look for the "withRSA" in "SHA1withRSA", etc.
-                    String sigAlgName =
-                            certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH);
-                    String pattern = "WITH" + sigType.toUpperCase(Locale.ENGLISH);
-                    if (sigAlgName.contains(pattern) == false) {
-                        continue;
-                    }
-                }
-            }
-
-            if (issuers.length == 0) {
-                // no issuer specified, match all
-                aliases.add(alias);
-                if (debug != null && Debug.isOn("keymanager")) {
-                    System.out.println("matching alias: " + alias);
-                }
-            } else {
-                Set<X500Principal> certIssuers =
-                                        credentials.getIssuerX500Principals();
-                for (int i = 0; i < x500Issuers.length; i++) {
-                    if (certIssuers.contains(issuers[i])) {
-                        aliases.add(alias);
-                        if (debug != null && Debug.isOn("keymanager")) {
-                            System.out.println("matching alias: " + alias);
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-
-        String[] aliasStrings = aliases.toArray(STRING0);
-        return ((aliasStrings.length == 0) ? null : aliasStrings);
-    }
-
-    /*
-     * Convert an array of Principals to an array of X500Principals, if
-     * possible. Principals that cannot be converted are ignored.
-     */
-    private static X500Principal[] convertPrincipals(Principal[] principals) {
-        List<X500Principal> list = new ArrayList<>(principals.length);
-        for (int i = 0; i < principals.length; i++) {
-            Principal p = principals[i];
-            if (p instanceof X500Principal) {
-                list.add((X500Principal)p);
-            } else {
-                try {
-                    list.add(new X500Principal(p.getName()));
-                } catch (IllegalArgumentException e) {
-                    // ignore
-                }
-            }
-        }
-        return list.toArray(new X500Principal[list.size()]);
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java
deleted file mode 100755
index ee2142c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.io.*;
-import java.math.*;
-import java.security.*;
-import java.security.cert.*;
-import javax.net.ssl.*;
-import java.security.spec.AlgorithmParameterSpec;
-
-import sun.security.validator.Validator;
-
-abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-    private X509TrustManager trustManager = null;
-    private boolean isInitialized = false;
-
-    TrustManagerFactoryImpl() {
-        // empty
-    }
-
-    protected void engineInit(KeyStore ks) throws KeyStoreException {
-        if (ks == null) {
-            try {
-                ks = getCacertsKeyStore("trustmanager");
-            } catch (SecurityException se) {
-                // eat security exceptions but report other throwables
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + se);
-                }
-            } catch (Error err) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + err);
-                }
-                throw err;
-            } catch (RuntimeException re) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + re);
-                }
-                throw re;
-            } catch (Exception e) {
-                if (debug != null && Debug.isOn("trustmanager")) {
-                    System.out.println(
-                        "SunX509: skip default keystore: " + e);
-                }
-                throw new KeyStoreException(
-                    "problem accessing trust store" + e);
-            }
-        }
-        trustManager = getInstance(ks);
-        isInitialized = true;
-    }
-
-    abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
-
-    abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
-            throws InvalidAlgorithmParameterException;
-
-    protected void engineInit(ManagerFactoryParameters spec) throws
-            InvalidAlgorithmParameterException {
-        trustManager = getInstance(spec);
-        isInitialized = true;
-    }
-
-    /**
-     * Returns one trust manager for each type of trust material.
-     */
-    protected TrustManager[] engineGetTrustManagers() {
-        if (!isInitialized) {
-            throw new IllegalStateException(
-                        "TrustManagerFactoryImpl is not initialized");
-        }
-        return new TrustManager[] { trustManager };
-    }
-
-    /*
-     * Try to get an InputStream based on the file we pass in.
-     */
-    private static FileInputStream getFileInputStream(final File file)
-            throws Exception {
-        return AccessController.doPrivileged(
-                new PrivilegedExceptionAction<FileInputStream>() {
-                    public FileInputStream run() throws Exception {
-                        try {
-                            if (file.exists()) {
-                                return new FileInputStream(file);
-                            } else {
-                                return null;
-                            }
-                        } catch (FileNotFoundException e) {
-                            // couldn't find it, oh well.
-                            return null;
-                        }
-                    }
-                });
-    }
-
-    /**
-     * Returns the keystore with the configured CA certificates.
-     */
-    static KeyStore getCacertsKeyStore(String dbgname) throws Exception
-    {
-        String storeFileName = null;
-        File storeFile = null;
-        FileInputStream fis = null;
-        String defaultTrustStoreType;
-        String defaultTrustStoreProvider;
-        final HashMap<String,String> props = new HashMap<>();
-        final String sep = File.separator;
-        KeyStore ks = null;
-
-        AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
-            public Void run() throws Exception {
-                props.put("trustStore", System.getProperty(
-                                "javax.net.ssl.trustStore"));
-                props.put("javaHome", System.getProperty(
-                                        "java.home"));
-                props.put("trustStoreType", System.getProperty(
-                                "javax.net.ssl.trustStoreType",
-                                KeyStore.getDefaultType()));
-                props.put("trustStoreProvider", System.getProperty(
-                                "javax.net.ssl.trustStoreProvider", ""));
-                props.put("trustStorePasswd", System.getProperty(
-                                "javax.net.ssl.trustStorePassword", ""));
-                return null;
-            }
-        });
-
-        /*
-         * Try:
-         *      javax.net.ssl.trustStore  (if this variable exists, stop)
-         *      jssecacerts
-         *      cacerts
-         *
-         * If none exists, we use an empty keystore.
-         */
-
-        storeFileName = props.get("trustStore");
-        if (!"NONE".equals(storeFileName)) {
-            if (storeFileName != null) {
-                storeFile = new File(storeFileName);
-                fis = getFileInputStream(storeFile);
-            } else {
-                String javaHome = props.get("javaHome");
-                storeFile = new File(javaHome + sep + "lib" + sep
-                                                + "security" + sep +
-                                                "jssecacerts");
-                if ((fis = getFileInputStream(storeFile)) == null) {
-                    storeFile = new File(javaHome + sep + "lib" + sep
-                                                + "security" + sep +
-                                                "cacerts");
-                    fis = getFileInputStream(storeFile);
-                }
-            }
-
-            if (fis != null) {
-                storeFileName = storeFile.getPath();
-            } else {
-                storeFileName = "No File Available, using empty keystore.";
-            }
-        }
-
-        defaultTrustStoreType = props.get("trustStoreType");
-        defaultTrustStoreProvider = props.get("trustStoreProvider");
-        if (debug != null && Debug.isOn(dbgname)) {
-            System.out.println("trustStore is: " + storeFileName);
-            System.out.println("trustStore type is : " +
-                                defaultTrustStoreType);
-            System.out.println("trustStore provider is : " +
-                                defaultTrustStoreProvider);
-        }
-
-        /*
-         * Try to initialize trust store.
-         */
-        if (defaultTrustStoreType.length() != 0) {
-            if (debug != null && Debug.isOn(dbgname)) {
-                System.out.println("init truststore");
-            }
-            if (defaultTrustStoreProvider.length() == 0) {
-                ks = KeyStore.getInstance(defaultTrustStoreType);
-            } else {
-                ks = KeyStore.getInstance(defaultTrustStoreType,
-                                        defaultTrustStoreProvider);
-            }
-            char[] passwd = null;
-            String defaultTrustStorePassword = props.get("trustStorePasswd");
-            if (defaultTrustStorePassword.length() != 0)
-                passwd = defaultTrustStorePassword.toCharArray();
-
-            // if trustStore is NONE, fis will be null
-            ks.load(fis, passwd);
-
-            // Zero out the temporary password storage
-            if (passwd != null) {
-                for (int i = 0; i < passwd.length; i++) {
-                    passwd[i] = (char)0;
-                }
-            }
-        }
-
-        if (fis != null) {
-            fis.close();
-        }
-
-        return ks;
-    }
-
-    public static final class SimpleFactory extends TrustManagerFactoryImpl {
-        X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
-            return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
-        }
-        X509TrustManager getInstance(ManagerFactoryParameters spec)
-                throws InvalidAlgorithmParameterException {
-            throw new InvalidAlgorithmParameterException
-                ("SunX509 TrustManagerFactory does not use "
-                + "ManagerFactoryParameters");
-        }
-   }
-
-    public static final class PKIXFactory extends TrustManagerFactoryImpl {
-        X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
-            return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
-        }
-        X509TrustManager getInstance(ManagerFactoryParameters spec)
-                throws InvalidAlgorithmParameterException {
-            if (spec instanceof CertPathTrustManagerParameters == false) {
-                throw new InvalidAlgorithmParameterException
-                    ("Parameters must be CertPathTrustManagerParameters");
-            }
-            CertPathParameters params =
-                ((CertPathTrustManagerParameters)spec).getParameters();
-            if (params instanceof PKIXBuilderParameters == false) {
-                throw new InvalidAlgorithmParameterException
-                    ("Encapsulated parameters must be PKIXBuilderParameters");
-            }
-            PKIXBuilderParameters pkixParams = (PKIXBuilderParameters)params;
-            return new X509TrustManagerImpl(Validator.TYPE_PKIX, pkixParams);
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java
deleted file mode 100755
index 426f5bf..0000000
--- a/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java
+++ /dev/null
@@ -1,741 +0,0 @@
-/*
- * Copyright (c) 2004, 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.security.ssl;
-
-import java.lang.ref.*;
-import java.util.*;
-import static java.util.Locale.ENGLISH;
-import java.util.concurrent.atomic.AtomicLong;
-import java.net.Socket;
-
-import java.security.*;
-import java.security.KeyStore.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-
-/**
- * The new X509 key manager implementation. The main differences to the
- * old SunX509 key manager are:
- *  . it is based around the KeyStore.Builder API. This allows it to use
- *    other forms of KeyStore protection or password input (e.g. a
- *    CallbackHandler) or to have keys within one KeyStore protected by
- *    different keys.
- *  . it can use multiple KeyStores at the same time.
- *  . it is explicitly designed to accomodate KeyStores that change over
- *    the lifetime of the process.
- *  . it makes an effort to choose the key that matches best, i.e. one that
- *    is not expired and has the appropriate certificate extensions.
- *
- * Note that this code is not explicitly performance optimzied yet.
- *
- * @author  Andreas Sterbenz
- */
-final class X509KeyManagerImpl extends X509ExtendedKeyManager
-        implements X509KeyManager {
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    private final static boolean useDebug =
-                            (debug != null) && Debug.isOn("keymanager");
-
-    // for unit testing only, set via privileged reflection
-    private static Date verificationDate;
-
-    // list of the builders
-    private final List<Builder> builders;
-
-    // counter to generate unique ids for the aliases
-    private final AtomicLong uidCounter;
-
-    // cached entries
-    private final Map<String,Reference<PrivateKeyEntry>> entryCacheMap;
-
-    X509KeyManagerImpl(Builder builder) {
-        this(Collections.singletonList(builder));
-    }
-
-    X509KeyManagerImpl(List<Builder> builders) {
-        this.builders = builders;
-        uidCounter = new AtomicLong();
-        entryCacheMap = Collections.synchronizedMap
-                        (new SizedMap<String,Reference<PrivateKeyEntry>>());
-    }
-
-    // LinkedHashMap with a max size of 10
-    // see LinkedHashMap JavaDocs
-    private static class SizedMap<K,V> extends LinkedHashMap<K,V> {
-        @Override protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
-            return size() > 10;
-        }
-    }
-
-    //
-    // public methods
-    //
-
-    public X509Certificate[] getCertificateChain(String alias) {
-        PrivateKeyEntry entry = getEntry(alias);
-        return entry == null ? null :
-                (X509Certificate[])entry.getCertificateChain();
-    }
-
-    public PrivateKey getPrivateKey(String alias) {
-        PrivateKeyEntry entry = getEntry(alias);
-        return entry == null ? null : entry.getPrivateKey();
-    }
-
-    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
-            Socket socket) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
-                        getAlgorithmConstraints(socket));
-    }
-
-    public String chooseEngineClientAlias(String[] keyTypes,
-            Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
-                        getAlgorithmConstraints(engine));
-    }
-
-    public String chooseServerAlias(String keyType,
-            Principal[] issuers, Socket socket) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
-                        getAlgorithmConstraints(socket));
-    }
-
-    public String chooseEngineServerAlias(String keyType,
-            Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
-                        getAlgorithmConstraints(engine));
-    }
-
-    public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.CLIENT, null);
-    }
-
-    public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.SERVER, null);
-    }
-
-    //
-    // implementation private methods
-    //
-
-    // Gets algorithm constraints of the socket.
-    private AlgorithmConstraints getAlgorithmConstraints(Socket socket) {
-        if (socket != null && socket.isConnected() &&
-                                        socket instanceof SSLSocket) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-
-            if (session != null) {
-                ProtocolVersion protocolVersion =
-                    ProtocolVersion.valueOf(session.getProtocol());
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    String[] peerSupportedSignAlgs = null;
-
-                    if (session instanceof ExtendedSSLSession) {
-                        ExtendedSSLSession extSession =
-                            (ExtendedSSLSession)session;
-                        peerSupportedSignAlgs =
-                            extSession.getPeerSupportedSignatureAlgorithms();
-                    }
-
-                    return new SSLAlgorithmConstraints(
-                        sslSocket, peerSupportedSignAlgs, true);
-                }
-            }
-
-            return new SSLAlgorithmConstraints(sslSocket, true);
-        }
-
-        return new SSLAlgorithmConstraints((SSLSocket)null, true);
-    }
-
-    // Gets algorithm constraints of the engine.
-    private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session != null) {
-                ProtocolVersion protocolVersion =
-                    ProtocolVersion.valueOf(session.getProtocol());
-                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                    String[] peerSupportedSignAlgs = null;
-
-                    if (session instanceof ExtendedSSLSession) {
-                        ExtendedSSLSession extSession =
-                            (ExtendedSSLSession)session;
-                        peerSupportedSignAlgs =
-                            extSession.getPeerSupportedSignatureAlgorithms();
-                    }
-
-                    return new SSLAlgorithmConstraints(
-                        engine, peerSupportedSignAlgs, true);
-                }
-            }
-        }
-
-        return new SSLAlgorithmConstraints(engine, true);
-    }
-
-    // we construct the alias we return to JSSE as seen in the code below
-    // a unique id is included to allow us to reliably cache entries
-    // between the calls to getCertificateChain() and getPrivateKey()
-    // even if tokens are inserted or removed
-    private String makeAlias(EntryStatus entry) {
-        return uidCounter.incrementAndGet() + "." + entry.builderIndex + "."
-                + entry.alias;
-    }
-
-    private PrivateKeyEntry getEntry(String alias) {
-        // if the alias is null, return immediately
-        if (alias == null) {
-            return null;
-        }
-
-        // try to get the entry from cache
-        Reference<PrivateKeyEntry> ref = entryCacheMap.get(alias);
-        PrivateKeyEntry entry = (ref != null) ? ref.get() : null;
-        if (entry != null) {
-            return entry;
-        }
-
-        // parse the alias
-        int firstDot = alias.indexOf('.');
-        int secondDot = alias.indexOf('.', firstDot + 1);
-        if ((firstDot == -1) || (secondDot == firstDot)) {
-            // invalid alias
-            return null;
-        }
-        try {
-            int builderIndex = Integer.parseInt
-                                (alias.substring(firstDot + 1, secondDot));
-            String keyStoreAlias = alias.substring(secondDot + 1);
-            Builder builder = builders.get(builderIndex);
-            KeyStore ks = builder.getKeyStore();
-            Entry newEntry = ks.getEntry
-                    (keyStoreAlias, builder.getProtectionParameter(alias));
-            if (newEntry instanceof PrivateKeyEntry == false) {
-                // unexpected type of entry
-                return null;
-            }
-            entry = (PrivateKeyEntry)newEntry;
-            entryCacheMap.put(alias, new SoftReference(entry));
-            return entry;
-        } catch (Exception e) {
-            // ignore
-            return null;
-        }
-    }
-
-    // Class to help verify that the public key algorithm (and optionally
-    // the signature algorithm) of a certificate matches what we need.
-    private static class KeyType {
-
-        final String keyAlgorithm;
-
-        // In TLS 1.2, the signature algorithm  has been obsoleted by the
-        // supported_signature_algorithms, and the certificate type no longer
-        // restricts the algorithm used to sign the certificate.
-        // However, because we don't support certificate type checking other
-        // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
-        // protocol version here.
-        final String sigKeyAlgorithm;
-
-        KeyType(String algorithm) {
-            int k = algorithm.indexOf("_");
-            if (k == -1) {
-                keyAlgorithm = algorithm;
-                sigKeyAlgorithm = null;
-            } else {
-                keyAlgorithm = algorithm.substring(0, k);
-                sigKeyAlgorithm = algorithm.substring(k + 1);
-            }
-        }
-
-        boolean matches(Certificate[] chain) {
-            if (!chain[0].getPublicKey().getAlgorithm().equals(keyAlgorithm)) {
-                return false;
-            }
-            if (sigKeyAlgorithm == null) {
-                return true;
-            }
-            if (chain.length > 1) {
-                // if possible, check the public key in the issuer cert
-                return sigKeyAlgorithm.equals(
-                        chain[1].getPublicKey().getAlgorithm());
-            } else {
-                // Check the signature algorithm of the certificate itself.
-                // Look for the "withRSA" in "SHA1withRSA", etc.
-                X509Certificate issuer = (X509Certificate)chain[0];
-                String sigAlgName = issuer.getSigAlgName().toUpperCase(ENGLISH);
-                String pattern = "WITH" + sigKeyAlgorithm.toUpperCase(ENGLISH);
-                return sigAlgName.contains(pattern);
-            }
-        }
-    }
-
-    private static List<KeyType> getKeyTypes(String ... keyTypes) {
-        if ((keyTypes == null) ||
-                (keyTypes.length == 0) || (keyTypes[0] == null)) {
-            return null;
-        }
-        List<KeyType> list = new ArrayList<>(keyTypes.length);
-        for (String keyType : keyTypes) {
-            list.add(new KeyType(keyType));
-        }
-        return list;
-    }
-
-    /*
-     * Return the best alias that fits the given parameters.
-     * The algorithm we use is:
-     *   . scan through all the aliases in all builders in order
-     *   . as soon as we find a perfect match, return
-     *     (i.e. a match with a cert that has appropriate key usage
-     *      and is not expired).
-     *   . if we do not find a perfect match, keep looping and remember
-     *     the imperfect matches
-     *   . at the end, sort the imperfect matches. we prefer expired certs
-     *     with appropriate key usage to certs with the wrong key usage.
-     *     return the first one of them.
-     */
-    private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
-            CheckType checkType, AlgorithmConstraints constraints) {
-        if (keyTypeList == null || keyTypeList.size() == 0) {
-            return null;
-        }
-
-        Set<Principal> issuerSet = getIssuerSet(issuers);
-        List<EntryStatus> allResults = null;
-        for (int i = 0, n = builders.size(); i < n; i++) {
-            try {
-                List<EntryStatus> results = getAliases(i, keyTypeList,
-                                    issuerSet, false, checkType, constraints);
-                if (results != null) {
-                    // the results will either be a single perfect match
-                    // or 1 or more imperfect matches
-                    // if it's a perfect match, return immediately
-                    EntryStatus status = results.get(0);
-                    if (status.checkResult == CheckResult.OK) {
-                        if (useDebug) {
-                            debug.println("KeyMgr: choosing key: " + status);
-                        }
-                        return makeAlias(status);
-                    }
-                    if (allResults == null) {
-                        allResults = new ArrayList<EntryStatus>();
-                    }
-                    allResults.addAll(results);
-                }
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        if (allResults == null) {
-            if (useDebug) {
-                debug.println("KeyMgr: no matching key found");
-            }
-            return null;
-        }
-        Collections.sort(allResults);
-        if (useDebug) {
-            debug.println("KeyMgr: no good matching key found, "
-                        + "returning best match out of:");
-            debug.println(allResults.toString());
-        }
-        return makeAlias(allResults.get(0));
-    }
-
-    /*
-     * Return all aliases that (approximately) fit the parameters.
-     * These are perfect matches plus imperfect matches (expired certificates
-     * and certificates with the wrong extensions).
-     * The perfect matches will be first in the array.
-     */
-    public String[] getAliases(String keyType, Principal[] issuers,
-            CheckType checkType, AlgorithmConstraints constraints) {
-        if (keyType == null) {
-            return null;
-        }
-
-        Set<Principal> issuerSet = getIssuerSet(issuers);
-        List<KeyType> keyTypeList = getKeyTypes(keyType);
-        List<EntryStatus> allResults = null;
-        for (int i = 0, n = builders.size(); i < n; i++) {
-            try {
-                List<EntryStatus> results = getAliases(i, keyTypeList,
-                                    issuerSet, true, checkType, constraints);
-                if (results != null) {
-                    if (allResults == null) {
-                        allResults = new ArrayList<EntryStatus>();
-                    }
-                    allResults.addAll(results);
-                }
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        if (allResults == null || allResults.size() == 0) {
-            if (useDebug) {
-                debug.println("KeyMgr: no matching alias found");
-            }
-            return null;
-        }
-        Collections.sort(allResults);
-        if (useDebug) {
-            debug.println("KeyMgr: getting aliases: " + allResults);
-        }
-        return toAliases(allResults);
-    }
-
-    // turn candidate entries into unique aliases we can return to JSSE
-    private String[] toAliases(List<EntryStatus> results) {
-        String[] s = new String[results.size()];
-        int i = 0;
-        for (EntryStatus result : results) {
-            s[i++] = makeAlias(result);
-        }
-        return s;
-    }
-
-    // make a Set out of the array
-    private Set<Principal> getIssuerSet(Principal[] issuers) {
-        if ((issuers != null) && (issuers.length != 0)) {
-            return new HashSet<>(Arrays.asList(issuers));
-        } else {
-            return null;
-        }
-    }
-
-    // a candidate match
-    // identifies the entry by builder and alias
-    // and includes the result of the certificate check
-    private static class EntryStatus implements Comparable<EntryStatus> {
-
-        final int builderIndex;
-        final int keyIndex;
-        final String alias;
-        final CheckResult checkResult;
-
-        EntryStatus(int builderIndex, int keyIndex, String alias,
-                Certificate[] chain, CheckResult checkResult) {
-            this.builderIndex = builderIndex;
-            this.keyIndex = keyIndex;
-            this.alias = alias;
-            this.checkResult = checkResult;
-        }
-
-        public int compareTo(EntryStatus other) {
-            int result = this.checkResult.compareTo(other.checkResult);
-            return (result == 0) ? (this.keyIndex - other.keyIndex) : result;
-        }
-
-        public String toString() {
-            String s = alias + " (verified: " + checkResult + ")";
-            if (builderIndex == 0) {
-                return s;
-            } else {
-                return "Builder #" + builderIndex + ", alias: " + s;
-            }
-        }
-    }
-
-    // enum for the type of certificate check we want to perform
-    // (client or server)
-    // also includes the check code itself
-    private static enum CheckType {
-
-        // enum constant for "no check" (currently not used)
-        NONE(Collections.<String>emptySet()),
-
-        // enum constant for "tls client" check
-        // valid EKU for TLS client: any, tls_client
-        CLIENT(new HashSet<String>(Arrays.asList(new String[] {
-            "2.5.29.37.0", "1.3.6.1.5.5.7.3.2" }))),
-
-        // enum constant for "tls server" check
-        // valid EKU for TLS server: any, tls_server, ns_sgc, ms_sgc
-        SERVER(new HashSet<String>(Arrays.asList(new String[] {
-            "2.5.29.37.0", "1.3.6.1.5.5.7.3.1", "2.16.840.1.113730.4.1",
-            "1.3.6.1.4.1.311.10.3.3" })));
-
-        // set of valid EKU values for this type
-        final Set<String> validEku;
-
-        CheckType(Set<String> validEku) {
-            this.validEku = validEku;
-        }
-
-        private static boolean getBit(boolean[] keyUsage, int bit) {
-            return (bit < keyUsage.length) && keyUsage[bit];
-        }
-
-        // check if this certificate is appropriate for this type of use
-        // first check extensions, if they match, check expiration
-        // note: we may want to move this code into the sun.security.validator
-        // package
-        CheckResult check(X509Certificate cert, Date date) {
-            if (this == NONE) {
-                return CheckResult.OK;
-            }
-
-            // check extensions
-            try {
-                // check extended key usage
-                List<String> certEku = cert.getExtendedKeyUsage();
-                if ((certEku != null) &&
-                        Collections.disjoint(validEku, certEku)) {
-                    // if extension present and it does not contain any of
-                    // the valid EKU OIDs, return extension_mismatch
-                    return CheckResult.EXTENSION_MISMATCH;
-                }
-
-                // check key usage
-                boolean[] ku = cert.getKeyUsage();
-                if (ku != null) {
-                    String algorithm = cert.getPublicKey().getAlgorithm();
-                    boolean kuSignature = getBit(ku, 0);
-                    if (algorithm.equals("RSA")) {
-                        // require either signature bit
-                        // or if server also allow key encipherment bit
-                        if (kuSignature == false) {
-                            if ((this == CLIENT) || (getBit(ku, 2) == false)) {
-                                return CheckResult.EXTENSION_MISMATCH;
-                            }
-                        }
-                    } else if (algorithm.equals("DSA")) {
-                        // require signature bit
-                        if (kuSignature == false) {
-                            return CheckResult.EXTENSION_MISMATCH;
-                        }
-                    } else if (algorithm.equals("DH")) {
-                        // require keyagreement bit
-                        if (getBit(ku, 4) == false) {
-                            return CheckResult.EXTENSION_MISMATCH;
-                        }
-                    } else if (algorithm.equals("EC")) {
-                        // require signature bit
-                        if (kuSignature == false) {
-                            return CheckResult.EXTENSION_MISMATCH;
-                        }
-                        // For servers, also require key agreement.
-                        // This is not totally accurate as the keyAgreement bit
-                        // is only necessary for static ECDH key exchange and
-                        // not ephemeral ECDH. We leave it in for now until
-                        // there are signs that this check causes problems
-                        // for real world EC certificates.
-                        if ((this == SERVER) && (getBit(ku, 4) == false)) {
-                            return CheckResult.EXTENSION_MISMATCH;
-                        }
-                    }
-                }
-            } catch (CertificateException e) {
-                // extensions unparseable, return failure
-                return CheckResult.EXTENSION_MISMATCH;
-            }
-
-            try {
-                cert.checkValidity(date);
-                return CheckResult.OK;
-            } catch (CertificateException e) {
-                return CheckResult.EXPIRED;
-            }
-        }
-    }
-
-    // enum for the result of the extension check
-    // NOTE: the order of the constants is important as they are used
-    // for sorting, i.e. OK is best, followed by EXPIRED and EXTENSION_MISMATCH
-    private static enum CheckResult {
-        OK,                     // ok or not checked
-        EXPIRED,                // extensions valid but cert expired
-        EXTENSION_MISMATCH,     // extensions invalid (expiration not checked)
-    }
-
-    /*
-     * Return a List of all candidate matches in the specified builder
-     * that fit the parameters.
-     * We exclude entries in the KeyStore if they are not:
-     *  . private key entries
-     *  . the certificates are not X509 certificates
-     *  . the algorithm of the key in the EE cert doesn't match one of keyTypes
-     *  . none of the certs is issued by a Principal in issuerSet
-     * Using those entries would not be possible or they would almost
-     * certainly be rejected by the peer.
-     *
-     * In addition to those checks, we also check the extensions in the EE
-     * cert and its expiration. Even if there is a mismatch, we include
-     * such certificates because they technically work and might be accepted
-     * by the peer. This leads to more graceful failure and better error
-     * messages if the cert expires from one day to the next.
-     *
-     * The return values are:
-     *   . null, if there are no matching entries at all
-     *   . if 'findAll' is 'false' and there is a perfect match, a List
-     *     with a single element (early return)
-     *   . if 'findAll' is 'false' and there is NO perfect match, a List
-     *     with all the imperfect matches (expired, wrong extensions)
-     *   . if 'findAll' is 'true', a List with all perfect and imperfect
-     *     matches
-     */
-    private List<EntryStatus> getAliases(int builderIndex,
-            List<KeyType> keyTypes, Set<Principal> issuerSet,
-            boolean findAll, CheckType checkType,
-            AlgorithmConstraints constraints) throws Exception {
-        Builder builder = builders.get(builderIndex);
-        KeyStore ks = builder.getKeyStore();
-        List<EntryStatus> results = null;
-        Date date = verificationDate;
-        boolean preferred = false;
-        for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
-            String alias = e.nextElement();
-            // check if it is a key entry (private key or secret key)
-            if (ks.isKeyEntry(alias) == false) {
-                continue;
-            }
-
-            Certificate[] chain = ks.getCertificateChain(alias);
-            if ((chain == null) || (chain.length == 0)) {
-                // must be secret key entry, ignore
-                continue;
-            }
-
-            boolean incompatible = false;
-            for (Certificate cert : chain) {
-                if (cert instanceof X509Certificate == false) {
-                    // not an X509Certificate, ignore this alias
-                    incompatible = true;
-                    break;
-                }
-            }
-            if (incompatible) {
-                continue;
-            }
-
-            // check keytype
-            int keyIndex = -1;
-            int j = 0;
-            for (KeyType keyType : keyTypes) {
-                if (keyType.matches(chain)) {
-                    keyIndex = j;
-                    break;
-                }
-                j++;
-            }
-            if (keyIndex == -1) {
-                if (useDebug) {
-                    debug.println("Ignoring alias " + alias
-                                + ": key algorithm does not match");
-                }
-                continue;
-            }
-            // check issuers
-            if (issuerSet != null) {
-                boolean found = false;
-                for (Certificate cert : chain) {
-                    X509Certificate xcert = (X509Certificate)cert;
-                    if (issuerSet.contains(xcert.getIssuerX500Principal())) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (found == false) {
-                    if (useDebug) {
-                        debug.println("Ignoring alias " + alias
-                                    + ": issuers do not match");
-                    }
-                    continue;
-                }
-            }
-
-            // check the algorithm constraints
-            if (constraints != null &&
-                    !conformsToAlgorithmConstraints(constraints, chain)) {
-
-                if (useDebug) {
-                    debug.println("Ignoring alias " + alias +
-                            ": certificate list does not conform to " +
-                            "algorithm constraints");
-                }
-                continue;
-            }
-
-            if (date == null) {
-                date = new Date();
-            }
-            CheckResult checkResult =
-                    checkType.check((X509Certificate)chain[0], date);
-            EntryStatus status =
-                    new EntryStatus(builderIndex, keyIndex,
-                                        alias, chain, checkResult);
-            if (!preferred && checkResult == CheckResult.OK && keyIndex == 0) {
-                preferred = true;
-            }
-            if (preferred && (findAll == false)) {
-                // if we have a good match and do not need all matches,
-                // return immediately
-                return Collections.singletonList(status);
-            } else {
-                if (results == null) {
-                    results = new ArrayList<EntryStatus>();
-                }
-                results.add(status);
-            }
-        }
-        return results;
-    }
-
-    private static boolean conformsToAlgorithmConstraints(
-            AlgorithmConstraints constraints, Certificate[] chain) {
-
-        AlgorithmChecker checker = new AlgorithmChecker(constraints);
-        try {
-            checker.init(false);
-        } catch (CertPathValidatorException cpve) {
-            // unlikely to happen
-            return false;
-        }
-
-        // It is a forward checker, so we need to check from trust to target.
-        for (int i = chain.length - 1; i >= 0; i--) {
-            Certificate cert = chain[i];
-            try {
-                // We don't care about the unresolved critical extensions.
-                checker.check(cert, Collections.<String>emptySet());
-            } catch (CertPathValidatorException cpve) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java
deleted file mode 100755
index d38e727..0000000
--- a/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.net.Socket;
-import javax.net.ssl.SSLSession;
-
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-
-import javax.net.ssl.*;
-
-import sun.security.validator.*;
-
-import sun.security.util.HostnameChecker;
-
-/**
- * This class implements the SunJSSE X.509 trust manager using the internal
- * validator API in J2SE core. The logic in this class is minimal.<p>
- * <p>
- * This class supports both the Simple validation algorithm from previous
- * JSSE versions and PKIX validation. Currently, it is not possible for the
- * application to specify PKIX parameters other than trust anchors. This will
- * be fixed in a future release using new APIs. When that happens, it may also
- * make sense to separate the Simple and PKIX trust managers into separate
- * classes.
- *
- * @author Andreas Sterbenz
- */
-final class X509TrustManagerImpl extends X509ExtendedTrustManager
-        implements X509TrustManager {
-
-    private final String validatorType;
-
-    /**
-     * The Set of trusted X509Certificates.
-     */
-    private final Collection<X509Certificate> trustedCerts;
-
-    private final PKIXBuilderParameters pkixParams;
-
-    // note that we need separate validator for client and server due to
-    // the different extension checks. They are initialized lazily on demand.
-    private volatile Validator clientValidator, serverValidator;
-
-    private static final Debug debug = Debug.getInstance("ssl");
-
-    X509TrustManagerImpl(String validatorType, KeyStore ks)
-            throws KeyStoreException {
-        this.validatorType = validatorType;
-        this.pkixParams = null;
-        if (ks == null) {
-            trustedCerts = Collections.<X509Certificate>emptySet();
-        } else {
-            trustedCerts = KeyStores.getTrustedCerts(ks);
-        }
-        showTrustedCerts();
-    }
-
-    X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
-        this.validatorType = validatorType;
-        this.pkixParams = params;
-        // create server validator eagerly so that we can conveniently
-        // get the trusted certificates
-        // clients need it anyway eventually, and servers will not mind
-        // the little extra footprint
-        Validator v = getValidator(Validator.VAR_TLS_SERVER);
-        trustedCerts = v.getTrustedCertificates();
-        serverValidator = v;
-        showTrustedCerts();
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        checkTrusted(chain, authType, (Socket)null, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        checkTrusted(chain, authType, (Socket)null, false);
-    }
-
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
-        trustedCerts.toArray(certsArray);
-        return certsArray;
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-                Socket socket) throws CertificateException {
-        checkTrusted(chain, authType, socket, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            Socket socket) throws CertificateException {
-        checkTrusted(chain, authType, socket, false);
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        checkTrusted(chain, authType, engine, true);
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine) throws CertificateException {
-        checkTrusted(chain, authType, engine, false);
-    }
-
-    private Validator checkTrustedInit(X509Certificate[] chain,
-                                        String authType, boolean isClient) {
-        if (chain == null || chain.length == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length certificate chain");
-        }
-
-        if (authType == null || authType.length() == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length authentication type");
-        }
-
-        Validator v = null;
-        if (isClient) {
-            v = clientValidator;
-            if (v == null) {
-                synchronized (this) {
-                    v = clientValidator;
-                    if (v == null) {
-                        v = getValidator(Validator.VAR_TLS_CLIENT);
-                        clientValidator = v;
-                    }
-                }
-            }
-        } else {
-            // assume double checked locking with a volatile flag works
-            // (guaranteed under the new Tiger memory model)
-            v = serverValidator;
-            if (v == null) {
-                synchronized (this) {
-                    v = serverValidator;
-                    if (v == null) {
-                        v = getValidator(Validator.VAR_TLS_SERVER);
-                        serverValidator = v;
-                    }
-                }
-            }
-        }
-
-        return v;
-    }
-
-
-    private void checkTrusted(X509Certificate[] chain, String authType,
-                Socket socket, boolean isClient) throws CertificateException {
-        Validator v = checkTrustedInit(chain, authType, isClient);
-
-        AlgorithmConstraints constraints = null;
-        if ((socket != null) && socket.isConnected() &&
-                                        (socket instanceof SSLSocket)) {
-
-            SSLSocket sslSocket = (SSLSocket)socket;
-            SSLSession session = sslSocket.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = sslSocket.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                String hostname = session.getPeerHost();
-                checkIdentity(hostname, chain[0], identityAlg);
-            }
-
-            // create the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] localSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    sslSocket, localSupportedSignAlgs, false);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(sslSocket, false);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(sslSocket, false);
-            }
-        }
-
-        X509Certificate[] trustedChain = null;
-        if (isClient) {
-            trustedChain = validate(v, chain, constraints, null);
-        } else {
-            trustedChain = validate(v, chain, constraints, authType);
-        }
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    private void checkTrusted(X509Certificate[] chain, String authType,
-            SSLEngine engine, boolean isClient) throws CertificateException {
-        Validator v = checkTrustedInit(chain, authType, isClient);
-
-        AlgorithmConstraints constraints = null;
-        if (engine != null) {
-            SSLSession session = engine.getHandshakeSession();
-            if (session == null) {
-                throw new CertificateException("No handshake session");
-            }
-
-            // check endpoint identity
-            String identityAlg = engine.getSSLParameters().
-                                        getEndpointIdentificationAlgorithm();
-            if (identityAlg != null && identityAlg.length() != 0) {
-                String hostname = session.getPeerHost();
-                checkIdentity(hostname, chain[0], identityAlg);
-            }
-
-            // create the algorithm constraints
-            ProtocolVersion protocolVersion =
-                ProtocolVersion.valueOf(session.getProtocol());
-            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
-                if (session instanceof ExtendedSSLSession) {
-                    ExtendedSSLSession extSession =
-                                    (ExtendedSSLSession)session;
-                    String[] localSupportedSignAlgs =
-                            extSession.getLocalSupportedSignatureAlgorithms();
-
-                    constraints = new SSLAlgorithmConstraints(
-                                    engine, localSupportedSignAlgs, false);
-                } else {
-                    constraints =
-                            new SSLAlgorithmConstraints(engine, false);
-                }
-            } else {
-                constraints = new SSLAlgorithmConstraints(engine, false);
-            }
-        }
-
-        X509Certificate[] trustedChain = null;
-        if (isClient) {
-            trustedChain = validate(v, chain, constraints, null);
-        } else {
-            trustedChain = validate(v, chain, constraints, authType);
-        }
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    private void showTrustedCerts() {
-        if (debug != null && Debug.isOn("trustmanager")) {
-            for (X509Certificate cert : trustedCerts) {
-                System.out.println("adding as trusted cert:");
-                System.out.println("  Subject: "
-                                        + cert.getSubjectX500Principal());
-                System.out.println("  Issuer:  "
-                                        + cert.getIssuerX500Principal());
-                System.out.println("  Algorithm: "
-                                        + cert.getPublicKey().getAlgorithm()
-                                        + "; Serial number: 0x"
-                                        + cert.getSerialNumber().toString(16));
-                System.out.println("  Valid from "
-                                        + cert.getNotBefore() + " until "
-                                        + cert.getNotAfter());
-                System.out.println();
-            }
-        }
-    }
-
-    private Validator getValidator(String variant) {
-        Validator v;
-        if (pkixParams == null) {
-            v = Validator.getInstance(validatorType, variant, trustedCerts);
-        } else {
-            v = Validator.getInstance(validatorType, variant, pkixParams);
-        }
-        return v;
-    }
-
-    private static X509Certificate[] validate(Validator v,
-            X509Certificate[] chain, AlgorithmConstraints constraints,
-            String authType) throws CertificateException {
-        Object o = JsseJce.beginFipsProvider();
-        try {
-            return v.validate(chain, null, constraints, authType);
-        } finally {
-            JsseJce.endFipsProvider(o);
-        }
-    }
-
-    /*
-     * Identify the peer by its certificate and hostname.
-     *
-     * Lifted from sun.net.www.protocol.https.HttpsClient.
-     */
-    static void checkIdentity(String hostname, X509Certificate cert,
-            String algorithm) throws CertificateException {
-        if (algorithm != null && algorithm.length() != 0) {
-            // if IPv6 strip off the "[]"
-            if ((hostname != null) && hostname.startsWith("[") &&
-                    hostname.endsWith("]")) {
-                hostname = hostname.substring(1, hostname.length() - 1);
-            }
-
-            if (algorithm.equalsIgnoreCase("HTTPS")) {
-                HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match(
-                        hostname, cert);
-            } else if (algorithm.equalsIgnoreCase("LDAP") ||
-                    algorithm.equalsIgnoreCase("LDAPS")) {
-                HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP).match(
-                        hostname, cert);
-            } else {
-                throw new CertificateException(
-                        "Unknown identification algorithm: " + algorithm);
-            }
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/security/util/HostnameChecker.java b/ojluni/src/main/java/sun/security/util/HostnameChecker.java
deleted file mode 100755
index b3e8971..0000000
--- a/ojluni/src/main/java/sun/security/util/HostnameChecker.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2002, 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 sun.security.util;
-
-import java.io.IOException;
-import java.util.*;
-
-import java.security.Principal;
-import java.security.cert.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.ssl.Krb5Helper;
-import sun.security.x509.X500Name;
-
-import sun.net.util.IPAddressUtil;
-
-/**
- * Class to check hostnames against the names specified in a certificate as
- * required for TLS and LDAP.
- *
- */
-public class HostnameChecker {
-
-    // Constant for a HostnameChecker for TLS
-    public final static byte TYPE_TLS = 1;
-    private final static HostnameChecker INSTANCE_TLS =
-                                        new HostnameChecker(TYPE_TLS);
-
-    // Constant for a HostnameChecker for LDAP
-    public final static byte TYPE_LDAP = 2;
-    private final static HostnameChecker INSTANCE_LDAP =
-                                        new HostnameChecker(TYPE_LDAP);
-
-    // constants for subject alt names of type DNS and IP
-    private final static int ALTNAME_DNS = 2;
-    private final static int ALTNAME_IP  = 7;
-
-    // the algorithm to follow to perform the check. Currently unused.
-    private final byte checkType;
-
-    private HostnameChecker(byte checkType) {
-        this.checkType = checkType;
-    }
-
-    /**
-     * Get a HostnameChecker instance. checkType should be one of the
-     * TYPE_* constants defined in this class.
-     */
-    public static HostnameChecker getInstance(byte checkType) {
-        if (checkType == TYPE_TLS) {
-            return INSTANCE_TLS;
-        } else if (checkType == TYPE_LDAP) {
-            return INSTANCE_LDAP;
-        }
-        throw new IllegalArgumentException("Unknown check type: " + checkType);
-    }
-
-    /**
-     * Perform the check.
-     *
-     * @exception CertificateException if the name does not match any of
-     * the names specified in the certificate
-     */
-    public void match(String expectedName, X509Certificate cert)
-            throws CertificateException {
-        if (isIpAddress(expectedName)) {
-           matchIP(expectedName, cert);
-        } else {
-           matchDNS(expectedName, cert);
-        }
-    }
-
-    /**
-     * Perform the check for Kerberos.
-     */
-    public static boolean match(String expectedName, Principal principal) {
-        String hostName = getServerName(principal);
-        return (expectedName.equalsIgnoreCase(hostName));
-    }
-
-    /**
-     * Return the Server name from Kerberos principal.
-     */
-    public static String getServerName(Principal principal) {
-        return Krb5Helper.getPrincipalHostName(principal);
-    }
-
-    /**
-     * Test whether the given hostname looks like a literal IPv4 or IPv6
-     * address. The hostname does not need to be a fully qualified name.
-     *
-     * This is not a strict check that performs full input validation.
-     * That means if the method returns true, name need not be a correct
-     * IP address, rather that it does not represent a valid DNS hostname.
-     * Likewise for IP addresses when it returns false.
-     */
-    private static boolean isIpAddress(String name) {
-        if (IPAddressUtil.isIPv4LiteralAddress(name) ||
-            IPAddressUtil.isIPv6LiteralAddress(name)) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Check if the certificate allows use of the given IP address.
-     *
-     * From RFC2818:
-     * In some cases, the URI is specified as an IP address rather than a
-     * hostname. In this case, the iPAddress subjectAltName must be present
-     * in the certificate and must exactly match the IP in the URI.
-     */
-    private static void matchIP(String expectedIP, X509Certificate cert)
-            throws CertificateException {
-        Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
-        if (subjAltNames == null) {
-            throw new CertificateException
-                                ("No subject alternative names present");
-        }
-        for (List<?> next : subjAltNames) {
-            // For IP address, it needs to be exact match
-            if (((Integer)next.get(0)).intValue() == ALTNAME_IP) {
-                String ipAddress = (String)next.get(1);
-                if (expectedIP.equalsIgnoreCase(ipAddress)) {
-                    return;
-                }
-            }
-        }
-        throw new CertificateException("No subject alternative " +
-                        "names matching " + "IP address " +
-                        expectedIP + " found");
-    }
-
-    /**
-     * Check if the certificate allows use of the given DNS name.
-     *
-     * From RFC2818:
-     * If a subjectAltName extension of type dNSName is present, that MUST
-     * be used as the identity. Otherwise, the (most specific) Common Name
-     * field in the Subject field of the certificate MUST be used. Although
-     * the use of the Common Name is existing practice, it is deprecated and
-     * Certification Authorities are encouraged to use the dNSName instead.
-     *
-     * Matching is performed using the matching rules specified by
-     * [RFC2459].  If more than one identity of a given type is present in
-     * the certificate (e.g., more than one dNSName name, a match in any one
-     * of the set is considered acceptable.)
-     */
-    private void matchDNS(String expectedName, X509Certificate cert)
-            throws CertificateException {
-        Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
-        if (subjAltNames != null) {
-            boolean foundDNS = false;
-            for ( List<?> next : subjAltNames) {
-                if (((Integer)next.get(0)).intValue() == ALTNAME_DNS) {
-                    foundDNS = true;
-                    String dnsName = (String)next.get(1);
-                    if (isMatched(expectedName, dnsName)) {
-                        return;
-                    }
-                }
-            }
-            if (foundDNS) {
-                // if certificate contains any subject alt names of type DNS
-                // but none match, reject
-                throw new CertificateException("No subject alternative DNS "
-                        + "name matching " + expectedName + " found.");
-            }
-        }
-        X500Name subjectName = getSubjectX500Name(cert);
-        DerValue derValue = subjectName.findMostSpecificAttribute
-                                                    (X500Name.commonName_oid);
-        if (derValue != null) {
-            try {
-                if (isMatched(expectedName, derValue.getAsString())) {
-                    return;
-                }
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-        String msg = "No name matching " + expectedName + " found";
-        throw new CertificateException(msg);
-    }
-
-
-    /**
-     * Return the subject of a certificate as X500Name, by reparsing if
-     * necessary. X500Name should only be used if access to name components
-     * is required, in other cases X500Principal is to be prefered.
-     *
-     * This method is currently used from within JSSE, do not remove.
-     */
-    public static X500Name getSubjectX500Name(X509Certificate cert)
-            throws CertificateParsingException {
-        try {
-            Principal subjectDN = cert.getSubjectDN();
-            if (subjectDN instanceof X500Name) {
-                return (X500Name)subjectDN;
-            } else {
-                X500Principal subjectX500 = cert.getSubjectX500Principal();
-                return new X500Name(subjectX500.getEncoded());
-            }
-        } catch (IOException e) {
-            throw(CertificateParsingException)
-                new CertificateParsingException().initCause(e);
-        }
-    }
-
-
-    /**
-     * Returns true if name matches against template.<p>
-     *
-     * The matching is performed as per RFC 2818 rules for TLS and
-     * RFC 2830 rules for LDAP.<p>
-     *
-     * The <code>name</code> parameter should represent a DNS name.
-     * The <code>template</code> parameter
-     * may contain the wildcard character *
-     */
-    private boolean isMatched(String name, String template) {
-        if (checkType == TYPE_TLS) {
-            return matchAllWildcards(name, template);
-        } else if (checkType == TYPE_LDAP) {
-            return matchLeftmostWildcard(name, template);
-        } else {
-            return false;
-        }
-    }
-
-
-    /**
-     * Returns true if name matches against template.<p>
-     *
-     * According to RFC 2818, section 3.1 -
-     * Names may contain the wildcard character * which is
-     * considered to match any single domain name component
-     * or component fragment.
-     * E.g., *.a.com matches foo.a.com but not
-     * bar.foo.a.com. f*.com matches foo.com but not bar.com.
-     */
-    private static boolean matchAllWildcards(String name,
-         String template) {
-        name = name.toLowerCase();
-        template = template.toLowerCase();
-        StringTokenizer nameSt = new StringTokenizer(name, ".");
-        StringTokenizer templateSt = new StringTokenizer(template, ".");
-
-        if (nameSt.countTokens() != templateSt.countTokens()) {
-            return false;
-        }
-
-        while (nameSt.hasMoreTokens()) {
-            if (!matchWildCards(nameSt.nextToken(),
-                        templateSt.nextToken())) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * Returns true if name matches against template.<p>
-     *
-     * As per RFC 2830, section 3.6 -
-     * The "*" wildcard character is allowed.  If present, it applies only
-     * to the left-most name component.
-     * E.g. *.bar.com would match a.bar.com, b.bar.com, etc. but not
-     * bar.com.
-     */
-    private static boolean matchLeftmostWildcard(String name,
-                         String template) {
-        name = name.toLowerCase();
-        template = template.toLowerCase();
-
-        // Retreive leftmost component
-        int templateIdx = template.indexOf(".");
-        int nameIdx = name.indexOf(".");
-
-        if (templateIdx == -1)
-            templateIdx = template.length();
-        if (nameIdx == -1)
-            nameIdx = name.length();
-
-        if (matchWildCards(name.substring(0, nameIdx),
-            template.substring(0, templateIdx))) {
-
-            // match rest of the name
-            return template.substring(templateIdx).equals(
-                        name.substring(nameIdx));
-        } else {
-            return false;
-        }
-    }
-
-
-    /**
-     * Returns true if the name matches against the template that may
-     * contain wildcard char * <p>
-     */
-    private static boolean matchWildCards(String name, String template) {
-
-        int wildcardIdx = template.indexOf("*");
-        if (wildcardIdx == -1)
-            return name.equals(template);
-
-        boolean isBeginning = true;
-        String beforeWildcard = "";
-        String afterWildcard = template;
-
-        while (wildcardIdx != -1) {
-
-            // match in sequence the non-wildcard chars in the template.
-            beforeWildcard = afterWildcard.substring(0, wildcardIdx);
-            afterWildcard = afterWildcard.substring(wildcardIdx + 1);
-
-            int beforeStartIdx = name.indexOf(beforeWildcard);
-            if ((beforeStartIdx == -1) ||
-                        (isBeginning && beforeStartIdx != 0)) {
-                return false;
-            }
-            isBeginning = false;
-
-            // update the match scope
-            name = name.substring(beforeStartIdx + beforeWildcard.length());
-            wildcardIdx = afterWildcard.indexOf("*");
-        }
-        return name.endsWith(afterWildcard);
-    }
-}
diff --git a/ojluni/src/main/native/AbstractPlainDatagramSocketImpl.c b/ojluni/src/main/native/AbstractPlainDatagramSocketImpl.c
new file mode 100644
index 0000000..d1de68f
--- /dev/null
+++ b/ojluni/src/main/native/AbstractPlainDatagramSocketImpl.c
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __solaris__
+#include <unistd.h>
+#include <stropts.h>
+
+#ifndef BSD_COMP
+#define BSD_COMP
+#endif
+
+#endif
+
+#include <sys/ioctl.h>
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_AbstractPlainDatagramSocketImpl.h"
+
+#include "JNIHelp.h"
+
+#define NATIVE_METHOD(className, functionName, signature) \
+{ #functionName, signature, (void*)(className ## _ ## functionName) }
+
+static jfieldID IO_fd_fdID;
+
+static jfieldID apdsi_fdID;
+
+
+/*
+ * Class:     java_net_AbstractPlainDatagramSocketImpl
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
+
+    apdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
+                                   "Ljava/io/FileDescriptor;");
+    CHECK_NULL(apdsi_fdID);
+
+    IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+/*
+ * Class:     java_net_AbstractPlainDatagramSocketImpl
+ * Method:    dataAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
+(JNIEnv *env, jobject this) {
+    int fd, retval;
+
+    jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                        "Socket closed");
+        return -1;
+    }
+    fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+    if (ioctl(fd, FIONREAD, &retval) < 0) {
+        return -1;
+    }
+    return retval;
+}
+
+static JNINativeMethod gMethods[] = {
+    NATIVE_METHOD(Java_java_net_AbstractPlainDatagramSocketImpl, init, "()V"),
+    NATIVE_METHOD(Java_java_net_AbstractPlainDatagramSocketImpl, dataAvailable, "()I"),
+};
+
+void register_java_net_AbstractPlainDatagramSocketImpl(JNIEnv* env) {
+    jniRegisterNativeMethods(env, "java/net/AbstractPlainDatagramSocketImpl", gMethods, NELEM(gMethods));
+}
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index c40dcd1..89dca05 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -52,6 +52,7 @@
 extern void register_java_lang_System(JNIEnv*);
 extern void register_java_lang_Thread(JNIEnv*);
 extern void register_java_lang_UNIXProcess(JNIEnv*);
+extern void register_java_net_AbstractPlainDatagramSocketImpl(JNIEnv*);
 extern void register_java_net_DatagramPacket(JNIEnv*);
 extern void register_java_net_Inet4Address(JNIEnv*);
 extern void register_java_net_Inet6Address(JNIEnv*);
@@ -130,6 +131,7 @@
     // register_java_net_InetAddress depends on java_lang_Float & Math being
     // fully registered (getMethodId on InetAddress class triggers its
     // <clinit> which depends on java.lang.Float)
+    register_java_net_AbstractPlainDatagramSocketImpl(env);
     register_java_net_InetAddress(env);
     register_java_net_Inet4Address(env);
     register_java_net_Inet6Address(env);
diff --git a/ojluni/src/main/native/java_net_AbstractPlainDatagramSocketImpl.h b/ojluni/src/main/native/java_net_AbstractPlainDatagramSocketImpl.h
new file mode 100644
index 0000000..5a50671
--- /dev/null
+++ b/ojluni/src/main/native/java_net_AbstractPlainDatagramSocketImpl.h
@@ -0,0 +1,57 @@
+/* This file was generated from java/net/AbstractPlainDatagramSocketImpl.java
+ * and is licensed under the same terms.  The copyright and license information
+ * for java/net/AbstractPlainDatagramSocketImpl.java follows.
+ *
+ * Copyright (c) 1996, 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.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_AbstractPlainDatagramSocketImpl */
+
+#ifndef _Included_java_net_AbstractPlainDatagramSocketImpl
+#define _Included_java_net_AbstractPlainDatagramSocketImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     java_net_AbstractPlainDatagramSocketImpl
+ * Method:    dataAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     java_net_AbstractPlainDatagramSocketImpl
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_init
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 41f6e482..e861230 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -75,6 +75,7 @@
     Character.cpp \
     Register.cpp \
     socket_tagger_util.cpp \
+    AbstractPlainDatagramSocketImpl.c \
 
 LOCAL_C_INCLUDES += \
        libcore/$(srcdir) \
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index fba2e73..9fa9afa 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -262,6 +262,7 @@
     ojluni/src/main/java/java/net/Inet4Address.java \
     ojluni/src/main/java/java/net/Inet6AddressImpl.java \
     ojluni/src/main/java/java/net/Inet6Address.java \
+    ojluni/src/main/java/java/net/InetAddressContainer.java \
     ojluni/src/main/java/java/net/InetAddressImpl.java \
     ojluni/src/main/java/java/net/InetAddress.java \
     ojluni/src/main/java/java/net/InetSocketAddress.java \
@@ -846,6 +847,7 @@
     ojluni/src/main/java/java/util/function/ToLongBiFunction.java \
     ojluni/src/main/java/java/util/function/ToLongFunction.java \
     ojluni/src/main/java/java/util/function/UnaryOperator.java \
+    ojluni/src/main/java/java/util/function/package-info.java \
     ojluni/src/main/java/java/util/jar/Attributes.java \
     ojluni/src/main/java/java/util/jar/JarEntry.java \
     ojluni/src/main/java/java/util/jar/JarException.java \
@@ -1134,7 +1136,6 @@
     ojluni/src/main/java/sun/reflect/CallerSensitive.java \
 
 openjdk_java_files := \
-    ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java \
     ojluni/src/main/java/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java \
     ojluni/src/main/java/com/sun/security/cert/internal/x509/X509V1CertImpl.java \
     ojluni/src/main/java/com/sun/nio/file/ExtendedCopyOption.java \
@@ -1143,8 +1144,8 @@
     ojluni/src/main/java/com/sun/nio/file/SensitivityWatchEventModifier.java \
     ojluni/src/main/java/java/beans/ChangeListenerMap.java \
     ojluni/src/main/java/java/lang/Shutdown.java \
-    ojluni/src/main/java/sun/misc/FDBigInt.java \
-    ojluni/src/main/java/java/lang/FloatingDecimal.java \
+    ojluni/src/main/java/sun/misc/FDBigInteger.java \
+    ojluni/src/main/java/sun/misc/FloatingDecimal.java \
     ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java \
     ojluni/src/main/java/java/text/spi/CollatorProvider.java \
     ojluni/src/main/java/java/text/spi/DateFormatProvider.java \
@@ -1226,60 +1227,46 @@
     ojluni/src/main/java/sun/net/TransferProtocolClient.java \
     ojluni/src/main/java/sun/net/util/IPAddressUtil.java \
     ojluni/src/main/java/sun/net/util/URLUtil.java \
-    ojluni/src/main/java/sun/net/www/ApplicationLaunchException.java \
     ojluni/src/main/java/sun/net/www/HeaderParser.java \
+    ojluni/src/main/java/sun/net/www/MessageHeader.java \
+    ojluni/src/main/java/sun/net/www/MeteredStream.java \
+    ojluni/src/main/java/sun/net/www/ParseUtil.java \
+    ojluni/src/main/java/sun/net/www/URLConnection.java \
     ojluni/src/main/java/sun/net/www/http/ChunkedInputStream.java \
     ojluni/src/main/java/sun/net/www/http/ChunkedOutputStream.java \
-    ojluni/src/main/java/sun/net/www/http/HttpCaptureInputStream.java \
     ojluni/src/main/java/sun/net/www/http/HttpCapture.java \
+    ojluni/src/main/java/sun/net/www/http/HttpCaptureInputStream.java \
     ojluni/src/main/java/sun/net/www/http/HttpCaptureOutputStream.java \
     ojluni/src/main/java/sun/net/www/http/HttpClient.java \
     ojluni/src/main/java/sun/net/www/http/Hurryable.java \
     ojluni/src/main/java/sun/net/www/http/KeepAliveCache.java \
-    ojluni/src/main/java/sun/net/www/http/KeepAliveStreamCleaner.java \
     ojluni/src/main/java/sun/net/www/http/KeepAliveStream.java \
+    ojluni/src/main/java/sun/net/www/http/KeepAliveStreamCleaner.java \
     ojluni/src/main/java/sun/net/www/http/PosterOutputStream.java \
-    ojluni/src/main/java/sun/net/www/MessageHeader.java \
-    ojluni/src/main/java/sun/net/www/MeteredStream.java \
-    ojluni/src/main/java/sun/net/www/MimeEntry.java \
-    ojluni/src/main/java/sun/net/www/MimeLauncher.java \
-    ojluni/src/main/java/sun/net/www/MimeTable.java \
-    ojluni/src/main/java/sun/net/www/ParseUtil.java \
     ojluni/src/main/java/sun/net/www/protocol/file/FileURLConnection.java \
     ojluni/src/main/java/sun/net/www/protocol/file/Handler.java \
     ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java \
     ojluni/src/main/java/sun/net/www/protocol/ftp/Handler.java \
-    ojluni/src/main/java/sun/net/www/protocol/gopher/GopherClient.java \
-    ojluni/src/main/java/sun/net/www/protocol/gopher/Handler.java \
-    ojluni/src/main/java/sun/net/www/protocol/http/AuthCacheImpl.java \
     ojluni/src/main/java/sun/net/www/protocol/http/AuthCache.java \
+    ojluni/src/main/java/sun/net/www/protocol/http/AuthCacheImpl.java \
     ojluni/src/main/java/sun/net/www/protocol/http/AuthCacheValue.java \
+    ojluni/src/main/java/sun/net/www/protocol/http/AuthScheme.java \
     ojluni/src/main/java/sun/net/www/protocol/http/AuthenticationHeader.java \
     ojluni/src/main/java/sun/net/www/protocol/http/AuthenticationInfo.java \
-    ojluni/src/main/java/sun/net/www/protocol/http/AuthScheme.java \
     ojluni/src/main/java/sun/net/www/protocol/http/BasicAuthentication.java \
     ojluni/src/main/java/sun/net/www/protocol/http/DigestAuthentication.java \
     ojluni/src/main/java/sun/net/www/protocol/http/Handler.java \
     ojluni/src/main/java/sun/net/www/protocol/http/HttpAuthenticator.java \
     ojluni/src/main/java/sun/net/www/protocol/http/HttpCallerInfo.java \
     ojluni/src/main/java/sun/net/www/protocol/http/HttpURLConnection.java \
+    ojluni/src/main/java/sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
     ojluni/src/main/java/sun/net/www/protocol/http/NegotiateAuthentication.java \
     ojluni/src/main/java/sun/net/www/protocol/http/Negotiator.java \
-    ojluni/src/main/java/sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
-    ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
-    ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java \
-    ojluni/src/main/java/sun/net/www/protocol/https/Handler.java \
-    ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java \
-    ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java \
     ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java \
     ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java \
     ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java \
-    ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java \
     ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java \
-    ojluni/src/main/java/sun/net/www/protocol/mailto/Handler.java \
-    ojluni/src/main/java/sun/net/www/protocol/mailto/MailToURLConnection.java \
-    ojluni/src/main/java/sun/net/www/protocol/netdoc/Handler.java \
-    ojluni/src/main/java/sun/net/www/URLConnection.java \
+    ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java \
     ojluni/src/main/java/sun/nio/ByteBuffered.java \
     ojluni/src/main/java/sun/nio/ch/AbstractPollArrayWrapper.java \
     ojluni/src/main/java/sun/nio/ch/AbstractPollSelectorImpl.java \
@@ -1477,61 +1464,6 @@
     ojluni/src/main/java/sun/security/provider/certpath/X509CertificatePair.java \
     ojluni/src/main/java/sun/security/provider/X509Factory.java \
     ojluni/src/main/java/sun/security/rsa/SunRsaSignEntries.java \
-    ojluni/src/main/java/sun/security/ssl/Alerts.java \
-    ojluni/src/main/java/sun/security/ssl/AppInputStream.java \
-    ojluni/src/main/java/sun/security/ssl/AppOutputStream.java \
-    ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java \
-    ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java \
-    ojluni/src/main/java/sun/security/ssl/CipherBox.java \
-    ojluni/src/main/java/sun/security/ssl/CipherSuite.java \
-    ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java \
-    ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java \
-    ojluni/src/main/java/sun/security/ssl/Debug.java \
-    ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java \
-    ojluni/src/main/java/sun/security/ssl/DHCrypt.java \
-    ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java \
-    ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java \
-    ojluni/src/main/java/sun/security/ssl/EngineArgs.java \
-    ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java \
-    ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java \
-    ojluni/src/main/java/sun/security/ssl/EngineWriter.java \
-    ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java \
-    ojluni/src/main/java/sun/security/ssl/HandshakeHash.java \
-    ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java \
-    ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java \
-    ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java \
-    ojluni/src/main/java/sun/security/ssl/Handshaker.java \
-    ojluni/src/main/java/sun/security/ssl/HelloExtensions.java \
-    ojluni/src/main/java/sun/security/ssl/InputRecord.java \
-    ojluni/src/main/java/sun/security/ssl/JsseJce.java \
-    ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java \
-    ojluni/src/main/java/sun/security/ssl/Krb5Helper.java \
-    ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java \
-    ojluni/src/main/java/sun/security/ssl/MAC.java \
-    ojluni/src/main/java/sun/security/ssl/OutputRecord.java \
-    ojluni/src/main/java/sun/security/ssl/ProtocolList.java \
-    ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java \
-    ojluni/src/main/java/sun/security/ssl/RandomCookie.java \
-    ojluni/src/main/java/sun/security/ssl/Record.java \
-    ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java \
-    ojluni/src/main/java/sun/security/ssl/RSASignature.java \
-    ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java \
-    ojluni/src/main/java/sun/security/ssl/SessionId.java \
-    ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java \
-    ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java \
-    ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java \
-    ojluni/src/main/java/sun/security/ssl/SunJSSE.java \
-    ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java \
-    ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java \
-    ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java \
-    ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java \
     ojluni/src/main/java/sun/security/timestamp/TimestampToken.java \
     ojluni/src/main/java/sun/security/util/BitArray.java \
     ojluni/src/main/java/sun/security/util/ByteArrayLexOrder.java \
@@ -1545,7 +1477,6 @@
     ojluni/src/main/java/sun/security/util/DerOutputStream.java \
     ojluni/src/main/java/sun/security/util/DerValue.java \
     ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java \
-    ojluni/src/main/java/sun/security/util/HostnameChecker.java \
     ojluni/src/main/java/sun/security/util/KeyUtil.java \
     ojluni/src/main/java/sun/security/util/Length.java \
     ojluni/src/main/java/sun/security/util/ManifestDigester.java \
diff --git a/support/src/test/java/tests/util/SummaryStatistics.java b/support/src/test/java/tests/util/SummaryStatistics.java
index 4ce0a04..7a0d0b1 100644
--- a/support/src/test/java/tests/util/SummaryStatistics.java
+++ b/support/src/test/java/tests/util/SummaryStatistics.java
@@ -23,11 +23,13 @@
   /** Sum of the values. */
   private double sum;
 
-  /** Sum of the squares of the values added. */
-  private double squaresSum;
+  /** Use the first value to shift all values to it when computing variance, as it improves
+   * numerical stability. Note variance is invariant to shifting. */
+  private Double firstValue = null;
 
-  /** The previously added value. */
-  private double lastValue;
+  /** Sum of the squares of the values added, shifted according to the first value. */
+  private double shiftedSquaresSum;
+
 
   public SummaryStatistics() {
   }
@@ -38,10 +40,12 @@
 
   /** Add a new value to the values seen. */
   public void add(double value) {
-    sum += value - lastValue;
-    squaresSum += square(value) - square(lastValue);
+    if (firstValue == null) {
+      firstValue = new Double(value);
+    }
+    sum += value;
+    shiftedSquaresSum += square(value - firstValue);
     numValues++;
-    lastValue = value;
   }
 
   /** Mean of the values seen. */
@@ -51,7 +55,8 @@
 
   /** Variance of the values seen. */
   public double var() {
-    return (squaresSum / numValues) - square(mean());
+    double shiftedMean = (sum - numValues * firstValue) / numValues;
+    return (shiftedSquaresSum / numValues) - square(shiftedMean);
   }
 
   /** Standard deviation of the values seen. */