Merge
authorlana
Tue, 09 Nov 2010 22:53:18 -0800
changeset 7050 525b0c46526a
parent 6995 e8d03f9ed991 (current diff)
parent 7049 f6ad89ce23f7 (diff)
child 7056 e5798edad254
Merge
jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java
jdk/src/share/classes/sun/java2d/pisces/LineSink.java
jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java
jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java
--- a/jdk/make/java/java/FILES_java.gmk	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/java/java/FILES_java.gmk	Tue Nov 09 22:53:18 2010 -0800
@@ -413,6 +413,7 @@
     java/io/FilePermission.java \
     java/io/Serializable.java \
     java/io/Externalizable.java \
+    java/io/SerialCallbackContext.java \
 	java/io/Bits.java \
 	java/io/ObjectInput.java \
 	java/io/ObjectInputStream.java \
--- a/jdk/make/java/jli/Makefile	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/java/jli/Makefile	Tue Nov 09 22:53:18 2010 -0800
@@ -148,14 +148,9 @@
 #
 ifeq ($(PLATFORM), windows)
 
-STATIC_LIBRARY_DIR = $(OBJDIR)/static
-STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
-STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
+STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
 
-$(STATIC_LIBRARY_DIR): $(OBJDIR)
-	@$(MKDIR) $(STATIC_LIBRARY_DIR)
-
-$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
+$(STATIC_LIBRARY): $(FILES_o)
 	@$(prep-target)
 	$(LIBEXE) -nologo -out:$@ $(FILES_o)
 
--- a/jdk/make/java/nio/FILES_java.gmk	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/java/nio/FILES_java.gmk	Tue Nov 09 22:53:18 2010 -0800
@@ -33,7 +33,6 @@
 	java/nio/channels/AsynchronousByteChannel.java \
 	java/nio/channels/AsynchronousChannel.java \
 	java/nio/channels/AsynchronousChannelGroup.java \
-	java/nio/channels/AsynchronousDatagramChannel.java \
 	java/nio/channels/AsynchronousFileChannel.java \
 	java/nio/channels/AsynchronousServerSocketChannel.java \
 	java/nio/channels/AsynchronousSocketChannel.java \
@@ -207,7 +206,6 @@
 	sun/nio/ch/SelChImpl.java \
 	sun/nio/ch/ServerSocketAdaptor.java \
 	sun/nio/ch/ServerSocketChannelImpl.java \
-	sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
         sun/nio/ch/SinkChannelImpl.java \
 	sun/nio/ch/SocketAdaptor.java \
 	sun/nio/ch/SocketChannelImpl.java \
--- a/jdk/make/javax/sound/jsoundds/Makefile	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/javax/sound/jsoundds/Makefile	Tue Nov 09 22:53:18 2010 -0800
@@ -53,7 +53,7 @@
 #
 # Extra cc/linker flags.
 #
-LDLIBS += dsound.lib winmm.lib user32.lib
+LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib
 CPPFLAGS += \
 	-DUSE_DAUDIO=TRUE \
 	-I$(SHARE_SRC)/native/com/sun/media/sound \
--- a/jdk/make/netbeans/jmx/build.properties	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/netbeans/jmx/build.properties	Tue Nov 09 22:53:18 2010 -0800
@@ -48,8 +48,8 @@
 jar.jmx.sealed				= true
 jar.jmx.spec.title			= JSR 003, 160, 255 - JMX API
 jar.jmx.spec.version			= ${project.spec.version}
-jar.jmx.spec.vendor			= Sun Microsystems, Inc.
-jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API 
+jar.jmx.spec.vendor			= Oracle Corporation
+jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API
 jar.jmx.impl.vendor			= Project OpenJDK
 
 javadoc.options=-J-Xmx256m
--- a/jdk/make/sun/javazic/tzdata/VERSION	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/sun/javazic/tzdata/VERSION	Tue Nov 09 22:53:18 2010 -0800
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2010l
+tzdata2010o
--- a/jdk/make/sun/javazic/tzdata/asia	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/sun/javazic/tzdata/asia	Tue Nov 09 22:53:18 2010 -0800
@@ -569,8 +569,8 @@
 Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
 Rule	HK	1954	only	-	Oct	31	3:30	0	-
 Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
-Rule	HK	1965	1977	-	Apr	Sun>=16	3:30	1:00	S
-Rule	HK	1965	1977	-	Oct	Sun>=16	3:30	0	-
+Rule	HK	1965	1976	-	Apr	Sun>=16	3:30	1:00	S
+Rule	HK	1965	1976	-	Oct	Sun>=16	3:30	0	-
 Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
 Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
 Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
--- a/jdk/make/sun/javazic/tzdata/australasia	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/sun/javazic/tzdata/australasia	Tue Nov 09 22:53:18 2010 -0800
@@ -306,13 +306,26 @@
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
 # </a>
 
+# From Alexander Krivenyshev (2010-10-24):
+# According to Radio Fiji and Fiji Times online, Fiji will end DST 3 
+# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
+# Here is confirmation from Government of the Republic of the Fiji Islands, 
+# Ministry of Information (fiji.gov.fj) web site:
+# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
+# </a>
+# or
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
+# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
+# </a>
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
 Rule	Fiji	2009	only	-	Nov	29	2:00	1:00	S
 Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
 Rule	Fiji	2010	only	-	Oct	24	2:00	1:00	S
-Rule	Fiji	2011	only	-	Mar	lastSun 3:00	0	-
+Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
@@ -509,11 +522,21 @@
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
 # </a>
 
+# From Raymond Hughes (2010-10-07):
+# Please see
+# <a href="http://www.mcil.gov.ws">
+# http://www.mcil.gov.ws
+# </a>,
+# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
+# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
+# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
+# backwards from 1:00am to 12:00am"
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
 			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 3
+			-11:00	1:00	WSDT	2011 Apr 3 1:00
 			-11:00	-	WST
 
 # Solomon Is
--- a/jdk/make/sun/javazic/tzdata/zone.tab	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/make/sun/javazic/tzdata/zone.tab	Tue Nov 09 22:53:18 2010 -0800
@@ -63,7 +63,7 @@
 AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
-AQ	-7824+10654	Antarctica/Vostok	Vostok Station, S Magnetic Pole
+AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
 AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-5430+15857	Antarctica/Macquarie	Macquarie Island Station, Macquarie Island
--- a/jdk/src/share/bin/java.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/bin/java.c	Tue Nov 09 22:53:18 2010 -0800
@@ -355,7 +355,6 @@
 
     JavaVM *vm = 0;
     JNIEnv *env = 0;
-    jstring mainClassName;
     jclass mainClass;
     jmethodID mainID;
     jobjectArray mainArgs;
--- a/jdk/src/share/bin/parse_manifest.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/bin/parse_manifest.c	Tue Nov 09 22:53:18 2010 -0800
@@ -72,7 +72,7 @@
     if (entry->how == STORED) {
         *(char *)((size_t)in + entry->csize) = '\0';
         if (size_out) {
-            *size_out = entry->csize;
+            *size_out = (int)entry->csize;
         }
         return (in);
     } else if (entry->how == DEFLATED) {
@@ -103,7 +103,7 @@
             return (NULL);
         }
         if (size_out) {
-            *size_out = entry->isize;
+            *size_out = (int)entry->isize;
         }
         return (out);
     } else
@@ -317,7 +317,7 @@
          * manifest.  If so, build the entry record from the data found in
          * the header located and return success.
          */
-        if (CENNAM(p) == JLI_StrLen(file_name) &&
+        if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
           memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
             if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
                 free(buffer);
@@ -606,8 +606,5 @@
     }
     free(mp);
     close(fd);
-    if (rc == 0)
-        return (0);
-    else
-        return (-2);
+    return (rc == 0) ? 0 : -2;
 }
--- a/jdk/src/share/bin/wildcard.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/bin/wildcard.c	Tue Nov 09 22:53:18 2010 -0800
@@ -290,12 +290,12 @@
     char *path;
     char *p;
     for (i = 0, size = 1; i < fl->size; i++)
-        size += JLI_StrLen(fl->files[i]) + 1;
+        size += (int)JLI_StrLen(fl->files[i]) + 1;
 
     path = JLI_MemAlloc(size);
 
     for (i = 0, p = path; i < fl->size; i++) {
-        int len = JLI_StrLen(fl->files[i]);
+        int len = (int)JLI_StrLen(fl->files[i]);
         if (i > 0) *p++ = sep;
         memcpy(p, fl->files[i], len);
         p += len;
@@ -309,7 +309,7 @@
 FileList_split(const char *path, char sep)
 {
     const char *p, *q;
-    int len = JLI_StrLen(path);
+    int len = (int)JLI_StrLen(path);
     int count;
     FileList fl;
     for (count = 1, p = path; p < path + len; p++)
@@ -330,7 +330,7 @@
 static int
 isJarFileName(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len >= 4) &&
         (filename[len - 4] == '.') &&
         (equal(filename + len - 3, "jar") ||
@@ -342,8 +342,8 @@
 static char *
 wildcardConcat(const char *wildcard, const char *basename)
 {
-    int wildlen = JLI_StrLen(wildcard);
-    int baselen = JLI_StrLen(basename);
+    int wildlen = (int)JLI_StrLen(wildcard);
+    int baselen = (int)JLI_StrLen(basename);
     char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
     /* Replace the trailing '*' with basename */
     memcpy(filename, wildcard, wildlen-1);
@@ -369,7 +369,7 @@
 static int
 isWildcard(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len > 0) &&
         (filename[len - 1] == '*') &&
         (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
--- a/jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -253,7 +253,8 @@
             for (j = 0; j < 8; j++) {
                 if (AA[i][j] != 0) {
                     AA[i][j] = (byte)
-                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
+                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
+                        % 255];
                 }
             }
             for (t = 0; t < 4; t++) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -92,7 +92,8 @@
     }
 
     // core crypt code. OFB style, so works for both encryption and decryption
-    private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
+    private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs) {
         if (is < 0) {
             // doFinal() was called, need to reset the cipher to initial state
             init(lastKey);
--- a/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -31,8 +31,8 @@
 import javax.crypto.spec.*;
 
 /**
- * This class implements the DESede algorithm (DES-EDE, tripleDES) in its various
- * modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
+ * This class implements the DESede algorithm (DES-EDE, tripleDES) in
+ * its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
  * <code>CBC</code>, <code>PCBC</code>) and padding schemes
  * (<code>PKCS5Padding</code>, <code>NoPadding</code>,
  * <code>ISO10126Padding</code>).
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -190,7 +190,8 @@
             ike.initCause(e);
             throw ike;
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
@@ -300,7 +301,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.x = in.getBigInteger();
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -180,7 +180,8 @@
             throw new InvalidKeyException("Private-value length too big");
 
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
@@ -281,7 +282,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.y = in.getBigInteger();
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
--- a/jdk/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -764,7 +764,8 @@
                                     cf = (CertificateFactory)cfs.get(certType);
                                 } else {
                                 // create new certificate factory
-                                    cf = CertificateFactory.getInstance(certType);
+                                    cf = CertificateFactory.getInstance(
+                                        certType);
                                 // store the certificate factory so we can
                                 // reuse it later
                                     cfs.put(certType, cf);
@@ -863,8 +864,9 @@
                     dis.readFully(actual);
                     for (int i = 0; i < computed.length; i++) {
                         if (computed[i] != actual[i]) {
-                            throw new IOException("Keystore was tampered with, or "
-                                                  + "password was incorrect");
+                            throw new IOException(
+                                "Keystore was tampered with, or "
+                                + "password was incorrect");
                         }
                     }
                 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -139,7 +139,8 @@
                 if (!val.getOID().equals((Object) OID_MGF1)) {
                     throw new IOException("Only MGF1 mgf is supported");
                 }
-                AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams()));
+                AlgorithmId params = AlgorithmId.parse(
+                    new DerValue(val.getEncodedParams()));
                 String mgfDigestName = convertToStandardName(params.getName());
                 if (mgfDigestName.equals("SHA-1")) {
                     mgfSpec = MGF1ParameterSpec.SHA1;
@@ -150,7 +151,8 @@
                 } else if (mgfDigestName.equals("SHA-512")) {
                     mgfSpec = MGF1ParameterSpec.SHA512;
                 } else {
-                    throw new IOException("Unrecognized message digest algorithm");
+                    throw new IOException(
+                        "Unrecognized message digest algorithm");
                 }
             } else if (data.isContextSpecific((byte) 0x02)) {
                 // pSource algid
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -121,8 +121,8 @@
         this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
     }
 
-    private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt,
-                                    int iterCount, int keyLengthInBit) {
+    private static byte[] deriveKey(final Mac prf, final byte[] password,
+            byte[] salt, int iterCount, int keyLengthInBit) {
         int keyLength = keyLengthInBit/8;
         byte[] key = new byte[keyLength];
         try {
@@ -155,8 +155,9 @@
                     if (this == obj) return true;
                     if (this.getClass() != obj.getClass()) return false;
                     SecretKey sk = (SecretKey)obj;
-                    return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) &&
-                            Arrays.equals(password, sk.getEncoded());
+                    return prf.getAlgorithm().equalsIgnoreCase(
+                        sk.getAlgorithm()) &&
+                        Arrays.equals(password, sk.getEncoded());
                 }
             };
             prf.init(macKey);
--- a/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -206,7 +206,8 @@
                 (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
         } catch (GeneralSecurityException gse) {
             // should never happen
-            throw new RuntimeException("SunJCE provider is not configured properly");
+            throw new RuntimeException(
+                "SunJCE provider is not configured properly");
         }
         try {
             params.init(pbeSpec);
@@ -316,7 +317,8 @@
             try {
                 paramSpec = params.getParameterSpec(PBEParameterSpec.class);
             } catch (InvalidParameterSpecException ipse) {
-                throw new InvalidAlgorithmParameterException("requires PBE parameters");
+                throw new InvalidAlgorithmParameterException(
+                    "requires PBE parameters");
             }
         }
         implInit(opmode, key, paramSpec, random);
--- a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -423,15 +423,31 @@
 
                 /*
                  * SSL/TLS mechanisms
+                 *
+                 * These are strictly internal implementations and may
+                 * be changed at any time.  These names were chosen
+                 * because PKCS11/SunPKCS11 does not yet have TLS1.2
+                 * mechanisms, and it will cause calls to come here.
                  */
                 put("KeyGenerator.SunTlsPrf",
-                        "com.sun.crypto.provider.TlsPrfGenerator");
-                put("KeyGenerator.SunTlsRsaPremasterSecret",
-                        "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
+                        "com.sun.crypto.provider.TlsPrfGenerator$V10");
+                put("KeyGenerator.SunTls12Prf",
+                        "com.sun.crypto.provider.TlsPrfGenerator$V12");
+
                 put("KeyGenerator.SunTlsMasterSecret",
-                        "com.sun.crypto.provider.TlsMasterSecretGenerator");
+                    "com.sun.crypto.provider.TlsMasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
+                    "SunTlsMasterSecret");
+
                 put("KeyGenerator.SunTlsKeyMaterial",
-                        "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                    "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12KeyMaterial",
+                    "SunTlsKeyMaterial");
+
+                put("KeyGenerator.SunTlsRsaPremasterSecret",
+                    "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12RsaPremasterSecret",
+                    "SunTlsRsaPremasterSecret");
 
                 return null;
             }
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -65,12 +65,14 @@
         }
         this.spec = (TlsKeyMaterialParameterSpec)params;
         if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -80,8 +82,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsKeyMaterialGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsKeyMaterialGenerator must be initialized");
         }
         try {
             return engineGenerateKey0();
@@ -99,8 +101,8 @@
         SecretKey clientMacKey = null;
         SecretKey serverMacKey = null;
         SecretKey clientCipherKey = null;
+        SecretKey serverCipherKey = null;
         IvParameterSpec clientIv = null;
-        SecretKey serverCipherKey = null;
         IvParameterSpec serverIv = null;
 
         int macLength = spec.getMacKeyLength();
@@ -109,21 +111,33 @@
         int keyLength = spec.getCipherKeyLength();
         int ivLength = spec.getIvLength();
 
-        int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength);
+        int keyBlockLen = macLength + keyLength
+            + (isExportable ? 0 : ivLength);
         keyBlockLen <<= 1;
         byte[] keyBlock = new byte[keyBlockLen];
 
-        MessageDigest md5 = MessageDigest.getInstance("MD5");
-        MessageDigest sha = MessageDigest.getInstance("SHA1");
+        // These may be used again later for exportable suite calculations.
+        MessageDigest md5 = null;
+        MessageDigest sha = null;
 
         // generate key block
-        if (protocolVersion >= 0x0301) {
-            // TLS
+        if (protocolVersion >= 0x0303) {
+            // TLS 1.2
             byte[] seed = concat(serverRandom, clientRandom);
-            keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+            keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+                        keyBlockLen, spec.getPRFHashAlg(),
+                        spec.getPRFHashLength(), spec.getPRFBlockSize());
+        } else if (protocolVersion >= 0x0301) {
+            // TLS 1.0/1.1
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
+            byte[] seed = concat(serverRandom, clientRandom);
+            keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
                         keyBlockLen, md5, sha);
         } else {
             // SSL
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
             keyBlock = new byte[keyBlockLen];
 
             byte[] tmp = new byte[20];
@@ -169,6 +183,7 @@
 
         String alg = spec.getCipherAlgorithm();
 
+        // cipher keys
         byte[] clientKeyBytes = new byte[keyLength];
         System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
         ofs += keyLength;
@@ -182,6 +197,7 @@
             clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
             serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
 
+            // IV keys if needed.
             if (ivLength != 0) {
                 tmp = new byte[ivLength];
 
@@ -194,21 +210,28 @@
                 serverIv = new IvParameterSpec(tmp);
             }
         } else {
+            // if exportable suites, calculate the alternate
             // cipher key expansion and IV generation
-            if (protocolVersion >= 0x0301) {
+            if (protocolVersion >= 0x0302) {
+                // TLS 1.1+
+                throw new RuntimeException(
+                    "Internal Error:  TLS 1.1+ should not be negotiating" +
+                    "exportable ciphersuites");
+            } else if (protocolVersion == 0x0301) {
+                // TLS 1.0
                 byte[] seed = concat(clientRandom, serverRandom);
 
-                tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
+                tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 clientCipherKey = new SecretKeySpec(tmp, alg);
 
-                tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
+                tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 serverCipherKey = new SecretKeySpec(tmp, alg);
 
                 if (ivLength != 0) {
                     tmp = new byte[ivLength];
-                    byte[] block = doPRF(null, LABEL_IV_BLOCK, seed,
+                    byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
                                 ivLength << 1, md5, sha);
                     System.arraycopy(block, 0, tmp, 0, ivLength);
                     clientIv = new IvParameterSpec(tmp);
@@ -216,6 +239,7 @@
                     serverIv = new IvParameterSpec(tmp);
                 }
             } else {
+                // SSLv3
                 tmp = new byte[expandedKeyLength];
 
                 md5.update(clientKeyBytes);
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -64,12 +64,14 @@
         }
         this.spec = (TlsMasterSecretParameterSpec)params;
         if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -79,8 +81,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsMasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsMasterSecretGenerator must be initialized");
         }
         SecretKey premasterKey = spec.getPremasterSecret();
         byte[] premaster = premasterKey.getEncoded();
@@ -103,7 +105,11 @@
 
             if (protocolVersion >= 0x0301) {
                 byte[] seed = concat(clientRandom, serverRandom);
-                master = doPRF(premaster, LABEL_MASTER_SECRET, seed, 48);
+                master = ((protocolVersion >= 0x0303) ?
+                    doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
+                        spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                        spec.getPRFBlockSize()) :
+                    doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
             } else {
                 master = new byte[48];
                 MessageDigest md5 = MessageDigest.getInstance("MD5");
@@ -124,7 +130,8 @@
 
             }
 
-            return new TlsMasterSecretKey(master, premasterMajor, premasterMinor);
+            return new TlsMasterSecretKey(master, premasterMajor,
+                premasterMinor);
         } catch (NoSuchAlgorithmException e) {
             throw new ProviderException(e);
         } catch (DigestException e) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -37,11 +37,15 @@
 
 /**
  * KeyGenerator implementation for the TLS PRF function.
+ * <p>
+ * This class duplicates the HMAC functionality (RFC 2104) with
+ * performance optimizations (e.g. XOR'ing keys with padding doesn't
+ * need to be redone for each HMAC operation).
  *
  * @author  Andreas Sterbenz
  * @since   1.6
  */
-public final class TlsPrfGenerator extends KeyGeneratorSpi {
+abstract class TlsPrfGenerator extends KeyGeneratorSpi {
 
     // magic constants and utility functions, also used by other files
     // in this package
@@ -69,8 +73,10 @@
      * TLS HMAC "inner" and "outer" padding.  This isn't a function
      * of the digest algorithm.
      */
-    private static final byte[] HMAC_ipad = genPad((byte)0x36, 64);
-    private static final byte[] HMAC_opad = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_ipad64  = genPad((byte)0x36, 64);
+    private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
+    private static final byte[] HMAC_opad64  = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
 
     // SSL3 magic mix constants ("A", "BB", "CCC", ...)
     final static byte[][] SSL3_CONST = genConst();
@@ -123,8 +129,8 @@
         this.spec = (TlsPrfParameterSpec)params;
         SecretKey key = spec.getSecret();
         if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
-            throw new InvalidAlgorithmParameterException
-                ("Key encoding format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key encoding format must be RAW");
         }
     }
 
@@ -132,17 +138,21 @@
         throw new InvalidParameterException(MSG);
     }
 
-    protected SecretKey engineGenerateKey() {
+    SecretKey engineGenerateKey0(boolean tls12) {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsPrfGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsPrfGenerator must be initialized");
         }
         SecretKey key = spec.getSecret();
         byte[] secret = (key == null) ? null : key.getEncoded();
         try {
             byte[] labelBytes = spec.getLabel().getBytes("UTF8");
             int n = spec.getOutputLength();
-            byte[] prfBytes = doPRF(secret, labelBytes, spec.getSeed(), n);
+            byte[] prfBytes = (tls12 ?
+                doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
+                    spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                    spec.getPRFBlockSize()) :
+                doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
             return new SecretKeySpec(prfBytes, "TlsPrf");
         } catch (GeneralSecurityException e) {
             throw new ProviderException("Could not generate PRF", e);
@@ -151,16 +161,67 @@
         }
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength) throws NoSuchAlgorithmException, DigestException {
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            String prfHash, int prfHashLength, int prfBlockSize)
+            throws NoSuchAlgorithmException, DigestException {
+        if (prfHash == null) {
+            throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
+        }
+        MessageDigest prfMD = MessageDigest.getInstance(prfHash);
+        return doTLS12PRF(secret, labelBytes, seed, outputLength,
+            prfMD, prfHashLength, prfBlockSize);
+    }
+
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
+            throws DigestException {
+
+        if (secret == null) {
+            secret = B0;
+        }
+
+        // If we have a long secret, digest it first.
+        if (secret.length > mdPRFBlockSize) {
+            secret = mdPRF.digest(secret);
+        }
+
+        byte[] output = new byte[outputLength];
+        byte [] ipad;
+        byte [] opad;
+
+        switch (mdPRFBlockSize) {
+        case 64:
+            ipad = HMAC_ipad64.clone();
+            opad = HMAC_opad64.clone();
+            break;
+        case 128:
+            ipad = HMAC_ipad128.clone();
+            opad = HMAC_opad128.clone();
+            break;
+        default:
+            throw new DigestException("Unexpected block size.");
+        }
+
+        // P_HASH(Secret, label + seed)
+        expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
+            seed, output, ipad, opad);
+
+        return output;
+    }
+
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength) throws NoSuchAlgorithmException,
+            DigestException {
         MessageDigest md5 = MessageDigest.getInstance("MD5");
         MessageDigest sha = MessageDigest.getInstance("SHA1");
-        return doPRF(secret, labelBytes, seed, outputLength, md5, sha);
+        return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength, MessageDigest md5, MessageDigest sha)
-            throws DigestException {
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength, MessageDigest md5,
+            MessageDigest sha) throws DigestException {
         /*
          * Split the secret into two halves S1 and S2 of same length.
          * S1 is taken from the first half of the secret, S2 from the
@@ -183,10 +244,12 @@
         byte[] output = new byte[outputLength];
 
         // P_MD5(S1, label + seed)
-        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output);
+        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         // P_SHA-1(S2, label + seed)
-        expand(sha, 20, secret, off, seclen, labelBytes, seed, output);
+        expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         return output;
     }
@@ -201,16 +264,13 @@
      * @param seed the seed
      * @param output the output array
      */
-    private static final void expand(MessageDigest digest, int hmacSize,
+    private static void expand(MessageDigest digest, int hmacSize,
             byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
-            byte[] output) throws DigestException {
+            byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
         /*
          * modify the padding used, by XORing the key into our copy of that
          * padding.  That's to avoid doing that for each HMAC computation.
          */
-        byte[] pad1 = HMAC_ipad.clone();
-        byte[] pad2 = HMAC_opad.clone();
-
         for (int i = 0; i < secLen; i++) {
             pad1[i] ^= secret[i + secOff];
             pad2[i] ^= secret[i + secOff];
@@ -275,7 +335,34 @@
             }
             remaining -= k;
         }
-
     }
 
+    /**
+     * A KeyGenerator implementation that supports TLS 1.2.
+     * <p>
+     * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
+     * calculations.  As of 2010, there is no PKCS11-level support for TLS
+     * 1.2 PRF calculations, and no known OS's have an internal variant
+     * we could use.  Therefore for TLS 1.2, we are updating JSSE to request
+     * a different provider algorithm:  "SunTls12Prf".  If we reused the
+     * name "SunTlsPrf", the PKCS11 provider would need be updated to
+     * fail correctly when presented with the wrong version number
+     * (via Provider.Service.supportsParameters()), and add the
+     * appropriate supportsParamters() checks into KeyGenerators (not
+     * currently there).
+     */
+    static public class V12 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(true);
+        }
+    }
+
+    /**
+     * A KeyGenerator implementation that supports TLS 1.0/1.1.
+     */
+    static public class V10 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(false);
+        }
+    }
 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -69,8 +69,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                    ("TlsRsaPremasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsRsaPremasterSecretGenerator must be initialized");
         }
         if (random == null) {
             random = new SecureRandom();
--- a/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Tue Nov 09 22:53:18 2010 -0800
@@ -76,9 +76,9 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of this product implementing the  JMX specification.
@@ -91,7 +91,7 @@
      * The name of the vendor of this product implementing the
      * JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Tue Nov 09 22:53:18 2010 -0800
@@ -27,7 +27,7 @@
 
 /**
  * Used for storing default values used by SNMP Runtime services.
- * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * <p><b>This API is an Oracle Corporation internal API  and is subject
  * to change without notice.</b></p>
  */
 public class ServiceName {
@@ -144,16 +144,16 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of the vendor of this product implementing the  JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 
     /**
       * The build number of the current product version, of the form <CODE>rXX</CODE>.
--- a/jdk/src/share/classes/com/sun/management/package.html	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/com/sun/management/package.html	Tue Nov 09 22:53:18 2010 -0800
@@ -30,7 +30,7 @@
 </head>
 <body bgcolor="white">
 
-This package contains Sun Microsystem's platform extension to
+This package contains Oracle Corporation's platform extension to
 the implementation of the
 <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html">
 java.lang.management</a> API and also defines the management
--- a/jdk/src/share/classes/java/awt/BasicStroke.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/BasicStroke.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,8 @@
 
 package java.awt;
 
+import java.beans.ConstructorProperties;
+
 /**
  * The <code>BasicStroke</code> class defines a basic set of rendering
  * attributes for the outlines of graphics primitives, which are rendered
@@ -183,6 +185,7 @@
      *         <code>dash</code> is zero
      * @throws IllegalArgumentException if dash lengths are all zero.
      */
+    @ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" })
     public BasicStroke(float width, int cap, int join, float miterlimit,
                        float dash[], float dash_phase) {
         if (width < 0.0f) {
--- a/jdk/src/share/classes/java/awt/GradientPaint.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/GradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -29,6 +29,7 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.geom.AffineTransform;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>GradientPaint</code> class provides a way to fill
@@ -166,6 +167,7 @@
      * @throws NullPointerException if either one of colors or points
      * is null
      */
+    @ConstructorProperties({ "point1", "color1", "point2", "color2", "cyclic" })
     public GradientPaint(Point2D pt1,
                          Color color1,
                          Point2D pt2,
--- a/jdk/src/share/classes/java/awt/GridBagConstraints.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/GridBagConstraints.java	Tue Nov 09 22:53:18 2010 -0800
@@ -126,7 +126,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the start of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTH for horizontal
+     * {@code ComponentOrientation}.  Equal to NORTH for horizontal
      * orientations.
      */
     public static final int PAGE_START = 19;
@@ -134,7 +134,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the end of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTH for horizontal
+     * {@code ComponentOrientation}.  Equal to SOUTH for horizontal
      * orientations.
      */
     public static final int PAGE_END = 20;
@@ -142,7 +142,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to WEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to WEST for horizontal,
      * left-to-right orientations and EAST for horizontal, right-to-left
      * orientations.
      */
@@ -151,7 +151,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to EAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to EAST for horizontal,
      * left-to-right orientations and WEST for horizontal, right-to-left
      * orientations.
      */
@@ -160,7 +160,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHWEST for horizontal,
      * left-to-right orientations and NORTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -169,7 +169,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHEAST for horizontal,
      * left-to-right orientations and NORTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -178,7 +178,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally start for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHWEST for horizontal,
      * left-to-right orientations and SOUTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -187,7 +187,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHEAST for horizontal,
      * left-to-right orientations and SOUTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -437,7 +437,7 @@
      * <code>LINE_START</code>, <code>LINE_END</code>,
      * <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>,
      * <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>.  The
-     * baseline relvative values are:
+     * baseline relative values are:
      * <code>BASELINE</code>, <code>BASELINE_LEADING</code>,
      * <code>BASELINE_TRAILING</code>,
      * <code>ABOVE_BASELINE</code>, <code>ABOVE_BASELINE_LEADING</code>,
--- a/jdk/src/share/classes/java/awt/LinearGradientPaint.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/LinearGradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -26,10 +26,10 @@
 package java.awt;
 
 import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code LinearGradientPaint} class provides a way to fill
@@ -271,6 +271,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public LinearGradientPaint(Point2D start, Point2D end,
                                float[] fractions, Color[] colors,
                                CycleMethod cycleMethod,
--- a/jdk/src/share/classes/java/awt/RadialGradientPaint.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/RadialGradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -29,6 +29,7 @@
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code RadialGradientPaint} class provides a way to fill a shape with
@@ -428,6 +429,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "centerPoint", "radius", "focusPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public RadialGradientPaint(Point2D center,
                                float radius,
                                Point2D focus,
--- a/jdk/src/share/classes/java/awt/Scrollbar.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/Scrollbar.java	Tue Nov 09 22:53:18 2010 -0800
@@ -213,7 +213,8 @@
      * The size of the <code>Scrollbar</code>'s bubble.
      * When a scroll bar is used to select a range of values,
      * the visibleAmount represents the size of this range.
-     * This is visually indicated by the size of the bubble.
+     * Depending on platform, this may be visually indicated
+     * by the size of the bubble.
      *
      * @serial
      * @see #getVisibleAmount
@@ -637,6 +638,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
@@ -670,6 +673,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
--- a/jdk/src/share/classes/java/awt/Toolkit.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/Toolkit.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1831,7 +1831,11 @@
             desktopProperties.put(name, newValue);
         }
 
-        desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        // Don't fire change event if old and new values are null.
+        // It helps to avoid recursive resending of WM_THEMECHANGED
+        if (oldValue != null || newValue != null) {
+            desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -26,6 +26,7 @@
 package java.awt.geom;
 
 import java.awt.Shape;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>AffineTransform</code> class represents a 2D affine transform
@@ -508,6 +509,7 @@
      * @param m12 the Y coordinate translation element of the 3x3 matrix
      * @since 1.2
      */
+    @ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
     public AffineTransform(float m00, float m10,
                            float m01, float m11,
                            float m02, float m12) {
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -265,7 +265,7 @@
      * object currently being deserialized and descriptor for current class.
      * Null when not during readObject upcall.
      */
-    private CallbackContext curContext;
+    private SerialCallbackContext curContext;
 
     /**
      * Creates an ObjectInputStream that reads from the specified InputStream.
@@ -1798,7 +1798,7 @@
     private void readExternalData(Externalizable obj, ObjectStreamClass desc)
         throws IOException
     {
-        CallbackContext oldContext = curContext;
+        SerialCallbackContext oldContext = curContext;
         curContext = null;
         try {
             boolean blocked = desc.hasBlockExternalData();
@@ -1857,10 +1857,10 @@
                     slotDesc.hasReadObjectMethod() &&
                     handles.lookupException(passHandle) == null)
                 {
-                    CallbackContext oldContext = curContext;
+                    SerialCallbackContext oldContext = curContext;
 
                     try {
-                        curContext = new CallbackContext(obj, slotDesc);
+                        curContext = new SerialCallbackContext(obj, slotDesc);
 
                         bin.setBlockDataMode(true);
                         slotDesc.invokeReadObject(obj, this);
@@ -3505,42 +3505,4 @@
         }
     }
 
-    /**
-     * Context that during upcalls to class-defined readObject methods; holds
-     * object currently being deserialized and descriptor for current class.
-     * This context keeps a boolean state to indicate that defaultReadObject
-     * or readFields has already been invoked with this context or the class's
-     * readObject method has returned; if true, the getObj method throws
-     * NotActiveException.
-     */
-    private static class CallbackContext {
-        private final Object obj;
-        private final ObjectStreamClass desc;
-        private final AtomicBoolean used = new AtomicBoolean();
-
-        public CallbackContext(Object obj, ObjectStreamClass desc) {
-            this.obj = obj;
-            this.desc = desc;
-        }
-
-        public Object getObj() throws NotActiveException {
-            checkAndSetUsed();
-            return obj;
-        }
-
-        public ObjectStreamClass getDesc() {
-            return desc;
-        }
-
-        private void checkAndSetUsed() throws NotActiveException {
-            if (!used.compareAndSet(false, true)) {
-                 throw new NotActiveException(
-                      "not in readObject invocation or fields already read");
-            }
-        }
-
-        public void setUsed() {
-            used.set(true);
-        }
-    }
 }
--- a/jdk/src/share/classes/java/io/ObjectOutputStream.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -35,6 +35,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
+import java.io.SerialCallbackContext;
 
 /**
  * An ObjectOutputStream writes primitive data types and graphs of Java objects
@@ -191,10 +192,12 @@
     private boolean enableReplace;
 
     // values below valid only during upcalls to writeObject()/writeExternal()
-    /** object currently being serialized */
-    private Object curObj;
-    /** descriptor for current class (null if in writeExternal()) */
-    private ObjectStreamClass curDesc;
+    /**
+     * Context during upcalls to class-defined writeObject methods; holds
+     * object currently being serialized and descriptor for current class.
+     * Null when not during writeObject upcall.
+     */
+    private SerialCallbackContext curContext;
     /** current PutField object */
     private PutFieldImpl curPut;
 
@@ -426,9 +429,11 @@
      *          <code>OutputStream</code>
      */
     public void defaultWriteObject() throws IOException {
-        if (curObj == null || curDesc == null) {
+        if ( curContext == null ) {
             throw new NotActiveException("not in call to writeObject");
         }
+        Object curObj = curContext.getObj();
+        ObjectStreamClass curDesc = curContext.getDesc();
         bout.setBlockDataMode(false);
         defaultWriteFields(curObj, curDesc);
         bout.setBlockDataMode(true);
@@ -446,9 +451,11 @@
      */
     public ObjectOutputStream.PutField putFields() throws IOException {
         if (curPut == null) {
-            if (curObj == null || curDesc == null) {
+            if (curContext == null) {
                 throw new NotActiveException("not in call to writeObject");
             }
+            Object curObj = curContext.getObj();
+            ObjectStreamClass curDesc = curContext.getDesc();
             curPut = new PutFieldImpl(curDesc);
         }
         return curPut;
@@ -1420,17 +1427,15 @@
      * writeExternal() method.
      */
     private void writeExternalData(Externalizable obj) throws IOException {
-        Object oldObj = curObj;
-        ObjectStreamClass oldDesc = curDesc;
         PutFieldImpl oldPut = curPut;
-        curObj = obj;
-        curDesc = null;
         curPut = null;
 
         if (extendedDebugInfo) {
             debugInfoStack.push("writeExternal data");
         }
+        SerialCallbackContext oldContext = curContext;
         try {
+            curContext = null;
             if (protocol == PROTOCOL_VERSION_1) {
                 obj.writeExternal(this);
             } else {
@@ -1440,13 +1445,12 @@
                 bout.writeByte(TC_ENDBLOCKDATA);
             }
         } finally {
+            curContext = oldContext;
             if (extendedDebugInfo) {
                 debugInfoStack.pop();
             }
         }
 
-        curObj = oldObj;
-        curDesc = oldDesc;
         curPut = oldPut;
     }
 
@@ -1461,12 +1465,9 @@
         for (int i = 0; i < slots.length; i++) {
             ObjectStreamClass slotDesc = slots[i].desc;
             if (slotDesc.hasWriteObjectMethod()) {
-                Object oldObj = curObj;
-                ObjectStreamClass oldDesc = curDesc;
                 PutFieldImpl oldPut = curPut;
-                curObj = obj;
-                curDesc = slotDesc;
                 curPut = null;
+                SerialCallbackContext oldContext = curContext;
 
                 if (extendedDebugInfo) {
                     debugInfoStack.push(
@@ -1474,18 +1475,19 @@
                         slotDesc.getName() + "\")");
                 }
                 try {
+                    curContext = new SerialCallbackContext(obj, slotDesc);
                     bout.setBlockDataMode(true);
                     slotDesc.invokeWriteObject(obj, this);
                     bout.setBlockDataMode(false);
                     bout.writeByte(TC_ENDBLOCKDATA);
                 } finally {
+                    curContext.setUsed();
+                    curContext = oldContext;
                     if (extendedDebugInfo) {
                         debugInfoStack.pop();
                     }
                 }
 
-                curObj = oldObj;
-                curDesc = oldDesc;
                 curPut = oldPut;
             } else {
                 defaultWriteFields(obj, slotDesc);
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -1830,8 +1830,10 @@
         private final ObjectStreamField[] fields;
         /** number of primitive fields */
         private final int numPrimFields;
-        /** unsafe field keys */
-        private final long[] keys;
+        /** unsafe field keys for reading fields - may contain dupes */
+        private final long[] readKeys;
+        /** unsafe fields keys for writing fields - no dupes */
+        private final long[] writeKeys;
         /** field data offsets */
         private final int[] offsets;
         /** field type codes */
@@ -1849,16 +1851,22 @@
         FieldReflector(ObjectStreamField[] fields) {
             this.fields = fields;
             int nfields = fields.length;
-            keys = new long[nfields];
+            readKeys = new long[nfields];
+            writeKeys = new long[nfields];
             offsets = new int[nfields];
             typeCodes = new char[nfields];
             ArrayList<Class<?>> typeList = new ArrayList<Class<?>>();
+            Set<Long> usedKeys = new HashSet<Long>();
+
 
             for (int i = 0; i < nfields; i++) {
                 ObjectStreamField f = fields[i];
                 Field rf = f.getField();
-                keys[i] = (rf != null) ?
+                long key = (rf != null) ?
                     unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
+                readKeys[i] = key;
+                writeKeys[i] = usedKeys.add(key) ?
+                    key : Unsafe.INVALID_FIELD_OFFSET;
                 offsets[i] = f.getOffset();
                 typeCodes[i] = f.getTypeCode();
                 if (!f.isPrimitive()) {
@@ -1894,7 +1902,7 @@
              * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
              */
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = readKeys[i];
                 int off = offsets[i];
                 switch (typeCodes[i]) {
                     case 'Z':
@@ -1945,7 +1953,7 @@
                 throw new NullPointerException();
             }
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
@@ -2006,7 +2014,7 @@
                 switch (typeCodes[i]) {
                     case 'L':
                     case '[':
-                        vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
+                        vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
                         break;
 
                     default:
@@ -2027,7 +2035,7 @@
                 throw new NullPointerException();
             }
             for (int i = numPrimFields; i < fields.length; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/io/SerialCallbackContext.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,58 @@
+  /*
+   * %W% %E%
+   *
+   * Copyright (c) 2006, 2010  Oracle and/or its affiliates. All rights reserved.
+   * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+   */
+
+  package java.io;
+
+  /**
+   * Context during upcalls from object stream to class-defined
+   * readObject/writeObject methods.
+   * Holds object currently being deserialized and descriptor for current class.
+   *
+   * This context keeps track of the thread it was constructed on, and allows
+   * only a single call of defaultReadObject, readFields, defaultWriteObject
+   * or writeFields which must be invoked on the same thread before the class's
+   * readObject/writeObject method has returned.
+   * If not set to the current thread, the getObj method throws NotActiveException.
+   */
+  final class SerialCallbackContext {
+      private final Object obj;
+      private final ObjectStreamClass desc;
+      /**
+       * Thread this context is in use by.
+       * As this only works in one thread, we do not need to worry about thread-safety.
+       */
+      private Thread thread;
+
+      public SerialCallbackContext(Object obj, ObjectStreamClass desc) {
+          this.obj = obj;
+          this.desc = desc;
+          this.thread = Thread.currentThread();
+      }
+
+      public Object getObj() throws NotActiveException {
+          checkAndSetUsed();
+          return obj;
+      }
+
+      public ObjectStreamClass getDesc() {
+          return desc;
+      }
+
+      private void checkAndSetUsed() throws NotActiveException {
+          if (thread != Thread.currentThread()) {
+               throw new NotActiveException(
+                "not in readObject invocation or fields already read");
+          }
+          thread = null;
+      }
+
+      public void setUsed() {
+          thread = null;
+      }
+  }
+
+
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -100,7 +100,8 @@
      * @param   minimumCapacity   the minimum desired capacity.
      */
     public void ensureCapacity(int minimumCapacity) {
-        ensureCapacityInternal(minimumCapacity);
+        if (minimumCapacity > 0)
+            ensureCapacityInternal(minimumCapacity);
     }
 
     /**
@@ -108,6 +109,7 @@
      * never synchronized.
      */
     private void ensureCapacityInternal(int minimumCapacity) {
+        // overflow-conscious code
         if (minimumCapacity - value.length > 0)
             expandCapacity(minimumCapacity);
     }
--- a/jdk/src/share/classes/java/lang/ClassLoader.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java	Tue Nov 09 22:53:18 2010 -0800
@@ -553,6 +553,13 @@
      *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
      *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
      *
+     * @throws  SecurityException
+     *          If an attempt is made to add this class to a package that
+     *          contains classes that were signed by a different set of
+     *          certificates than this class, or if an attempt is made
+     *          to define a class in a package with a fully-qualified name
+     *          that starts with "{@code java.}".
+     *
      * @see  #loadClass(String, boolean)
      * @see  #resolveClass(Class)
      *
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -28,9 +28,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.InterruptedIOException;
 import java.io.FileDescriptor;
-import java.io.ByteArrayOutputStream;
 
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
@@ -58,7 +56,7 @@
     protected int fdUseCount = 0;
 
     /* lock when increment/decrementing fdUseCount */
-    protected Object fdLock = new Object();
+    protected final Object fdLock = new Object();
 
     /* indicates a close is pending on the file descriptor */
     protected boolean closePending = false;
@@ -68,7 +66,7 @@
     private int CONNECTION_RESET_PENDING = 1;
     private int CONNECTION_RESET = 2;
     private int resetState;
-    private Object resetLock = new Object();
+    private final Object resetLock = new Object();
 
     /**
      * Load net library into runtime.
@@ -100,25 +98,24 @@
     protected void connect(String host, int port)
         throws UnknownHostException, IOException
     {
-        IOException pending = null;
+        boolean connected = false;
         try {
             InetAddress address = InetAddress.getByName(host);
             this.port = port;
             this.address = address;
 
-            try {
-                connectToAddress(address, port, timeout);
-                return;
-            } catch (IOException e) {
-                pending = e;
+            connectToAddress(address, port, timeout);
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
             }
-        } catch (UnknownHostException e) {
-            pending = e;
         }
-
-        // everything failed
-        close();
-        throw pending;
     }
 
     /**
@@ -151,22 +148,29 @@
      *          SocketAddress subclass not supported by this socket
      * @since 1.4
      */
-    protected void connect(SocketAddress address, int timeout) throws IOException {
-        if (address == null || !(address instanceof InetSocketAddress))
-            throw new IllegalArgumentException("unsupported address type");
-        InetSocketAddress addr = (InetSocketAddress) address;
-        if (addr.isUnresolved())
-            throw new UnknownHostException(addr.getHostName());
-        this.port = addr.getPort();
-        this.address = addr.getAddress();
+    protected void connect(SocketAddress address, int timeout)
+            throws IOException {
+        boolean connected = false;
+        try {
+            if (address == null || !(address instanceof InetSocketAddress))
+                throw new IllegalArgumentException("unsupported address type");
+            InetSocketAddress addr = (InetSocketAddress) address;
+            if (addr.isUnresolved())
+                throw new UnknownHostException(addr.getHostName());
+            this.port = addr.getPort();
+            this.address = addr.getAddress();
 
-        try {
             connectToAddress(this.address, port, timeout);
-            return;
-        } catch (IOException e) {
-            // everything failed
-            close();
-            throw e;
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
+            }
         }
     }
 
@@ -311,7 +315,7 @@
             }
         }
         try {
-            FileDescriptor fd = acquireFD();
+            acquireFD();
             try {
                 socketConnect(address, port, timeout);
                 /* socket may have been closed during poll/select */
@@ -370,7 +374,7 @@
      * @param s the connection
      */
     protected void accept(SocketImpl s) throws IOException {
-        FileDescriptor fd = acquireFD();
+        acquireFD();
         try {
             socketAccept(s);
         } finally {
@@ -562,7 +566,6 @@
         close();
     }
 
-
     /*
      * "Acquires" and returns the FileDescriptor for this impl
      *
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Nov 09 22:53:18 2010 -0800
@@ -27,6 +27,7 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Cleaner;
 import sun.misc.Unsafe;
 import sun.misc.VM;
@@ -114,7 +115,7 @@
     //
     Direct$Type$Buffer$RW$(int cap) {                   // package-private
 #if[rw]
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
         boolean pa = VM.isDirectMemoryPageAligned();
         int ps = Bits.pageSize();
         long size = Math.max(1L, (long)cap + (pa ? ps : 0));
@@ -145,7 +146,7 @@
     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
     //
     private Direct$Type$Buffer(long addr, int cap) {
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
         address = addr;
         cleaner = null;
     }
@@ -154,14 +155,17 @@
 
     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
     //
-    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+    protected Direct$Type$Buffer$RW$(int cap, long addr,
+                                     FileDescriptor fd,
+                                     Runnable unmapper)
+    {
 #if[rw]
-        super(-1, 0, cap, cap, true);
+        super(-1, 0, cap, cap, fd);
         address = addr;
         viewedBuffer = null;
         cleaner = Cleaner.create(this, unmapper);
 #else[rw]
-        super(cap, addr, unmapper);
+        super(cap, addr, fd, unmapper);
 #end[rw]
     }
 
--- a/jdk/src/share/classes/java/nio/MappedByteBuffer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/nio/MappedByteBuffer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,6 +25,7 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Unsafe;
 
 
@@ -71,26 +72,26 @@
     // for optimization purposes, it's easier to do it the other way around.
     // This works because DirectByteBuffer is a package-private class.
 
-    // Volatile to make sure that the finalization thread sees the current
-    // value of this so that a region is not accidentally unmapped again later.
-    volatile boolean isAMappedBuffer;                   // package-private
+    // For mapped buffers, a FileDescriptor that may be used for mapping
+    // operations if valid; null if the buffer is not mapped.
+    private final FileDescriptor fd;
 
     // This should only be invoked by the DirectByteBuffer constructors
     //
     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
-                     boolean mapped)
+                     FileDescriptor fd)
     {
         super(mark, pos, lim, cap);
-        isAMappedBuffer = mapped;
+        this.fd = fd;
     }
 
     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
         super(mark, pos, lim, cap);
-        isAMappedBuffer = false;
+        this.fd = null;
     }
 
     private void checkMapped() {
-        if (!isAMappedBuffer)
+        if (fd == null)
             // Can only happen if a luser explicitly casts a direct byte buffer
             throw new UnsupportedOperationException();
     }
@@ -191,13 +192,12 @@
         checkMapped();
         if ((address != 0) && (capacity() != 0)) {
             long offset = mappingOffset();
-            force0(mappingAddress(offset), mappingLength(offset));
+            force0(fd, mappingAddress(offset), mappingLength(offset));
         }
         return this;
     }
 
     private native boolean isLoaded0(long address, long length, int pageCount);
     private native void load0(long address, long length);
-    private native void force0(long address, long length);
-
+    private native void force0(FileDescriptor fd, long address, long length);
 }
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Tue Nov 09 11:45:00 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-/*
- * Copyright (c) 2007, 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 java.nio.channels;
-
-import java.nio.channels.spi.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.Future;
-import java.io.IOException;
-import java.net.SocketOption;
-import java.net.SocketAddress;
-import java.net.ProtocolFamily;
-import java.nio.ByteBuffer;
-
-/**
- * An asynchronous channel for datagram-oriented sockets.
- *
- * <p> An asynchronous datagram channel is created by invoking one of the {@link
- * #open open} methods defined by this class. It is not possible to create a channel
- * for an arbitrary, pre-existing datagram socket. A newly-created asynchronous
- * datagram channel is open but not connected. It need not be connected in order
- * for the {@link #send send} and {@link #receive receive} methods to be used.
- * A datagram channel may be connected, by invoking its {@link #connect connect}
- * method, in order to avoid the overhead of the security checks that are otherwise
- * performed as part of every send and receive operation when a security manager
- * is set. The channel must be connected in order to use the {@link #read read}
- * and {@link #write write} methods, since those methods do not accept or return
- * socket addresses. Once connected, an asynchronous datagram channel remains
- * connected until it is disconnected or closed.
- *
- * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
- * setOption} method. An asynchronous datagram channel to an Internet Protocol
- * (IP) socket supports the following options:
- * <blockquote>
- * <table border>
- *   <tr>
- *     <th>Option Name</th>
- *     <th>Description</th>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
- *     <td> The size of the socket send buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
- *     <td> The size of the socket receive buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
- *     <td> Re-use address </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
- *     <td> Allow transmission of broadcast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
- *     <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
- *     <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
- *       IP_MULTICAST_TTL} </td>
- *     <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
- *       datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
- *       IP_MULTICAST_LOOP} </td>
- *     <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- * </table>
- * </blockquote>
- * Additional (implementation specific) options may also be supported.
- *
- * <p> Asynchronous datagram channels allow more than one read/receive and
- * write/send to be oustanding at any given time.
- *
- * <p> <b>Usage Example:</b>
- * <pre>
- *  final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
- *      .bind(new InetSocketAddress(4000));
- *
- *  // print the source address of all packets that we receive
- *  dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
- *      public void completed(SocketAddress sa, ByteBuffer buffer) {
- *          System.out.println(sa);
- *          buffer.clear();
- *          dc.receive(buffer, buffer, this);
- *      }
- *      public void failed(Throwable exc, ByteBuffer buffer) {
- *          ...
- *      }
- *  });
- * </pre>
- *
- * @since 1.7
- */
-
-public abstract class AsynchronousDatagramChannel
-    implements AsynchronousByteChannel, MulticastChannel
-{
-    private final AsynchronousChannelProvider provider;
-
-    /**
-     * Initializes a new instance of this class.
-     */
-    protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) {
-        this.provider = provider;
-    }
-
-    /**
-     * Returns the provider that created this channel.
-     */
-    public final AsynchronousChannelProvider provider() {
-        return provider;
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> The new channel is created by invoking the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel
-     * openAsynchronousDatagramChannel} method on the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
-     * the given group (or the default provider where {@code group} is {@code
-     * null}).
-     *
-     * <p> The {@code family} parameter is used to specify the {@link ProtocolFamily}.
-     * If the datagram channel is to be used for Internet Protocol {@link
-     * MulticastChannel multicasting} then this parameter should correspond to
-     * the address type of the multicast groups that this channel will join.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} to use the default protocol
-     *          family
-     * @param   group
-     *          The group to which the newly constructed channel should be bound,
-     *          or {@code null} for the default group
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  UnsupportedOperationException
-     *          If the specified protocol family is not supported. For example,
-     *          suppose the parameter is specified as {@link
-     *          java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not
-     *          enabled on the platform.
-     * @throws  ShutdownChannelGroupException
-     *          The specified group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open(ProtocolFamily family,
-                                                   AsynchronousChannelGroup group)
-        throws IOException
-    {
-        AsynchronousChannelProvider provider = (group == null) ?
-            AsynchronousChannelProvider.provider() : group.provider();
-        return provider.openAsynchronousDatagramChannel(family, group);
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> This method returns an asynchronous datagram channel that is
-     * bound to the <em>default group</em>. This method is equivalent to evaluating
-     * the expression:
-     * <blockquote><pre>
-     * open((ProtocolFamily)null,&nbsp;(AsynchronousChannelGroup)null);
-     * </pre></blockquote>
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open()
-        throws IOException
-    {
-        return open(null, null);
-    }
-
-    // -- Socket-specific operations --
-
-    /**
-     * @throws  AlreadyBoundException               {@inheritDoc}
-     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
-     * @throws  ClosedChannelException              {@inheritDoc}
-     * @throws  IOException                         {@inheritDoc}
-     * @throws  SecurityException
-     *          If a security manager has been installed and its {@link
-     *          SecurityManager#checkListen checkListen} method denies the
-     *          operation
-     */
-    @Override
-    public abstract AsynchronousDatagramChannel bind(SocketAddress local)
-        throws IOException;
-
-    /**
-     * @throws  IllegalArgumentException                {@inheritDoc}
-     * @throws  ClosedChannelException                  {@inheritDoc}
-     * @throws  IOException                             {@inheritDoc}
-     */
-    @Override
-    public abstract <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
-        throws IOException;
-
-    /**
-     * Returns the remote address to which this channel is connected.
-     *
-     * <p> Where the channel is connected to an Internet Protocol socket address
-     * then the return value from this method is of type {@link
-     * java.net.InetSocketAddress}.
-     *
-     * @return  The remote address; {@code null} if the channel's socket is not
-     *          connected
-     *
-     * @throws  ClosedChannelException
-     *          If the channel is closed
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract SocketAddress getRemoteAddress() throws IOException;
-
-    /**
-     * Connects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it only receives
-     * datagrams from, and sends datagrams to, the given remote <i>peer</i>
-     * address.  Once connected, datagrams may not be received from or sent to
-     * any other address.  A datagram socket remains connected until it is
-     * explicitly disconnected or until it is closed.
-     *
-     * <p> This method performs exactly the same security checks as the {@link
-     * java.net.DatagramSocket#connect connect} method of the {@link
-     * java.net.DatagramSocket} class.  That is, if a security manager has been
-     * installed then this method verifies that its {@link
-     * java.lang.SecurityManager#checkAccept checkAccept} and {@link
-     * java.lang.SecurityManager#checkConnect checkConnect} methods permit
-     * datagrams to be received from and sent to, respectively, the given
-     * remote address.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @param  remote
-     *         The remote address to which this channel is to be connected
-     *
-     * @return  This datagram channel
-     *
-     * @throws  ClosedChannelException
-     *          If this channel is closed
-     *
-     * @throws  SecurityException
-     *          If a security manager has been installed
-     *          and it does not permit access to the given remote address
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel connect(SocketAddress remote)
-        throws IOException;
-
-    /**
-     * Disconnects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it can receive datagrams
-     * from, and sends datagrams to, any remote address so long as the security
-     * manager, if installed, permits it.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @return  This datagram channel
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel disconnect() throws IOException;
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> The datagram is transferred into the given byte buffer starting at
-     * its current position, as if by a regular {@link AsynchronousByteChannel#read
-     * read} operation. If there are fewer bytes remaining in the buffer
-     * than are required to hold the datagram then the remainder of the datagram
-     * is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * <p> When a security manager has been installed and the channel is not
-     * connected, then it verifies that the source's address and port number are
-     * permitted by the security manager's {@link SecurityManager#checkAccept
-     * checkAccept} method. The permission check is performed with privileges that
-     * are restricted by the calling context of this method. If the permission
-     * check fails then the operation completes with a {@link SecurityException}.
-     * The overhead of this security check can be avoided by first connecting the
-     * socket via the {@link #connect connect} method.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void receive(ByteBuffer dst,
-                                     long timeout,
-                                     TimeUnit unit,
-                                     A attachment,
-                                     CompletionHandler<SocketAddress,? super A> handler);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
-     * timeout of {@code 0L}.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public final <A> void receive(ByteBuffer dst,
-                                  A attachment,
-                                  CompletionHandler<SocketAddress,? super A> handler)
-    {
-        receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The method behaves in exactly the same manner as the {@link
-     * #receive(ByteBuffer,Object,CompletionHandler)
-     * receive(ByteBuffer,Object,CompletionHandler)} method except that instead
-     * of specifying a completion handler, this method returns a {@code Future}
-     * representing the pending result. The {@code Future}'s {@link Future#get()
-     * get} method returns the datagram's source address.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     */
-    public abstract Future<SocketAddress> receive(ByteBuffer dst);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The {@code handler} parameter is a completion handler
-     * that is invoked when the send completes (or fails). The result passed to
-     * the completion handler is the number of bytes sent.
-     *
-     * <p> Otherwise this method works in the same manner as the {@link
-     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
-     * method.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void send(ByteBuffer src,
-                                  SocketAddress target,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The method behaves in exactly the same manner as the
-     * {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
-     * send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
-     * that instead of specifying a completion handler, this method returns a
-     * {@code Future} representing the pending result. The {@code Future}'s
-     * {@link Future#get() get} method returns the number of bytes sent.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     */
-    public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is number of bytes read.
-     *
-     * <p> This method may only be invoked if this channel is connected, and it
-     * only accepts datagrams from the peer that the channel is connected too.
-     * The datagram is transferred into the given byte buffer starting at
-     * its current position and exactly as specified in the {@link
-     * AsynchronousByteChannel} interface. If there are fewer bytes
-     * remaining in the buffer than are required to hold the datagram then the
-     * remainder of the datagram is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or buffer is read-only
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void read(ByteBuffer dst,
-                                  long timeout,
-                                  TimeUnit unit,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public final <A> void read(ByteBuffer dst,
-                               A attachment,
-                               CompletionHandler<Integer,? super A> handler)
-    {
-        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> read(ByteBuffer dst);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract <A> void  write(ByteBuffer src,
-                                    A attachment,
-                                    CompletionHandler<Integer,? super A> handler);
-
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> write(ByteBuffer src);
-}
--- a/jdk/src/share/classes/java/nio/channels/package-info.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/nio/channels/package-info.java	Tue Nov 09 22:53:18 2010 -0800
@@ -232,8 +232,6 @@
  *     <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
  *     <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
- * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousDatagramChannel}</tt></td>
- *     <td>An asynchronous channel to a datagram-oriented socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td>
  *     <td>A handler for consuming the result of an asynchronous operation</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td>
--- a/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Tue Nov 09 22:53:18 2010 -0800
@@ -26,7 +26,6 @@
 package java.nio.channels.spi;
 
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.ServiceLoader;
@@ -239,26 +238,4 @@
      */
     public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
         (AsynchronousChannelGroup group) throws IOException;
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} for the default protocol
-     *          family
-     * @param   group
-     *          The group to which the channel is bound, or {@code null} to
-     *          bind to the default group
-     *
-     * @return  The new channel
-     *
-     * @throws  IllegalChannelGroupException
-     *          If the provider that created the group differs from this provider
-     * @throws  ShutdownChannelGroupException
-     *          The group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/AlgorithmConstraints.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 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 java.security;
+
+import java.util.Set;
+
+/**
+ * This interface specifies constraints for cryptographic algorithms,
+ * keys (key sizes), and other algorithm parameters.
+ * <p>
+ * {@code AlgorithmConstraints} objects are immutable.  An implementation
+ * of this interface should not provide methods that can change the state
+ * of an instance once it has been created.
+ * <p>
+ * Note that {@code AlgorithmConstraints} can be used to represent the
+ * restrictions described by the security properties
+ * {@code jdk.certpath.disabledAlgorithms} and
+ * {@code jdk.tls.disabledAlgorithms}, or could be used by a
+ * concrete {@code PKIXCertPathChecker} to check whether a specified
+ * certificate in the certification path contains the required algorithm
+ * constraints.
+ *
+ * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
+ * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+ *
+ * @since 1.7
+ */
+
+public interface AlgorithmConstraints {
+
+    /**
+     * Determines whether an algorithm is granted permission for the
+     * specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the algorithm is permitted and can be used for all
+     *     of the specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters);
+
+    /**
+     * Determines whether a key is granted permission for the specified
+     * cryptographic primitives.
+     * <p>
+     * This method is usually used to check key size and key usage.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param key the key
+     *
+     * @return true if the key can be used for all of the specified
+     *     cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives is null or empty,
+     *     or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives, Key key);
+
+    /**
+     * Determines whether an algorithm and the corresponding key are granted
+     * permission for the specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the key and the algorithm can be used for all of the
+     *     specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty, or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, Key key, AlgorithmParameters parameters);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/CryptoPrimitive.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 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 java.security;
+
+/**
+ * An enumeration of cryptographic primitives.
+ *
+ * @since 1.7
+ */
+public enum CryptoPrimitive {
+    /**
+     * Hash function
+     */
+    MESSAGE_DIGEST,
+
+    /**
+     * Cryptographic random number generator
+     */
+    SECURE_RANDOM,
+
+    /**
+     * Symmetric primitive: block cipher
+     */
+    BLOCK_CIPHER,
+
+    /**
+     * Symmetric primitive: stream cipher
+     */
+    STREAM_CIPHER,
+
+    /**
+     * Symmetric primitive: message authentication code
+     */
+    MAC,
+
+    /**
+     * Symmetric primitive: key wrap
+     */
+    KEY_WRAP,
+
+    /**
+     * Asymmetric primitive: public key encryption
+     */
+    PUBLIC_KEY_ENCRYPTION,
+
+    /**
+     * Asymmetric primitive: signature scheme
+     */
+    SIGNATURE,
+
+    /**
+     * Asymmetric primitive: key encapsulation mechanism
+     */
+    KEY_ENCAPSULATION,
+
+    /**
+     * Asymmetric primitive: key agreement and key distribution
+     */
+    KEY_AGREEMENT
+}
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java	Tue Nov 09 22:53:18 2010 -0800
@@ -44,11 +44,12 @@
 import java.lang.ref.SoftReference;
 import java.text.spi.DateFormatSymbolsProvider;
 import java.util.Arrays;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.spi.LocaleServiceProvider;
 import sun.util.LocaleServiceProviderPool;
 import sun.util.TimeZoneNameUtility;
@@ -321,20 +322,64 @@
      * @since 1.6
      */
     public static final DateFormatSymbols getInstance(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return (DateFormatSymbols) getCachedInstance(locale).clone();
+    }
+
+    /**
+     * Returns a DateFormatSymbols provided by a provider or found in
+     * the cache. Note that this method returns a cached instance,
+     * not its clone. Therefore, the instance should never be given to
+     * an application.
+     */
+    static final DateFormatSymbols getInstanceRef(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return getCachedInstance(locale);
+    }
+
+    private static DateFormatSymbols getProviderInstance(Locale locale) {
+        DateFormatSymbols providersInstance = null;
 
         // Check whether a provider can provide an implementation that's closer
         // to the requested locale than what the Java runtime itself can provide.
         LocaleServiceProviderPool pool =
             LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
         if (pool.hasProviders()) {
-            DateFormatSymbols providersInstance = pool.getLocalizedObject(
-                                DateFormatSymbolsGetter.INSTANCE, locale);
-            if (providersInstance != null) {
-                return providersInstance;
+            providersInstance = pool.getLocalizedObject(
+                                    DateFormatSymbolsGetter.INSTANCE, locale);
+        }
+        return providersInstance;
+    }
+
+    /**
+     * Returns a cached DateFormatSymbols if it's found in the
+     * cache. Otherwise, this method returns a newly cached instance
+     * for the given locale.
+     */
+    private static DateFormatSymbols getCachedInstance(Locale locale) {
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs = null;
+        if (ref == null || (dfs = ref.get()) == null) {
+            dfs = new DateFormatSymbols(locale);
+            ref = new SoftReference<DateFormatSymbols>(dfs);
+            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
+            if (x != null) {
+                DateFormatSymbols y = x.get();
+                if (y != null) {
+                    dfs = y;
+                } else {
+                    // Replace the empty SoftReference with ref.
+                    cachedInstances.put(locale, ref);
+                }
             }
         }
-
-        return new DateFormatSymbols(locale);
+        return dfs;
     }
 
     /**
@@ -597,56 +642,44 @@
     static final int millisPerHour = 60*60*1000;
 
     /**
-     * Cache to hold the FormatData and TimeZoneNames ResourceBundles
-     * of a Locale.
-     */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
-
-    /**
-     * Look up resource data for the desiredLocale in the cache; update the
-     * cache if necessary.
+     * Cache to hold DateFormatSymbols instances per Locale.
      */
-    private static ResourceBundle cacheLookup(Locale desiredLocale) {
-        ResourceBundle rb;
-        SoftReference data
-            = (SoftReference)cachedLocaleData.get(desiredLocale);
-        if (data == null) {
-            rb = LocaleData.getDateFormatData(desiredLocale);
-            data = new SoftReference(rb);
-            cachedLocaleData.put(desiredLocale, data);
-        } else {
-            if ((rb = (ResourceBundle)data.get()) == null) {
-                rb = LocaleData.getDateFormatData(desiredLocale);
-                data = new SoftReference(rb);
-            }
-        }
-        return rb;
-    }
+    private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
+        = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
 
     private void initializeData(Locale desiredLocale) {
-        int i;
-        ResourceBundle resource = cacheLookup(desiredLocale);
+        locale = desiredLocale;
 
-        // FIXME: cache only ResourceBundle. Hence every time, will do
-        // getObject(). This won't be necessary if the Resource itself
-        // is cached.
-        eras = (String[])resource.getObject("Eras");
+        // Copy values of a cached instance if any.
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs;
+        if (ref != null && (dfs = ref.get()) != null) {
+            copyMembers(dfs, this);
+            return;
+        }
+
+        // Initialize the fields from the ResourceBundle for locale.
+        ResourceBundle resource = LocaleData.getDateFormatData(locale);
+
+        eras = resource.getStringArray("Eras");
         months = resource.getStringArray("MonthNames");
         shortMonths = resource.getStringArray("MonthAbbreviations");
-        String[] lWeekdays = resource.getStringArray("DayNames");
-        weekdays = new String[8];
-        weekdays[0] = "";  // 1-based
-        for (i=0; i<lWeekdays.length; i++)
-            weekdays[i+1] = lWeekdays[i];
-        String[] sWeekdays = resource.getStringArray("DayAbbreviations");
-        shortWeekdays = new String[8];
-        shortWeekdays[0] = "";  // 1-based
-        for (i=0; i<sWeekdays.length; i++)
-            shortWeekdays[i+1] = sWeekdays[i];
         ampms = resource.getStringArray("AmPmMarkers");
         localPatternChars = resource.getString("DateTimePatternChars");
 
-        locale = desiredLocale;
+        // Day of week names are stored in a 1-based array.
+        weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
+        shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
+    }
+
+    private static String[] toOneBasedArray(String[] src) {
+        int len = src.length;
+        String[] dst = new String[len + 1];
+        dst[0] = "";
+        for (int i = 0; i < len; i++) {
+            dst[i + 1] = src[i];
+        }
+        return dst;
     }
 
     /**
--- a/jdk/src/share/classes/java/text/DecimalFormat.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/text/DecimalFormat.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -46,9 +46,10 @@
 import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Currency;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import sun.util.resources.LocaleData;
@@ -394,14 +395,14 @@
     public DecimalFormat() {
         Locale def = Locale.getDefault(Locale.Category.FORMAT);
         // try to get the pattern from the cache
-        String pattern = (String) cachedLocaleData.get(def);
+        String pattern = cachedLocaleData.get(def);
         if (pattern == null) {  /* cache miss */
             // Get the pattern for the default locale.
             ResourceBundle rb = LocaleData.getNumberFormatData(def);
             String[] all = rb.getStringArray("NumberPatterns");
             pattern = all[0];
             /* update cache */
-            cachedLocaleData.put(def, pattern);
+            cachedLocaleData.putIfAbsent(def, pattern);
         }
 
         // Always applyPattern after the symbols are set
@@ -3272,5 +3273,6 @@
     /**
      * Cache to hold the NumberPattern of a Locale.
      */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
+    private static final ConcurrentMap<Locale, String> cachedLocaleData
+        = new ConcurrentHashMap<Locale, String>(3);
 }
--- a/jdk/src/share/classes/java/text/SimpleDateFormat.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java	Tue Nov 09 22:53:18 2010 -0800
@@ -44,13 +44,14 @@
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.calendar.CalendarUtils;
 import sun.util.calendar.ZoneInfoFile;
 import sun.util.resources.LocaleData;
@@ -503,14 +504,14 @@
     /**
      * Cache to hold the DateTimePatterns of a Locale.
      */
-    private static Hashtable<String,String[]> cachedLocaleData
-        = new Hashtable<String,String[]>(3);
+    private static final ConcurrentMap<String, String[]> cachedLocaleData
+        = new ConcurrentHashMap<String, String[]>(3);
 
     /**
      * Cache NumberFormat instances with Locale key.
      */
-    private static Hashtable<Locale,NumberFormat> cachedNumberFormatData
-        = new Hashtable<Locale,NumberFormat>(3);
+    private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
+        = new ConcurrentHashMap<Locale, NumberFormat>(3);
 
     /**
      * The Locale used to instantiate this
@@ -579,7 +580,7 @@
 
         initializeCalendar(locale);
         this.pattern = pattern;
-        this.formatData = DateFormatSymbols.getInstance(locale);
+        this.formatData = DateFormatSymbols.getInstanceRef(locale);
         this.locale = locale;
         initialize(locale);
     }
@@ -632,9 +633,9 @@
                 dateTimePatterns = r.getStringArray("DateTimePatterns");
             }
             /* update cache */
-            cachedLocaleData.put(key, dateTimePatterns);
+            cachedLocaleData.putIfAbsent(key, dateTimePatterns);
         }
-        formatData = DateFormatSymbols.getInstance(loc);
+        formatData = DateFormatSymbols.getInstanceRef(loc);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
             Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
                                      dateTimePatterns[dateStyle + 4]};
@@ -665,7 +666,7 @@
             numberFormat.setGroupingUsed(false);
 
             /* update cache */
-            cachedNumberFormatData.put(loc, numberFormat);
+            cachedNumberFormatData.putIfAbsent(loc, numberFormat);
         }
         numberFormat = (NumberFormat) numberFormat.clone();
 
@@ -897,7 +898,7 @@
      * so we can call it from readObject().
      */
     private void initializeDefaultCentury() {
-        calendar.setTime( new Date() );
+        calendar.setTimeInMillis(System.currentTimeMillis());
         calendar.add( Calendar.YEAR, -80 );
         parseAmbiguousDatesAsAfter(calendar.getTime());
     }
@@ -921,7 +922,7 @@
      * @since 1.2
      */
     public void set2DigitYearStart(Date startDate) {
-        parseAmbiguousDatesAsAfter(startDate);
+        parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
     }
 
     /**
@@ -934,7 +935,7 @@
      * @since 1.2
      */
     public Date get2DigitYearStart() {
-        return defaultCenturyStart;
+        return (Date) defaultCenturyStart.clone();
     }
 
     /**
--- a/jdk/src/share/classes/java/util/ArrayList.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/ArrayList.java	Tue Nov 09 22:53:18 2010 -0800
@@ -176,6 +176,11 @@
      * @param minCapacity the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
+        if (minCapacity > 0)
+            ensureCapacityInternal(minCapacity);
+    }
+
+    private void ensureCapacityInternal(int minCapacity) {
         modCount++;
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
@@ -403,7 +408,7 @@
      * @return <tt>true</tt> (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         elementData[size++] = e;
         return true;
     }
@@ -420,7 +425,7 @@
     public void add(int index, E element) {
         rangeCheckForAdd(index);
 
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         System.arraycopy(elementData, index, elementData, index + 1,
                          size - index);
         elementData[index] = element;
@@ -524,7 +529,7 @@
     public boolean addAll(Collection<? extends E> c) {
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
         System.arraycopy(a, 0, elementData, size, numNew);
         size += numNew;
         return numNew != 0;
@@ -550,7 +555,7 @@
 
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
 
         int numMoved = size - index;
         if (numMoved > 0)
--- a/jdk/src/share/classes/java/util/Calendar.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/Calendar.java	Tue Nov 09 22:53:18 2010 -0800
@@ -51,6 +51,8 @@
 import java.security.ProtectionDomain;
 import java.text.DateFormat;
 import java.text.DateFormatSymbols;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.BuddhistCalendar;
 import sun.util.calendar.ZoneInfo;
 import sun.util.resources.LocaleData;
@@ -837,7 +839,8 @@
      * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
      * of a Locale.
      */
-    private static Hashtable<Locale, int[]> cachedLocaleData = new Hashtable<Locale, int[]>(3);
+    private static final ConcurrentMap<Locale, int[]> cachedLocaleData
+        = new ConcurrentHashMap<Locale, int[]>(3);
 
     // Special values of stamp[]
     /**
@@ -1022,7 +1025,7 @@
             // returns a BuddhistCalendar instance.
             if ("th".equals(aLocale.getLanguage())
                     && ("TH".equals(aLocale.getCountry()))) {
-                    cal = new BuddhistCalendar(zone, aLocale);
+                cal = new BuddhistCalendar(zone, aLocale);
             } else {
                 cal = new GregorianCalendar(zone, aLocale);
             }
@@ -2588,7 +2591,7 @@
             data = new int[2];
             data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
             data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
-            cachedLocaleData.put(desiredLocale, data);
+            cachedLocaleData.putIfAbsent(desiredLocale, data);
         }
         firstDayOfWeek = data[0];
         minimalDaysInFirstWeek = data[1];
--- a/jdk/src/share/classes/java/util/Locale.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/Locale.java	Tue Nov 09 22:53:18 2010 -0800
@@ -758,7 +758,7 @@
     }
 
     private static void initDefault() {
-        String language, region, country, variant;
+        String language, region, script, country, variant;
         language = AccessController.doPrivileged(
             new GetPropertyAction("user.language", "en"));
         // for compatibility, check for old user.region property
@@ -774,43 +774,41 @@
                 country = region;
                 variant = "";
             }
+            script = "";
         } else {
+            script = AccessController.doPrivileged(
+                new GetPropertyAction("user.script", ""));
             country = AccessController.doPrivileged(
                 new GetPropertyAction("user.country", ""));
             variant = AccessController.doPrivileged(
                 new GetPropertyAction("user.variant", ""));
         }
-        defaultLocale = getInstance(language, country, variant);
+        defaultLocale = getInstance(language, script, country, variant, null);
     }
 
     private static void initDefault(Locale.Category category) {
-        String language, region, country, variant;
+        // make sure defaultLocale is initialized
+        if (defaultLocale == null) {
+            initDefault();
+        }
+
+        Locale defaultCategoryLocale = getInstance(
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
+            null);
+
         switch (category) {
         case DISPLAY:
-            language = AccessController.doPrivileged(
-                new GetPropertyAction("user.language.display", ""));
-            if ("".equals(language)) {
-                defaultDisplayLocale = getDefault();
-            } else {
-                country = AccessController.doPrivileged(
-                    new GetPropertyAction("user.country.display", ""));
-                variant = AccessController.doPrivileged(
-                    new GetPropertyAction("user.variant.display", ""));
-                defaultDisplayLocale = getInstance(language, country, variant);
-            }
+            defaultDisplayLocale = defaultCategoryLocale;
             break;
         case FORMAT:
-            language = AccessController.doPrivileged(
-                new GetPropertyAction("user.language.format", ""));
-            if ("".equals(language)) {
-                defaultFormatLocale = getDefault();
-            } else {
-                country = AccessController.doPrivileged(
-                    new GetPropertyAction("user.country.format", ""));
-                variant = AccessController.doPrivileged(
-                    new GetPropertyAction("user.variant.format", ""));
-                defaultFormatLocale = getInstance(language, country, variant);
-            }
+            defaultFormatLocale = defaultCategoryLocale;
             break;
         }
     }
@@ -2124,13 +2122,31 @@
          * Category used to represent the default locale for
          * displaying user interfaces.
          */
-        DISPLAY,
+        DISPLAY("user.language.display",
+                "user.script.display",
+                "user.country.display",
+                "user.variant.display"),
 
         /**
          * Category used to represent the default locale for
          * formatting dates, numbers, and/or currencies.
          */
-        FORMAT,
+        FORMAT("user.language.format",
+               "user.script.format",
+               "user.country.format",
+               "user.variant.format");
+
+        Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
+            this.languageKey = languageKey;
+            this.scriptKey = scriptKey;
+            this.countryKey = countryKey;
+            this.variantKey = variantKey;
+        }
+
+        final String languageKey;
+        final String scriptKey;
+        final String countryKey;
+        final String variantKey;
     }
 
     /**
--- a/jdk/src/share/classes/java/util/TimeZone.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/TimeZone.java	Tue Nov 09 22:53:18 2010 -0800
@@ -160,11 +160,6 @@
     private static final int ONE_HOUR   = 60*ONE_MINUTE;
     private static final int ONE_DAY    = 24*ONE_HOUR;
 
-    /**
-     * Cache to hold the SimpleDateFormat objects for a Locale.
-     */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
-
     // Proclaim serialization compatibility with JDK 1.1
     static final long serialVersionUID = 3581463369166924961L;
 
--- a/jdk/src/share/classes/java/util/Vector.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/Vector.java	Tue Nov 09 22:53:18 2010 -0800
@@ -222,8 +222,10 @@
      * @param minCapacity the desired minimum capacity
      */
     public synchronized void ensureCapacity(int minCapacity) {
-        modCount++;
-        ensureCapacityHelper(minCapacity);
+        if (minCapacity > 0) {
+            modCount++;
+            ensureCapacityHelper(minCapacity);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java	Tue Nov 09 22:53:18 2010 -0800
@@ -529,8 +529,6 @@
         Throwable throwable = new Throwable();
         int depth = access.getStackTraceDepth(throwable);
 
-        String logClassName = "java.util.logging.Logger";
-        String plogClassName = "sun.util.logging.PlatformLogger";
         boolean lookingForLogger = true;
         for (int ix = 0; ix < depth; ix++) {
             // Calling getStackTraceElement directly prevents the VM
@@ -538,13 +536,14 @@
             StackTraceElement frame =
                 access.getStackTraceElement(throwable, ix);
             String cname = frame.getClassName();
+            boolean isLoggerImpl = isLoggerImplFrame(cname);
             if (lookingForLogger) {
                 // Skip all frames until we have found the first logger frame.
-                if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
+                if (isLoggerImpl) {
                     lookingForLogger = false;
                 }
             } else {
-                if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
+                if (!isLoggerImpl) {
                     // skip reflection call
                     if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
                        // We've found the relevant frame.
@@ -558,4 +557,11 @@
         // We haven't found a suitable frame, so just punt.  This is
         // OK as we are only committed to making a "best effort" here.
     }
+
+    private boolean isLoggerImplFrame(String cname) {
+        // the log record could be created for a platform logger
+        return (cname.equals("java.util.logging.Logger") ||
+                cname.startsWith("java.util.logging.LoggingProxyImpl") ||
+                cname.startsWith("sun.util.logging."));
+    }
 }
--- a/jdk/src/share/classes/javax/management/ObjectName.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/management/ObjectName.java	Tue Nov 09 22:53:18 2010 -0800
@@ -211,8 +211,8 @@
  * reverse DNS name of the organization that specifies the MBeans,
  * followed by a period and a string whose interpretation is
  * determined by that organization.  For example, MBeans specified by
- * Sun Microsystems Inc., DNS name <code>sun.com</code>, would have
- * domains such as <code>com.sun.MyDomain</code>.  This is essentially
+ * <code>example.com</code>  would have
+ * domains such as <code>com.example.MyDomain</code>.  This is essentially
  * the same convention as for Java-language package names.</p>
  *
  * <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
--- a/jdk/src/share/classes/javax/management/build.xml	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/management/build.xml	Tue Nov 09 22:53:18 2010 -0800
@@ -35,18 +35,18 @@
      . Please also read the important comment on basedir definition below.
  -->
 
-<project name="JMX API Version 1.4 - Java SE 6 implementation" 
-	 default="jar" 
-	 basedir="../../../../.." 
+<project name="JMX API Version 1.4 - Java SE 6 implementation"
+	 default="jar"
+	 basedir="../../../../.."
 	 >
 
-    <!-- IMPORTANT: BASEDIR DEFINITION  
-         This file is assumed to be in: 
-         <src_bundle_dir>/j2se/src/share/classes/javax/management 
-         Thus the basedir for this project is defined above as: 
-         basedir="../../../../.."  
+    <!-- IMPORTANT: BASEDIR DEFINITION
+         This file is assumed to be in:
+         <src_bundle_dir>/j2se/src/share/classes/javax/management
+         Thus the basedir for this project is defined above as:
+         basedir="../../../../.."
          in order to be the parent dir of src subdir.
-	 Result of the build will be placed in ${basedir}/build_jmx 
+	 Result of the build will be placed in ${basedir}/build_jmx
 	 as defined by ${dir.build} property below.
      -->
 
@@ -163,14 +163,14 @@
         <echo message="   BUILD_DATE                  = ${BUILD_DATE}" />
 
     </target>
-    
+
 
 
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Call classes subtargets and rmic stubs generation -->
 
-    <target name="classes" depends="init,classes-javac,classes-rmic" 
-	    description="Call classes subtargets and rmic stubs generation" 
+    <target name="classes" depends="init,classes-javac,classes-rmic"
+	    description="Call classes subtargets and rmic stubs generation"
     />
 
 
@@ -183,13 +183,13 @@
         <mkdir dir="${dir.build.classes}" />
 
 	<javac 	srcdir="${dir.src}"
-		destdir="${dir.build.classes}" 
+		destdir="${dir.build.classes}"
 		source="${flag.javac.source}"
 		debug="${flag.debug}"
 		debuglevel="${flag.debug.level}"
 		optimize="${flag.optimize}"
 		includeAntRuntime="no"
-		includeJavaRuntime="no"	
+		includeJavaRuntime="no"
 	        >
 	    <include name="javax/management/**"/>
 	    <include name="com/sun/jmx/**"/>
@@ -253,7 +253,7 @@
 
        <mkdir dir="${dir.build.lib}" />
 
-       <jar jarfile="${dir.build.lib}/jmx.jar" 
+       <jar jarfile="${dir.build.lib}/jmx.jar"
 	    update="true"
 	    >
 
@@ -269,10 +269,10 @@
 		    <attribute name="Sealed"                 value="true" />
 		    <attribute name="Specification-Title"    value="JMX(TM) API" />
 		    <attribute name="Specification-Version"  value="1.4" />
-		    <attribute name="Specification-Vendor"   value="Sun Microsystems, Inc." />
+		    <attribute name="Specification-Vendor"   value="Oracle Corporation" />
 		    <attribute name="Implementation-Title"   value="JMX(TM) API, Java SE 6 implementation" />
-		    <attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Mustang JMX sources" /> 
-		    <attribute name="Implementation-Vendor"  value="Source bundle from Sun Microsystems, Inc. - Customer rebuilt" />
+		    <attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Java SE JMX sources" />
+		    <attribute name="Implementation-Vendor"  value="Source bundle from Oracle Corporation - Customer rebuilt" />
 		</section>
 	    </manifest>
        </jar>
@@ -295,16 +295,16 @@
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Delete build directory and all its contents -->
 
-    <target name="clean-all" 
+    <target name="clean-all"
             description="Delete build directory and all its contents" >
         <delete dir="${dir.build}" />
-    </target>               
-        
-  
+    </target>
+
+
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Clean all and build everything -->
 
-    <target name="all" depends="clean-all,jar" 
+    <target name="all" depends="clean-all,jar"
 	    description="Clean all and build everything" />
 
 
--- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java	Tue Nov 09 22:53:18 2010 -0800
@@ -92,8 +92,6 @@
  * @since 1.5
  */
 
-// Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
-//
 @SuppressWarnings("serial")  // serialVersionUID is not constant
 public class ModelMBeanNotificationInfo
     extends MBeanNotificationInfo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 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 javax.net.ssl;
+
+/**
+ * Extends the <code>SSLSession</code> interface to support additional
+ * session attributes.
+ *
+ * @since 1.7
+ */
+public abstract class ExtendedSSLSession implements SSLSession {
+    /**
+     * Obtains an array of supported signature algorithms that the local side
+     * is willing to use.
+     * <p>
+     * Note: this method is used to indicate to the peer which signature
+     * algorithms may be used for digital signatures in TLS 1.2. It is
+     * not meaningful for TLS versions prior to 1.2.
+     * <p>
+     * The signature algorithm name must be a standard Java Security
+     * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
+     * See Appendix A in the <a href=
+     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * for information about standard algorithm names.
+     * <p>
+     * Note: the local supported signature algorithms should conform to
+     * the algorithm constraints specified by
+     * {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
+     * method in <code>SSLParameters</code>.
+     *
+     * @return An array of supported signature algorithms, in descending
+     *     order of preference.  The return value is an empty array if
+     *     no signature algorithm is supported.
+     *
+     * @see SSLParameters#getAlgorithmConstraints
+     */
+    public abstract String[] getLocalSupportedSignatureAlgorithms();
+
+    /**
+     * Obtains an array of supported signature algorithms that the peer is
+     * able to use.
+     * <p>
+     * Note: this method is used to indicate to the local side which signature
+     * algorithms may be used for digital signatures in TLS 1.2. It is
+     * not meaningful for TLS versions prior to 1.2.
+     * <p>
+     * The signature algorithm name must be a standard Java Security
+     * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
+     * See Appendix A in the <a href=
+     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * for information about standard algorithm names.
+     *
+     * @return An array of supported signature algorithms, in descending
+     *     order of preference.  The return value is an empty array if
+     *     the peer has not sent the supported signature algorithms.
+     *
+     * @see X509KeyManager
+     * @see X509ExtendedKeyManager
+     */
+    public abstract String[] getPeerSupportedSignatureAlgorithms();
+}
--- a/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -188,19 +188,8 @@
      * <p>
      * The default implementation will deny such connections.
      */
-    private static HostnameVerifier defaultHostnameVerifier;
-
-    /**
-     * Initialize the default <code>HostnameVerifier</code>.
-     */
-    static {
-        try {
-            defaultHostnameVerifier =
-                new sun.net.www.protocol.https.DefaultHostnameVerifier();
-        } catch (NoClassDefFoundError e) {
-            defaultHostnameVerifier = new DefaultHostnameVerifier();
-        }
-    }
+    private static HostnameVerifier defaultHostnameVerifier =
+                                        new DefaultHostnameVerifier();
 
     /*
      * The initial default <code>HostnameVerifier</code>.  Should be
--- a/jdk/src/share/classes/javax/net/ssl/SSLEngine.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/SSLEngine.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -968,6 +968,47 @@
 
 
     /**
+     * Returns the {@code SSLSession} being constructed during a SSL/TLS
+     * handshake.
+     * <p>
+     * TLS protocols may negotiate parameters that are needed when using
+     * an instance of this class, but before the {@code SSLSession} has
+     * been completely initialized and made available via {@code getSession}.
+     * For example, the list of valid signature algorithms may restrict
+     * the type of certificates that can used during TrustManager
+     * decisions, or the maximum TLS fragment packet sizes can be
+     * resized to better support the network environment.
+     * <p>
+     * This method provides early access to the {@code SSLSession} being
+     * constructed.  Depending on how far the handshake has progressed,
+     * some data may not yet be available for use.  For example, if a
+     * remote server will be sending a Certificate chain, but that chain
+     * has yet not been processed, the {@code getPeerCertificates}
+     * method of {@code SSLSession} will throw a
+     * SSLPeerUnverifiedException.  Once that chain has been processed,
+     * {@code getPeerCertificates} will return the proper value.
+     *
+     * @see SSLSocket
+     * @see SSLSession
+     * @see ExtendedSSLSession
+     * @see X509ExtendedKeyManager
+     * @see X509ExtendedTrustManager
+     *
+     * @return null if this instance is not currently handshaking, or
+     *         if the current handshake has not progressed far enough to
+     *         create a basic SSLSession.  Otherwise, this method returns the
+     *         {@code SSLSession} currently being negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     *
+     * @since 1.7
+     */
+    public SSLSession getHandshakeSession() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /**
      * Initiates handshaking (initial or renegotiation) on this SSLEngine.
      * <P>
      * This method is not needed for the initial handshake, as the
--- a/jdk/src/share/classes/javax/net/ssl/SSLParameters.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/SSLParameters.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -25,24 +25,29 @@
 
 package javax.net.ssl;
 
+import java.security.AlgorithmConstraints;
+
 /**
  * Encapsulates parameters for an SSL/TLS connection. The parameters
  * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
- * the list of protocols to be allowed, and whether SSL/TLS servers should
- * request or require client authentication.
- *
- * <p>SSLParameters can be created via the constructors in this class.
+ * the list of protocols to be allowed, the endpoint identification
+ * algorithm during SSL/TLS handshaking, the algorithm constraints and
+ * whether SSL/TLS servers should request or require client authentication.
+ * <p>
+ * SSLParameters can be created via the constructors in this class.
  * Objects can also be obtained using the <code>getSSLParameters()</code>
  * methods in
  * {@link SSLSocket#getSSLParameters SSLSocket} and
+ * {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
  * {@link SSLEngine#getSSLParameters SSLEngine} or the
  * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
  * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
  * methods in <code>SSLContext</code>.
- *
- * <P>SSLParameters can be applied to a connection via the methods
+ * <p>
+ * SSLParameters can be applied to a connection via the methods
  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
- * {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
+ * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
+ * and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
  *
  * @see SSLSocket
  * @see SSLEngine
@@ -56,11 +61,13 @@
     private String[] protocols;
     private boolean wantClientAuth;
     private boolean needClientAuth;
+    private String identificationAlgorithm;
+    private AlgorithmConstraints algorithmConstraints;
 
     /**
      * Constructs SSLParameters.
-     *
-     * <p>The cipherSuites and protocols values are set to <code>null</code>,
+     * <p>
+     * The cipherSuites and protocols values are set to <code>null</code>,
      * wantClientAuth and needClientAuth are set to <code>false</code>.
      */
     public SSLParameters() {
@@ -69,6 +76,7 @@
 
     /**
      * Constructs SSLParameters from the specified array of ciphersuites.
+     * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
      * <code>setCipherSuites(cipherSuites);</code>.
@@ -82,6 +90,7 @@
     /**
      * Constructs SSLParameters from the specified array of ciphersuites
      * and protocols.
+     * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
      * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
@@ -178,4 +187,71 @@
         this.needClientAuth = needClientAuth;
     }
 
+    /**
+     * Returns the cryptographic algorithm constraints.
+     *
+     * @return the cryptographic algorithm constraints, or null if the
+     *     constraints have not been set
+     *
+     * @see #setAlgorithmConstraints(AlgorithmConstraints)
+     *
+     * @since 1.7
+     */
+    public AlgorithmConstraints getAlgorithmConstraints() {
+        return algorithmConstraints;
+    }
+
+    /**
+     * Sets the cryptographic algorithm constraints, which will be used
+     * in addition to any configured by the runtime environment.
+     * <p>
+     * If the <code>constraints</code> parameter is non-null, every
+     * cryptographic algorithm, key and algorithm parameters used in the
+     * SSL/TLS handshake must be permitted by the constraints.
+     *
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @since 1.7
+     */
+    public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
+        // the constraints object is immutable
+        this.algorithmConstraints = constraints;
+    }
+
+    /**
+     * Gets the endpoint identification algorithm.
+     *
+     * @return the endpoint identification algorithm, or null if none
+     * has been set.
+     *
+     * @see X509ExtendedTrustManager
+     * @see #setEndpointIdentificationAlgorithm(String)
+     *
+     * @since 1.7
+     */
+    public String getEndpointIdentificationAlgorithm() {
+        return identificationAlgorithm;
+    }
+
+    /**
+     * Sets the endpoint identification algorithm.
+     * <p>
+     * If the <code>algorithm</code> parameter is non-null or non-empty, the
+     * endpoint identification/verification procedures must be handled during
+     * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
+     *
+     * @param algorithm The standard string name of the endpoint
+     *     identification algorithm (or null).  See Appendix A in the <a href=
+     *     "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *     Java Cryptography Architecture API Specification &amp; Reference </a>
+     *     for information about standard algorithm names.
+     *
+     * @see X509ExtendedTrustManager
+     *
+     * @since 1.7
+     */
+    public void setEndpointIdentificationAlgorithm(String algorithm) {
+        this.identificationAlgorithm = algorithm;
+    }
+
 }
--- a/jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -56,8 +56,8 @@
  * @since 1.4
  * @author David Brownell
  */
-public abstract class SSLServerSocket extends ServerSocket
-{
+public abstract class SSLServerSocket extends ServerSocket {
+
     /**
      * Used only by subclasses.
      * <P>
@@ -449,8 +449,79 @@
      *
      * @return true indicates that sessions may be created; this
      *          is the default.  false indicates that an existing
-     *          session must be resumed.
+     *          session must be resumed
      * @see #setEnableSessionCreation(boolean)
      */
     public abstract boolean getEnableSessionCreation();
+
+    /**
+     * Returns the SSLParameters in effect for newly accepted connections.
+     * The ciphersuites and protocols of the returned SSLParameters
+     * are always non-null.
+     *
+     * @return the SSLParameters in effect for newly accepted connections
+     *
+     * @see #setSSLParameters(SSLParameters)
+     *
+     * @since 1.7
+     */
+    public SSLParameters getSSLParameters() {
+        SSLParameters parameters = new SSLParameters();
+
+        parameters.setCipherSuites(getEnabledCipherSuites());
+        parameters.setProtocols(getEnabledProtocols());
+        if (getNeedClientAuth()) {
+            parameters.setNeedClientAuth(true);
+        } else if (getWantClientAuth()) {
+            parameters.setWantClientAuth(true);
+        }
+
+        return parameters;
+    }
+
+    /**
+     * Applies SSLParameters to newly accepted connections.
+     *
+     * <p>This means:
+     * <ul>
+     * <li>if <code>params.getCipherSuites()</code> is non-null,
+     *   <code>setEnabledCipherSuites()</code> is called with that value
+     * <li>if <code>params.getProtocols()</code> is non-null,
+     *   <code>setEnabledProtocols()</code> is called with that value
+     * <li>if <code>params.getNeedClientAuth()</code> or
+     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
+     *   <code>setNeedClientAuth(true)</code> and
+     *   <code>setWantClientAuth(true)</code> are called, respectively;
+     *   otherwise <code>setWantClientAuth(false)</code> is called.
+     * </ul>
+     *
+     * @param params the parameters
+     * @throws IllegalArgumentException if the setEnabledCipherSuites() or
+     *    the setEnabledProtocols() call fails
+     *
+     * @see #getSSLParameters()
+     *
+     * @since 1.7
+     */
+    public void setSSLParameters(SSLParameters params) {
+        String[] s;
+        s = params.getCipherSuites();
+        if (s != null) {
+            setEnabledCipherSuites(s);
+        }
+
+        s = params.getProtocols();
+        if (s != null) {
+            setEnabledProtocols(s);
+        }
+
+        if (params.getNeedClientAuth()) {
+            setNeedClientAuth(true);
+        } else if (params.getWantClientAuth()) {
+            setWantClientAuth(true);
+        } else {
+            setWantClientAuth(false);
+        }
+    }
+
 }
--- a/jdk/src/share/classes/javax/net/ssl/SSLSocket.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/SSLSocket.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -371,6 +371,51 @@
 
 
     /**
+     * Returns the {@code SSLSession} being constructed during a SSL/TLS
+     * handshake.
+     * <p>
+     * TLS protocols may negotiate parameters that are needed when using
+     * an instance of this class, but before the {@code SSLSession} has
+     * been completely initialized and made available via {@code getSession}.
+     * For example, the list of valid signature algorithms may restrict
+     * the type of certificates that can used during TrustManager
+     * decisions, or the maximum TLS fragment packet sizes can be
+     * resized to better support the network environment.
+     * <p>
+     * This method provides early access to the {@code SSLSession} being
+     * constructed.  Depending on how far the handshake has progressed,
+     * some data may not yet be available for use.  For example, if a
+     * remote server will be sending a Certificate chain, but that chain
+     * has yet not been processed, the {@code getPeerCertificates}
+     * method of {@code SSLSession} will throw a
+     * SSLPeerUnverifiedException.  Once that chain has been processed,
+     * {@code getPeerCertificates} will return the proper value.
+     * <p>
+     * Unlike {@link #getSession()}, this method does not initiate the
+     * initial handshake and does not block until handshaking is
+     * complete.
+     *
+     * @see SSLEngine
+     * @see SSLSession
+     * @see ExtendedSSLSession
+     * @see X509ExtendedKeyManager
+     * @see X509ExtendedTrustManager
+     *
+     * @return null if this instance is not currently handshaking, or
+     *         if the current handshake has not progressed far enough to
+     *         create a basic SSLSession.  Otherwise, this method returns the
+     *         {@code SSLSession} currently being negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     *
+     * @since 1.7
+     */
+    public SSLSession getHandshakeSession() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /**
      * Registers an event listener to receive notifications that an
      * SSL handshake has completed on this connection.
      *
--- a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -30,6 +30,7 @@
 import javax.net.SocketFactory;
 import java.io.IOException;
 import java.security.*;
+import java.util.Locale;
 
 import sun.security.action.GetPropertyAction;
 
@@ -50,7 +51,8 @@
 
     static {
         String s = java.security.AccessController.doPrivileged(
-            new GetPropertyAction("javax.net.debug", "")).toLowerCase();
+            new GetPropertyAction("javax.net.debug", "")).toLowerCase(
+                                                            Locale.ENGLISH);
         DEBUG = s.contains("all") || s.contains("ssl");
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/net/ssl/X509ExtendedTrustManager.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 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 javax.net.ssl;
+
+import java.net.Socket;
+import javax.net.ssl.X509TrustManager;
+
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+
+/**
+ * Extensions to the <code>X509TrustManager</code> interface to support
+ * SSL/TLS connection sensitive trust management.
+ * <p>
+ * To prevent man-in-the-middle attacks, hostname checks can be done
+ * to verify that the hostname in an end-entity certificate matches the
+ * targeted hostname.  TLS does not require such checks, but some protocols
+ * over TLS (such as HTTPS) do.  In earlier versions of the JDK, the
+ * certificate chain checks were done at the SSL/TLS layer, and the hostname
+ * verification checks were done at the layer over TLS.  This class allows
+ * for the checking to be done during a single call to this class.
+ * <p>
+ * RFC 2830 defines the server identification specification for the "LDAPS"
+ * algorithm. RFC 2818 defines both the server identification and the
+ * client identification specification for the "HTTPS" algorithm.
+ *
+ * @see X509TrustManager
+ * @see HostnameVerifier
+ *
+ * @since 1.7
+ */
+public abstract class X509ExtendedTrustManager implements X509TrustManager {
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is determined by the actual certificate
+     * used. For instance, if RSAPublicKey is used, the authType
+     * should be "RSA". Checking is case-sensitive.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the endpoint identification
+     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * connected to should be checked against the peer's identity presented
+     * in the end-entity X509 certificate, as specified in the endpoint
+     * identification algorithm.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the algorithm constraints of the
+     * <code>SSLParameters</code> is non-null, for every certificate in the
+     * certification path, fields such as subject public key, the signature
+     * algorithm, key usage, extended key usage, etc. need to conform to the
+     * algorithm constraints in place on this socket.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param socket the socket used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkClientTrusted(X509Certificate[] chain,
+            String authType, Socket socket) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is the key exchange algorithm portion
+     * of the cipher suites represented as a String, such as "RSA",
+     * "DHE_DSS". Note: for some exportable cipher suites, the key
+     * exchange algorithm is determined at run time during the
+     * handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+     * the authType should be RSA_EXPORT when an ephemeral RSA key is
+     * used for the key exchange, and RSA when the key from the server
+     * certificate is used. Checking is case-sensitive.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the endpoint identification
+     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * connected to should be checked against the peer's identity presented
+     * in the end-entity X509 certificate, as specified in the endpoint
+     * identification algorithm.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the algorithm constraints of the
+     *  <code>SSLParameters</code> is non-null, for every certificate in the
+     * certification path, fields such as subject public key, the signature
+     * algorithm, key usage, extended key usage, etc. need to conform to the
+     * algorithm constraints in place on this socket.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param socket the socket used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkServerTrusted(X509Certificate[] chain,
+        String authType, Socket socket) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is determined by the actual certificate
+     * used. For instance, if RSAPublicKey is used, the authType
+     * should be "RSA". Checking is case-sensitive.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the endpoint
+     * identification algorithm of the <code>SSLParameters</code> is
+     * non-empty, to prevent man-in-the-middle attacks, the address that
+     * the <code>engine</code> connected to should be checked against
+     * the peer's identity presented in the end-entity X509 certificate,
+     * as specified in the endpoint identification algorithm.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the algorithm
+     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * certificate in the certification path, fields such as subject public
+     * key, the signature algorithm, key usage, extended key usage, etc.
+     * need to conform to the algorithm constraints in place on this engine.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param engine the engine used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkClientTrusted(X509Certificate[] chain,
+        String authType, SSLEngine engine) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is the key exchange algorithm portion
+     * of the cipher suites represented as a String, such as "RSA",
+     * "DHE_DSS". Note: for some exportable cipher suites, the key
+     * exchange algorithm is determined at run time during the
+     * handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+     * the authType should be RSA_EXPORT when an ephemeral RSA key is
+     * used for the key exchange, and RSA when the key from the server
+     * certificate is used. Checking is case-sensitive.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the endpoint
+     * identification algorithm of the <code>SSLParameters</code> is
+     * non-empty, to prevent man-in-the-middle attacks, the address that
+     * the <code>engine</code> connected to should be checked against
+     * the peer's identity presented in the end-entity X509 certificate,
+     * as specified in the endpoint identification algorithm.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the algorithm
+     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * certificate in the certification path, fields such as subject public
+     * key, the signature algorithm, key usage, extended key usage, etc.
+     * need to conform to the algorithm constraints in place on this engine.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param engine the engine used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkServerTrusted(X509Certificate[] chain,
+        String authType, SSLEngine engine) throws CertificateException;
+
+}
--- a/jdk/src/share/classes/javax/swing/BorderFactory.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/BorderFactory.java	Tue Nov 09 22:53:18 2010 -0800
@@ -24,8 +24,10 @@
  */
 package javax.swing;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.Paint;
 import javax.swing.border.*;
 
 /**
@@ -636,4 +638,125 @@
                                                 Icon tileIcon) {
         return new MatteBorder(top, left, bottom, right, tileIcon);
     }
+
+//// StrokeBorder //////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Creates a border of the specified {@code stroke}.
+     * The component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @return the {@code Border} object
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     *
+     * @since 1.7
+     */
+    public static Border createStrokeBorder(BasicStroke stroke) {
+        return new StrokeBorder(stroke);
+    }
+
+    /**
+     * Creates a border of the specified {@code stroke} and {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @param paint   the {@link Paint} object used to generate a color
+     * @return the {@code Border} object
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     *
+     * @since 1.7
+     */
+    public static Border createStrokeBorder(BasicStroke stroke, Paint paint) {
+        return new StrokeBorder(stroke, paint);
+    }
+
+//// DashedBorder //////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+    private static Border sharedDashedBorder;
+
+    /**
+     * Creates a dashed border of the specified {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     * The width of a dash line is equal to {@code 1}.
+     * The relative length of a dash line and
+     * the relative spacing between dash lines are equal to {@code 1}.
+     * A dash line is not rounded.
+     *
+     * @param paint  the {@link Paint} object used to generate a color
+     * @return the {@code Border} object
+     *
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint) {
+        return createDashedBorder(paint, 1.0f, 1.0f, 1.0f, false);
+    }
+
+    /**
+     * Creates a dashed border of the specified {@code paint},
+     * relative {@code length}, and relative {@code spacing}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     * The width of a dash line is equal to {@code 1}.
+     * A dash line is not rounded.
+     *
+     * @param paint    the {@link Paint} object used to generate a color
+     * @param length   the relative length of a dash line
+     * @param spacing  the relative spacing between dash lines
+     * @return the {@code Border} object
+     *
+     * @throws IllegalArgumentException if the specified {@code length} is less than {@code 1}, or
+     *                                  if the specified {@code spacing} is less than {@code 0}
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint, float length, float spacing) {
+        return createDashedBorder(paint, 1.0f, length, spacing, false);
+    }
+
+    /**
+     * Creates a dashed border of the specified {@code paint}, {@code thickness},
+     * line shape, relative {@code length}, and relative {@code spacing}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param paint      the {@link Paint} object used to generate a color
+     * @param thickness  the width of a dash line
+     * @param length     the relative length of a dash line
+     * @param spacing    the relative spacing between dash lines
+     * @param rounded    whether or not line ends should be round
+     * @return the {@code Border} object
+     *
+     * @throws IllegalArgumentException if the specified {@code thickness} is less than {@code 1}, or
+     *                                  if the specified {@code length} is less than {@code 1}, or
+     *                                  if the specified {@code spacing} is less than {@code 0}
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint, float thickness, float length, float spacing, boolean rounded) {
+        boolean shared = !rounded && (paint == null) && (thickness == 1.0f) && (length == 1.0f) && (spacing == 1.0f);
+        if (shared && (sharedDashedBorder != null)) {
+            return sharedDashedBorder;
+        }
+        if (thickness < 1.0f) {
+            throw new IllegalArgumentException("thickness is less than 1");
+        }
+        if (length < 1.0f) {
+            throw new IllegalArgumentException("length is less than 1");
+        }
+        if (spacing < 0.0f) {
+            throw new IllegalArgumentException("spacing is less than 0");
+        }
+        int cap = rounded ? BasicStroke.CAP_ROUND : BasicStroke.CAP_SQUARE;
+        int join = rounded ? BasicStroke.JOIN_ROUND : BasicStroke.JOIN_MITER;
+        float[] array = { thickness * (length - 1.0f), thickness * (spacing + 1.0f) };
+        Border border = createStrokeBorder(new BasicStroke(thickness, cap, join, thickness * 2.0f, array, 0.0f), paint);
+        if (shared) {
+            sharedDashedBorder = border;
+        }
+        return border;
+    }
 }
--- a/jdk/src/share/classes/javax/swing/DebugGraphics.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/DebugGraphics.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1322,13 +1322,11 @@
     }
 
     String toShortString() {
-        StringBuffer buffer = new StringBuffer("Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")");
-        return buffer.toString();
+        return "Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")";
     }
 
     String pointToString(int x, int y) {
-        StringBuffer buffer = new StringBuffer("(" + x + ", " + y + ")");
-        return buffer.toString();
+        return "(" + x + ", " + y + ")";
     }
 
     /** Enables/disables diagnostic information about every graphics
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Tue Nov 09 22:53:18 2010 -0800
@@ -4783,21 +4783,11 @@
      * @param y  the y value of the dirty region
      * @param width  the width of the dirty region
      * @param height  the height of the dirty region
+     * @see #isPaintingOrigin()
      * @see java.awt.Component#isShowing
      * @see RepaintManager#addDirtyRegion
      */
     public void repaint(long tm, int x, int y, int width, int height) {
-        Container p = this;
-        while ((p = p.getParent()) instanceof JComponent) {
-            JComponent jp = (JComponent) p;
-            if (jp.isPaintingOrigin()) {
-                Rectangle rectangle = SwingUtilities.convertRectangle(
-                        this, new Rectangle(x, y, width, height), jp);
-                jp.repaint(tm,
-                        rectangle.x, rectangle.y, rectangle.width, rectangle.height);
-                return;
-            }
-        }
         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
     }
 
@@ -4808,6 +4798,7 @@
      * currently pending events have been dispatched.
      *
      * @param  r a <code>Rectangle</code> containing the dirty region
+     * @see #isPaintingOrigin()
      * @see java.awt.Component#isShowing
      * @see RepaintManager#addDirtyRegion
      */
@@ -4912,13 +4903,19 @@
     }
 
     /**
-     * Returns true if a paint triggered on a child component should cause
+     * Returns {@code true} if a paint triggered on a child component should cause
      * painting to originate from this Component, or one of its ancestors.
+     * <p/>
+     * Calling {@link JComponent#repaint} on a Swing component will be delegated to
+     * the first ancestor which {@code isPaintingOrigin()} returns {@true},
+     * if there are any.
+     * <p/>
+     * {@code JComponent} subclasses that need to be repainted when any of their
+     * children are repainted should override this method to return {@code true}.
      *
-     * @return true if painting should originate from this Component or
-     *         one of its ancestors.
-     */
-    boolean isPaintingOrigin() {
+     * @return always returns {@code false}
+     */
+    protected boolean isPaintingOrigin() {
         return false;
     }
 
--- a/jdk/src/share/classes/javax/swing/JDialog.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/JDialog.java	Tue Nov 09 22:53:18 2010 -0800
@@ -303,10 +303,9 @@
      * @param modal specifies whether dialog blocks user input to other top-level
      *     windows when shown. If {@code true}, the modality type property is set to
      *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless.
-     * @param gc the {@code GraphicsConfiguration}
-     *     of the target screen device.  If {@code gc} is
-     *     {@code null}, the same
-     *     {@code GraphicsConfiguration} as the owning Frame is used.
+     * @param gc the {@code GraphicsConfiguration} of the target screen device;
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
      *     returns {@code true}.
      * @see java.awt.Dialog.ModalityType
@@ -441,10 +440,9 @@
      * @param modal specifies whether dialog blocks user input to other top-level
      *     windows when shown. If {@code true}, the modality type property is set to
      *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless
-     * @param gc the {@code GraphicsConfiguration}
-     *     of the target screen device.  If {@code gc} is
-     *     {@code null}, the same
-     *     {@code GraphicsConfiguration} as the owning Dialog is used.
+     * @param gc the {@code GraphicsConfiguration} of the target screen device;
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
      *     returns {@code true}.
      * @see java.awt.Dialog.ModalityType
@@ -612,10 +610,8 @@
      *     windows when shown. {@code null} value and unsupported modality
      *     types are equivalent to {@code MODELESS}
      * @param gc the {@code GraphicsConfiguration} of the target screen device;
-     *     if {@code null}, the {@code GraphicsConfiguration} from the owning
-     *     window is used; if {@code owner} is also {@code null}, the
-     *     system default {@code GraphicsConfiguration} is assumed
-     *
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws IllegalArgumentException
      *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
      *     or {@link java.awt.Frame Frame}
--- a/jdk/src/share/classes/javax/swing/JLayer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/JLayer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -384,7 +384,7 @@
      * @return true
      * @see JComponent#isPaintingOrigin()
      */
-    boolean isPaintingOrigin() {
+    protected boolean isPaintingOrigin() {
         return true;
     }
 
--- a/jdk/src/share/classes/javax/swing/JViewport.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/JViewport.java	Tue Nov 09 22:53:18 2010 -0800
@@ -637,14 +637,14 @@
     }
 
     /**
-     * Returns true if scroll mode is a BACKINGSTORE_SCROLL_MODE to cause
-     * painting to originate from <code>JViewport</code>, or one of its
-     * ancestors. Otherwise returns false.
+     * Returns true if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE} to cause
+     * painting to originate from {@code JViewport}, or one of its
+     * ancestors. Otherwise returns {@code false}.
      *
-     * @return true if if scroll mode is a BACKINGSTORE_SCROLL_MODE.
+     * @return true if if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE}.
      * @see JComponent#isPaintingOrigin()
      */
-    boolean isPaintingOrigin() {
+    protected boolean isPaintingOrigin() {
         return scrollMode == BACKINGSTORE_SCROLL_MODE;
     }
 
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java	Tue Nov 09 22:53:18 2010 -0800
@@ -438,6 +438,7 @@
      * @param y Y coordinate of the region to repaint
      * @param w Width of the region to repaint
      * @param h Height of the region to repaint
+     * @see JComponent#isPaintingOrigin()
      * @see JComponent#repaint
      */
     public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
@@ -447,6 +448,16 @@
             delegate.addDirtyRegion(c, x, y, w, h);
             return;
         }
+        Container p = c;
+        while ((p = p.getParent()) instanceof JComponent) {
+            JComponent jp = (JComponent) p;
+            if (jp.isPaintingOrigin()) {
+                Rectangle rectangle = SwingUtilities.convertRectangle(
+                        c, new Rectangle(x, y, w, h), jp);
+                jp.repaint(0, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+                return;
+            }
+        }
         addDirtyRegion0(c, x, y, w, h);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/swing/border/StrokeBorder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 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 javax.swing.border;
+
+import java.awt.BasicStroke;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Paint;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.beans.ConstructorProperties;
+
+/**
+ * A class which implements a border of an arbitrary stroke.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI
+ * between applications running the same version of Swing.
+ * As of 1.4, support for long term storage of all JavaBeans&trade;
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @author Sergey A. Malenkov
+ *
+ * @since 1.7
+ */
+public class StrokeBorder extends AbstractBorder {
+    private final BasicStroke stroke;
+    private final Paint paint;
+
+    /**
+     * Creates a border of the specified {@code stroke}.
+     * The component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     */
+    public StrokeBorder(BasicStroke stroke) {
+        this(stroke, null);
+    }
+
+    /**
+     * Creates a border of the specified {@code stroke} and {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @param paint   the {@link Paint} object used to generate a color
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     */
+    @ConstructorProperties({ "stroke", "paint" })
+    public StrokeBorder(BasicStroke stroke, Paint paint) {
+        if (stroke == null) {
+            throw new NullPointerException("border's stroke");
+        }
+        this.stroke = stroke;
+        this.paint = paint;
+    }
+
+    /**
+     * Paints the border for the specified component
+     * with the specified position and size.
+     *
+     * @param c       the component for which this border is being painted
+     * @param g       the paint graphics
+     * @param x       the x position of the painted border
+     * @param y       the y position of the painted border
+     * @param width   the width of the painted border
+     * @param height  the height of the painted border
+     *
+     * @throws NullPointerException if the specified {@code c} or {@code g} are {@code null}
+     */
+    @Override
+    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+        float size = this.stroke.getLineWidth();
+        if (size > 0.0f) {
+            g = g.create();
+            if (g instanceof Graphics2D) {
+                Graphics2D g2d = (Graphics2D) g;
+                g2d.setStroke(this.stroke);
+                g2d.setPaint(this.paint != null ? this.paint : c.getForeground());
+                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                     RenderingHints.VALUE_ANTIALIAS_ON);
+                g2d.draw(new Rectangle2D.Float(x + size / 2, y + size / 2, width - size, height - size));
+            }
+            g.dispose();
+        }
+    }
+
+    /**
+     * Reinitializes the {@code insets} parameter
+     * with this border's current insets.
+     * All insets are equal to the line width of the stroke.
+     *
+     * @param c       the component for which this border insets value applies
+     * @param insets  the {@code Insets} object to be reinitialized
+     * @return the reinitialized {@code insets} parameter
+     *
+     * @throws NullPointerException if the specified {@code insets} is {@code null}
+     */
+    @Override
+    public Insets getBorderInsets(Component c, Insets insets) {
+        int size = (int) Math.ceil(this.stroke.getLineWidth());
+        insets.set(size, size, size, size);
+        return insets;
+    }
+
+    /**
+     * Returns the {@link BasicStroke} object used to stroke a shape
+     * during the border rendering.
+     *
+     * @return the {@link BasicStroke} object
+     */
+    public BasicStroke getStroke() {
+        return this.stroke;
+    }
+
+    /**
+     * Returns the {@link Paint} object used to generate a color
+     * during the border rendering.
+     *
+     * @return the {@link Paint} object or {@code null}
+     *         if the {@code paint} parameter is not set
+     */
+    public Paint getPaint() {
+        return this.paint;
+    }
+}
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java	Tue Nov 09 22:53:18 2010 -0800
@@ -362,6 +362,14 @@
      * @since 1.6
      */
     public int getBaseline(JComponent c, int width, int height) {
+        if (c == null) {
+            throw new NullPointerException("Component must be non-null");
+        }
+
+        if (width < 0 || height < 0) {
+            throw new IllegalArgumentException("Width and height must be >= 0");
+        }
+
         JViewport viewport = scrollpane.getViewport();
         Insets spInsets = scrollpane.getInsets();
         int y = spInsets.top;
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Tue Nov 09 22:53:18 2010 -0800
@@ -115,10 +115,7 @@
         return new SynthTabbedPaneUI();
     }
 
-    private SynthTabbedPaneUI() {
-    }
-
-    private boolean scrollableTabLayoutEnabled() {
+     private boolean scrollableTabLayoutEnabled() {
         return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
     }
 
--- a/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -186,6 +186,9 @@
      */
     public Component getTableCellRendererComponent(JTable table, Object value,
                           boolean isSelected, boolean hasFocus, int row, int column) {
+        if (table == null) {
+            return this;
+        }
 
         Color fg = null;
         Color bg = null;
--- a/jdk/src/share/classes/javax/swing/text/DefaultCaret.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/DefaultCaret.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1334,13 +1334,13 @@
                     && component.getClientProperty("JPasswordField.cutCopyAllowed") !=
                     Boolean.TRUE) {
                     //fix for 4793761
-                    StringBuffer txt = null;
+                    StringBuilder txt = null;
                     char echoChar = ((JPasswordField)component).getEchoChar();
                     int p0 = Math.min(getDot(), getMark());
                     int p1 = Math.max(getDot(), getMark());
                     for (int i = p0; i < p1; i++) {
                         if (txt == null) {
-                            txt = new StringBuffer();
+                            txt = new StringBuilder();
                         }
                         txt.append(echoChar);
                     }
@@ -1675,7 +1675,6 @@
                 }
                 return;
             }
-            int adjust = 0;
             int offset = e.getOffset();
             int length = e.getLength();
             int newDot = dot;
@@ -1759,7 +1758,6 @@
             }
             int offs0 = e.getOffset();
             int offs1 = offs0 + e.getLength();
-            int adjust = 0;
             int newDot = dot;
             boolean adjustDotBias = false;
             int newMark = mark;
--- a/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java	Tue Nov 09 22:53:18 2010 -0800
@@ -132,7 +132,7 @@
             // install the content
             Content c = getContent();
             int n = data.length;
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0; i < n; i++) {
                 ElementSpec es = data[i];
                 if (es.getLength() > 0) {
@@ -191,7 +191,7 @@
             // install the content
             Content c = getContent();
             int n = data.length;
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0; i < n; i++) {
                 ElementSpec es = data[i];
                 if (es.getLength() > 0) {
--- a/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java	Tue Nov 09 22:53:18 2010 -0800
@@ -30,7 +30,6 @@
 import java.text.AttributedCharacterIterator.Attribute;
 import java.util.*;
 import javax.swing.*;
-import javax.swing.text.*;
 
 /**
  * <code>InternationalFormatter</code> extends <code>DefaultFormatter</code>,
@@ -875,7 +874,6 @@
                     (f instanceof AttributedCharacterIterator.Attribute)) {
             AttributedCharacterIterator.Attribute field =
                                    (AttributedCharacterIterator.Attribute)f;
-            int index = 0;
 
             iterator.first();
             while (iterator.getIndex() < start) {
--- a/jdk/src/share/classes/javax/swing/text/JTextComponent.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/JTextComponent.java	Tue Nov 09 22:53:18 2010 -0800
@@ -35,10 +35,7 @@
 import java.util.Hashtable;
 import java.util.Enumeration;
 import java.util.Vector;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 import java.util.concurrent.*;
 
@@ -4058,7 +4055,7 @@
 
     private static final Object KEYMAP_TABLE =
         new StringBuilder("JTextComponent_KeymapTable");
-    private JTextComponent editor;
+
     //
     // member variables used for on-the-spot input method
     // editing style support
@@ -4748,14 +4745,14 @@
                         processKeyEvent(ke);
                     }
                 } else {
-                    StringBuffer strBuf = new StringBuffer();
+                    StringBuilder strBuf = new StringBuilder();
                     for (char c = text.current(); commitCount > 0;
                          c = text.next(), commitCount--) {
                         strBuf.append(c);
                     }
 
                     // map it to an ActionEvent
-                    mapCommittedTextToAction(new String(strBuf));
+                    mapCommittedTextToAction(strBuf.toString());
                 }
 
                 // Remember latest committed text end index
@@ -4801,7 +4798,7 @@
     private void createComposedTextAttribute(int composedIndex,
                                         AttributedCharacterIterator text) {
         Document doc = getDocument();
-        StringBuffer strBuf = new StringBuffer();
+        StringBuilder strBuf = new StringBuilder();
 
         // create attributed string with no attributes
         for (char c = text.setIndex(composedIndex);
@@ -4809,7 +4806,7 @@
             strBuf.append(c);
         }
 
-        composedTextContent = new String(strBuf);
+        composedTextContent = strBuf.toString();
         composedTextAttribute = new SimpleAttributeSet();
         composedTextAttribute.addAttribute(StyleConstants.ComposedTextAttribute,
                 new AttributedString(text, composedIndex, text.getEndIndex()));
--- a/jdk/src/share/classes/javax/swing/text/MaskFormatter.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/MaskFormatter.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,7 +29,6 @@
 import java.text.*;
 import java.util.*;
 import javax.swing.*;
-import javax.swing.text.*;
 
 /**
  * <code>MaskFormatter</code> is used to format and edit strings. The behavior
@@ -385,7 +384,7 @@
      */
     public String valueToString(Object value) throws ParseException {
         String sValue = (value == null) ? "" : value.toString();
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         String placeholder = getPlaceholder();
         int[] valueCounter = { 0 };
 
@@ -484,7 +483,7 @@
      * Invokes <code>append</code> on the mask characters in
      * <code>mask</code>.
      */
-    private void append(StringBuffer result, String value, int[] index,
+    private void append(StringBuilder result, String value, int[] index,
                         String placeholder, MaskCharacter[] mask)
                           throws ParseException {
         for (int counter = 0, maxCounter = mask.length;
@@ -611,13 +610,13 @@
      * Removes the literal characters from the passed in string.
      */
     private String stripLiteralChars(String string) {
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         int last = 0;
 
         for (int counter = 0, max = string.length(); counter < max; counter++){
             if (isLiteral(counter)) {
                 if (sb == null) {
-                    sb = new StringBuffer();
+                    sb = new StringBuilder();
                     if (counter > 0) {
                         sb.append(string.substring(0, counter));
                     }
@@ -715,10 +714,10 @@
      */
     boolean canReplace(ReplaceHolder rh) {
         // This method is rather long, but much of the burden is in
-        // maintaining a String and swapping to a StringBuffer only if
+        // maintaining a String and swapping to a StringBuilder only if
         // absolutely necessary.
         if (!getAllowsInvalid()) {
-            StringBuffer replace = null;
+            StringBuilder replace = null;
             String text = rh.text;
             int tl = (text != null) ? text.length() : 0;
 
@@ -737,7 +736,7 @@
                     char aChar = text.charAt(textIndex);
                     if (aChar != getCharacter(rh.offset + counter, aChar)) {
                         if (replace == null) {
-                            replace = new StringBuffer();
+                            replace = new StringBuilder();
                             if (textIndex > 0) {
                                 replace.append(text.substring(0, textIndex));
                             }
@@ -758,7 +757,7 @@
                         }
                     }
                     else if (textIndex > 0) {
-                        replace = new StringBuffer(max);
+                        replace = new StringBuilder(max);
                         replace.append(text.substring(0, textIndex));
                         replace.append(getLiteral(rh.offset + counter));
                         if (textIndex < tl) {
@@ -780,7 +779,7 @@
                 else if (textIndex >= tl) {
                     // placeholder
                     if (replace == null) {
-                        replace = new StringBuffer();
+                        replace = new StringBuilder();
                         if (text != null) {
                             replace.append(text);
                         }
@@ -863,7 +862,7 @@
          * Appends the necessary character in <code>formatting</code> at
          * <code>index</code> to <code>buff</code>.
          */
-        public void append(StringBuffer buff, String formatting, int[] index,
+        public void append(StringBuilder buff, String formatting, int[] index,
                            String placeholder)
                           throws ParseException {
             boolean inString = index[0] < formatting.length();
--- a/jdk/src/share/classes/javax/swing/text/NumberFormatter.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/NumberFormatter.java	Tue Nov 09 22:53:18 2010 -0800
@@ -27,7 +27,6 @@
 import java.lang.reflect.*;
 import java.text.*;
 import java.util.*;
-import javax.swing.text.*;
 
 /**
  * <code>NumberFormatter</code> subclasses <code>InternationalFormatter</code>
@@ -132,7 +131,7 @@
         DecimalFormatSymbols dfs = getDecimalFormatSymbols();
 
         if (dfs != null) {
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
 
             sb.append(dfs.getCurrencySymbol());
             sb.append(dfs.getDecimalSeparator());
@@ -240,13 +239,6 @@
     }
 
     /**
-     */
-    private boolean isValidInsertionCharacter(char aChar) {
-        return (Character.isDigit(aChar) || specialChars.indexOf(aChar) != -1);
-    }
-
-
-    /**
      * Subclassed to return false if <code>text</code> contains in an invalid
      * character to insert, that is, it is not a digit
      * (<code>Character.isDigit()</code>) and
@@ -403,28 +395,6 @@
     }
 
     /**
-     * Returns true if the range offset to length identifies the only
-     * integer field.
-     */
-    private boolean isOnlyIntegerField(int offset, int length) {
-        if (isValidMask()) {
-            int start = getAttributeStart(NumberFormat.Field.INTEGER);
-
-            if (start != -1) {
-                AttributedCharacterIterator iterator = getIterator();
-
-                iterator.setIndex(start);
-                if (offset > start || iterator.getRunLimit(
-                    NumberFormat.Field.INTEGER) > (offset + length)) {
-                    return false;
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
      * Invoked to toggle the sign. For this to work the value class
      * must have a single arg constructor that takes a String.
      */
--- a/jdk/src/share/classes/javax/swing/text/PlainDocument.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/PlainDocument.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,7 +25,6 @@
 package javax.swing.text;
 
 import java.util.Vector;
-import javax.swing.event.*;
 
 /**
  * A plain document that maintains no character attributes.  The
@@ -118,7 +117,7 @@
         Object filterNewlines = getProperty("filterNewlines");
         if ((filterNewlines instanceof Boolean) && filterNewlines.equals(Boolean.TRUE)) {
             if ((str != null) && (str.indexOf('\n') >= 0)) {
-                StringBuffer filtered = new StringBuffer(str);
+                StringBuilder filtered = new StringBuilder(str);
                 int n = filtered.length();
                 for (int i = 0; i < n; i++) {
                     if (filtered.charAt(i) == '\n') {
@@ -204,11 +203,9 @@
                 }
             }
             if (hasBreaks) {
-                int rmCount = 1;
                 removed.addElement(rmCandidate);
                 if ((offset + length == rmOffs1) && (lastOffset != rmOffs1) &&
                     ((index+1) < lineMap.getElementCount())) {
-                    rmCount += 1;
                     Element e = lineMap.getElement(index+1);
                     removed.addElement(e);
                     rmOffs1 = e.getEndOffset();
--- a/jdk/src/share/classes/javax/swing/text/TabSet.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/TabSet.java	Tue Nov 09 22:53:18 2010 -0800
@@ -199,7 +199,7 @@
      */
     public String toString() {
         int            tabCount = getTabCount();
-        StringBuffer   buffer = new StringBuffer("[ ");
+        StringBuilder buffer = new StringBuilder("[ ");
 
         for(int counter = 0; counter < tabCount; counter++) {
             if(counter > 0)
--- a/jdk/src/share/classes/javax/swing/text/html/FormView.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/FormView.java	Tue Nov 09 22:53:18 2010 -0800
@@ -362,7 +362,7 @@
      */
     public void actionPerformed(ActionEvent evt) {
         Element element = getElement();
-        StringBuffer dataBuffer = new StringBuffer();
+        StringBuilder dataBuffer = new StringBuilder();
         HTMLDocument doc = (HTMLDocument)getDocument();
         AttributeSet attr = element.getAttributes();
 
@@ -508,7 +508,7 @@
      */
     protected void imageSubmit(String imageData) {
 
-        StringBuffer dataBuffer = new StringBuffer();
+        StringBuilder dataBuffer = new StringBuilder();
         Element elem = getElement();
         HTMLDocument hdoc = (HTMLDocument)elem.getDocument();
         getFormData(dataBuffer);
@@ -589,7 +589,7 @@
      * @param targetElement the element that triggered the
      *                      form submission
      */
-    void getFormData(StringBuffer buffer) {
+    private void getFormData(StringBuilder buffer) {
         Element formE = getFormElement();
         if (formE != null) {
             ElementIterator it = new ElementIterator(formE);
@@ -623,7 +623,7 @@
      * data is loaded in name/value pairs.
      *
      */
-    private void loadElementDataIntoBuffer(Element elem, StringBuffer buffer) {
+    private void loadElementDataIntoBuffer(Element elem, StringBuilder buffer) {
 
         AttributeSet attr = elem.getAttributes();
         String name = (String)attr.getAttribute(HTML.Attribute.NAME);
@@ -692,29 +692,6 @@
             }
             if (path != null && path.length() > 0) {
                 value = path;
-/*
-
-                try {
-                    Reader reader = new BufferedReader(new FileReader(path));
-                    StringBuffer buffer = new StringBuffer();
-                    char[] cBuff = new char[1024];
-                    int read;
-
-                    try {
-                        while ((read = reader.read(cBuff)) != -1) {
-                            buffer.append(cBuff, 0, read);
-                        }
-                    } catch (IOException ioe) {
-                        buffer = null;
-                    }
-                    try {
-                        reader.close();
-                    } catch (IOException ioe) {}
-                    if (buffer != null) {
-                        value = buffer.toString();
-                    }
-                } catch (IOException ioe) {}
-*/
             }
         }
         return value;
@@ -740,7 +717,7 @@
      * form element.  Basically, only items that are selected
      * and have their name attribute set are added to the buffer.
      */
-    private void loadSelectData(AttributeSet attr, StringBuffer buffer) {
+    private void loadSelectData(AttributeSet attr, StringBuilder buffer) {
 
         String name = (String)attr.getAttribute(HTML.Attribute.NAME);
         if (name == null) {
@@ -771,7 +748,7 @@
      * URLEncoder.encode() method before being added to the
      * buffer.
      */
-    private void appendBuffer(StringBuffer buffer, String name, String value) {
+    private void appendBuffer(StringBuilder buffer, String name, String value) {
         if (buffer.length() > 0) {
             buffer.append('&');
         }
--- a/jdk/src/share/classes/javax/swing/text/html/MinimalHTMLWriter.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/MinimalHTMLWriter.java	Tue Nov 09 22:53:18 2010 -0800
@@ -691,11 +691,11 @@
         if (styleNameMapping == null) {
             return style;
         }
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         for (int counter = style.length() - 1; counter >= 0; counter--) {
             if (!isValidCharacter(style.charAt(counter))) {
                 if (sb == null) {
-                    sb = new StringBuffer(style);
+                    sb = new StringBuilder(style);
                 }
                 sb.setCharAt(counter, 'a');
             }
--- a/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Tue Nov 09 22:53:18 2010 -0800
@@ -998,7 +998,7 @@
     void addRule(String[] selector, AttributeSet declaration,
                  boolean isLinked) {
         int n = selector.length;
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(selector[0]);
         for (int counter = 1; counter < n; counter++) {
             sb.append(' ');
--- a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1470,7 +1470,7 @@
      */
     public String parseDTDMarkup() throws IOException {
 
-        StringBuffer strBuff = new StringBuffer();
+        StringBuilder strBuff = new StringBuilder();
         ch = readCh();
         while(true) {
             switch (ch) {
--- a/jdk/src/share/classes/javax/swing/text/rtf/AbstractFilter.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/javax/swing/text/rtf/AbstractFilter.java	Tue Nov 09 22:53:18 2010 -0800
@@ -160,7 +160,7 @@
     public void write(byte[] buf, int off, int len)
       throws IOException
     {
-      StringBuffer accumulator = null;
+      StringBuilder accumulator = null;
       while (len > 0) {
         short b = (short)buf[off];
 
@@ -178,7 +178,7 @@
           char ch = translationTable[b];
           if (ch != (char)0) {
             if (accumulator == null)
-              accumulator = new StringBuffer();
+              accumulator = new StringBuilder();
             accumulator.append(ch);
           }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/Curve.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,294 @@
+/*
+ * 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 sun.java2d.pisces;
+
+import java.util.Iterator;
+
+class Curve {
+
+    float ax, ay, bx, by, cx, cy, dx, dy;
+    float dax, day, dbx, dby;
+
+    Curve() {
+    }
+
+    void set(float[] points, int type) {
+        switch(type) {
+        case 8:
+            set(points[0], points[1],
+                points[2], points[3],
+                points[4], points[5],
+                points[6], points[7]);
+            break;
+        case 6:
+            set(points[0], points[1],
+                points[2], points[3],
+                points[4], points[5]);
+            break;
+        default:
+            throw new InternalError("Curves can only be cubic or quadratic");
+        }
+    }
+
+    void set(float x1, float y1,
+             float x2, float y2,
+             float x3, float y3,
+             float x4, float y4)
+    {
+        ax = 3 * (x2 - x3) + x4 - x1;
+        ay = 3 * (y2 - y3) + y4 - y1;
+        bx = 3 * (x1 - 2 * x2 + x3);
+        by = 3 * (y1 - 2 * y2 + y3);
+        cx = 3 * (x2 - x1);
+        cy = 3 * (y2 - y1);
+        dx = x1;
+        dy = y1;
+        dax = 3 * ax; day = 3 * ay;
+        dbx = 2 * bx; dby = 2 * by;
+    }
+
+    void set(float x1, float y1,
+             float x2, float y2,
+             float x3, float y3)
+    {
+        ax = ay = 0f;
+
+        bx = x1 - 2 * x2 + x3;
+        by = y1 - 2 * y2 + y3;
+        cx = 2 * (x2 - x1);
+        cy = 2 * (y2 - y1);
+        dx = x1;
+        dy = y1;
+        dax = 0; day = 0;
+        dbx = 2 * bx; dby = 2 * by;
+    }
+
+    float xat(float t) {
+        return t * (t * (t * ax + bx) + cx) + dx;
+    }
+    float yat(float t) {
+        return t * (t * (t * ay + by) + cy) + dy;
+    }
+
+    float dxat(float t) {
+        return t * (t * dax + dbx) + cx;
+    }
+
+    float dyat(float t) {
+        return t * (t * day + dby) + cy;
+    }
+
+    private float ddxat(float t) {
+        return 2 * dax * t + dbx;
+    }
+
+    private float ddyat(float t) {
+        return 2 * day * t + dby;
+    }
+
+    int dxRoots(float[] roots, int off) {
+        return Helpers.quadraticRoots(dax, dbx, cx, roots, off);
+    }
+
+    int dyRoots(float[] roots, int off) {
+        return Helpers.quadraticRoots(day, dby, cy, roots, off);
+    }
+
+    int infPoints(float[] pts, int off) {
+        // inflection point at t if -f'(t)x*f''(t)y + f'(t)y*f''(t)x == 0
+        // Fortunately, this turns out to be quadratic, so there are at
+        // most 2 inflection points.
+        final float a = dax * dby - dbx * day;
+        final float b = 2 * (cy * dax - day * cx);
+        final float c = cy * dbx - cx * dby;
+
+        return Helpers.quadraticRoots(a, b, c, pts, off);
+    }
+
+    // finds points where the first and second derivative are
+    // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
+    // * is a dot product). Unfortunately, we have to solve a cubic.
+    private int perpendiculardfddf(float[] pts, int off, final float err) {
+        assert pts.length >= off + 4;
+
+        // these are the coefficients of g(t):
+        final float a = 2*(dax*dax + day*day);
+        final float b = 3*(dax*dbx + day*dby);
+        final float c = 2*(dax*cx + day*cy) + dbx*dbx + dby*dby;
+        final float d = dbx*cx + dby*cy;
+        // TODO: We might want to divide the polynomial by a to make the
+        // coefficients smaller. This won't change the roots.
+        return Helpers.cubicRootsInAB(a, b, c, d, pts, off, err, 0f, 1f);
+    }
+
+    // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
+    // a variant of the false position algorithm to find the roots. False
+    // position requires that 2 initial values x0,x1 be given, and that the
+    // function must have opposite signs at those values. To find such
+    // values, we need the local extrema of the ROC function, for which we
+    // need the roots of its derivative; however, it's harder to find the
+    // roots of the derivative in this case than it is to find the roots
+    // of the original function. So, we find all points where this curve's
+    // first and second derivative are perpendicular, and we pretend these
+    // are our local extrema. There are at most 3 of these, so we will check
+    // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
+    // points, so roc-w can have at least 6 roots. This shouldn't be a
+    // problem for what we're trying to do (draw a nice looking curve).
+    int rootsOfROCMinusW(float[] roots, int off, final float w, final float err) {
+        // no OOB exception, because by now off<=6, and roots.length >= 10
+        assert off <= 6 && roots.length >= 10;
+        int ret = off;
+        int numPerpdfddf = perpendiculardfddf(roots, off, err);
+        float t0 = 0, ft0 = ROCsq(t0) - w*w;
+        roots[off + numPerpdfddf] = 1f; // always check interval end points
+        numPerpdfddf++;
+        for (int i = off; i < off + numPerpdfddf; i++) {
+            float t1 = roots[i], ft1 = ROCsq(t1) - w*w;
+            if (ft0 == 0f) {
+                roots[ret++] = t0;
+            } else if (ft1 * ft0 < 0f) { // have opposite signs
+                // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
+                // ROC(t) >= 0 for all t.
+                roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
+            }
+            t0 = t1;
+            ft0 = ft1;
+        }
+
+        return ret - off;
+    }
+
+    private static float eliminateInf(float x) {
+        return (x == Float.POSITIVE_INFINITY ? Float.MAX_VALUE :
+            (x == Float.NEGATIVE_INFINITY ? Float.MIN_VALUE : x));
+    }
+
+    // A slight modification of the false position algorithm on wikipedia.
+    // This only works for the ROCsq-x functions. It might be nice to have
+    // the function as an argument, but that would be awkward in java6.
+    // It is something to consider for java7, depending on how closures
+    // and function objects turn out. Same goes for the newton's method
+    // algorithm in Helpers.java
+    private float falsePositionROCsqMinusX(float x0, float x1,
+                                           final float x, final float err)
+    {
+        final int iterLimit = 100;
+        int side = 0;
+        float t = x1, ft = eliminateInf(ROCsq(t) - x);
+        float s = x0, fs = eliminateInf(ROCsq(s) - x);
+        float r = s, fr;
+        for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
+            r = (fs * t - ft * s) / (fs - ft);
+            fr = ROCsq(r) - x;
+            if (fr * ft > 0) {// have the same sign
+                ft = fr; t = r;
+                if (side < 0) {
+                    fs /= (1 << (-side));
+                    side--;
+                } else {
+                    side = -1;
+                }
+            } else if (fr * fs > 0) {
+                fs = fr; s = r;
+                if (side > 0) {
+                    ft /= (1 << side);
+                    side++;
+                } else {
+                    side = 1;
+                }
+            } else {
+                break;
+            }
+        }
+        return r;
+    }
+
+    // returns the radius of curvature squared at t of this curve
+    // see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
+    private float ROCsq(final float t) {
+        final float dx = dxat(t);
+        final float dy = dyat(t);
+        final float ddx = ddxat(t);
+        final float ddy = ddyat(t);
+        final float dx2dy2 = dx*dx + dy*dy;
+        final float ddx2ddy2 = ddx*ddx + ddy*ddy;
+        final float ddxdxddydy = ddx*dx + ddy*dy;
+        float ret = ((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy))*dx2dy2;
+        return ret;
+    }
+
+    // curve to be broken should be in pts[0]
+    // this will change the contents of both pts and Ts
+    // TODO: There's no reason for Ts to be an array. All we need is a sequence
+    // of t values at which to subdivide. An array statisfies this condition,
+    // but is unnecessarily restrictive. Ts should be an Iterator<Float> instead.
+    // Doing this will also make dashing easier, since we could easily make
+    // LengthIterator an Iterator<Float> and feed it to this function to simplify
+    // the loop in Dasher.somethingTo.
+    static Iterator<float[]> breakPtsAtTs(final float[][] pts, final int type,
+                                          final float[] Ts, final int numTs)
+    {
+        assert pts.length >= 2 && pts[0].length >= 8 && numTs <= Ts.length;
+        return new Iterator<float[]>() {
+            int nextIdx = 0;
+            int nextCurveIdx = 0;
+            float prevT = 0;
+
+            @Override public boolean hasNext() {
+                return nextCurveIdx < numTs + 1;
+            }
+
+            @Override public float[] next() {
+                float[] ret;
+                if (nextCurveIdx < numTs) {
+                    float curT = Ts[nextCurveIdx];
+                    float splitT = (curT - prevT) / (1 - prevT);
+                    Helpers.subdivideAt(splitT,
+                                        pts[nextIdx], 0,
+                                        pts[nextIdx], 0,
+                                        pts[1-nextIdx], 0, type);
+                    updateTs(Ts, Ts[nextCurveIdx], nextCurveIdx + 1, numTs - nextCurveIdx - 1);
+                    ret = pts[nextIdx];
+                    nextIdx = 1 - nextIdx;
+                } else {
+                    ret = pts[nextIdx];
+                }
+                nextCurveIdx++;
+                return ret;
+            }
+
+            @Override public void remove() {}
+        };
+    }
+
+    // precondition: ts[off]...ts[off+len-1] must all be greater than t.
+    private static void updateTs(float[] ts, final float t, final int off, final int len) {
+        for (int i = off; i < off + len; i++) {
+            ts[i] = (ts[i] - t) / (1 - t);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,6 +25,8 @@
 
 package sun.java2d.pisces;
 
+import sun.awt.geom.PathConsumer2D;
+
 /**
  * The <code>Dasher</code> class takes a series of linear commands
  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
@@ -36,18 +38,16 @@
  * semantics are unclear.
  *
  */
-public class Dasher implements LineSink {
-    private final LineSink output;
+public class Dasher implements sun.awt.geom.PathConsumer2D {
+
+    private final PathConsumer2D out;
     private final float[] dash;
     private final float startPhase;
     private final boolean startDashOn;
     private final int startIdx;
 
-    private final float m00, m10, m01, m11;
-    private final float det;
-
-    private boolean firstDashOn;
     private boolean starting;
+    private boolean needsMoveTo;
 
     private int idx;
     private boolean dashOn;
@@ -55,28 +55,23 @@
 
     private float sx, sy;
     private float x0, y0;
-    private float sx1, sy1;
 
+    // temporary storage for the current curve
+    private float[] curCurvepts;
 
     /**
      * Constructs a <code>Dasher</code>.
      *
-     * @param output an output <code>LineSink</code>.
-     * @param dash an array of <code>int</code>s containing the dash pattern
-     * @param phase an <code>int</code> containing the dash phase
-     * @param transform a <code>Transform4</code> object indicating
-     * the transform that has been previously applied to all incoming
-     * coordinates.  This is required in order to compute dash lengths
-     * properly.
+     * @param out an output <code>PathConsumer2D</code>.
+     * @param dash an array of <code>float</code>s containing the dash pattern
+     * @param phase a <code>float</code> containing the dash phase
      */
-    public Dasher(LineSink output,
-                  float[] dash, float phase,
-                  float a00, float a01, float a10, float a11) {
+    public Dasher(PathConsumer2D out, float[] dash, float phase) {
         if (phase < 0) {
             throw new IllegalArgumentException("phase < 0 !");
         }
 
-        this.output = output;
+        this.out = out;
 
         // Normalize so 0 <= phase < dash[0]
         int idx = 0;
@@ -92,16 +87,19 @@
         this.startPhase = this.phase = phase;
         this.startDashOn = dashOn;
         this.startIdx = idx;
+        this.starting = true;
 
-        m00 = a00;
-        m01 = a01;
-        m10 = a10;
-        m11 = a11;
-        det = m00 * m11 - m01 * m10;
+        // we need curCurvepts to be able to contain 2 curves because when
+        // dashing curves, we need to subdivide it
+        curCurvepts = new float[8 * 2];
     }
 
     public void moveTo(float x0, float y0) {
-        output.moveTo(x0, y0);
+        if (firstSegidx > 0) {
+            out.moveTo(sx, sy);
+            emitFirstSegments();
+        }
+        needsMoveTo = true;
         this.idx = startIdx;
         this.dashOn = this.startDashOn;
         this.phase = this.startPhase;
@@ -110,88 +108,108 @@
         this.starting = true;
     }
 
-    public void lineJoin() {
-        output.lineJoin();
+    private void emitSeg(float[] buf, int off, int type) {
+        switch (type) {
+        case 8:
+            out.curveTo(buf[off+0], buf[off+1],
+                        buf[off+2], buf[off+3],
+                        buf[off+4], buf[off+5]);
+            break;
+        case 6:
+            out.quadTo(buf[off+0], buf[off+1],
+                       buf[off+2], buf[off+3]);
+            break;
+        case 4:
+            out.lineTo(buf[off], buf[off+1]);
+        }
     }
 
-    private void goTo(float x1, float y1) {
+    private void emitFirstSegments() {
+        for (int i = 0; i < firstSegidx; ) {
+            emitSeg(firstSegmentsBuffer, i+1, (int)firstSegmentsBuffer[i]);
+            i += (((int)firstSegmentsBuffer[i]) - 1);
+        }
+        firstSegidx = 0;
+    }
+
+    // We don't emit the first dash right away. If we did, caps would be
+    // drawn on it, but we need joins to be drawn if there's a closePath()
+    // So, we store the path elements that make up the first dash in the
+    // buffer below.
+    private float[] firstSegmentsBuffer = new float[7];
+    private int firstSegidx = 0;
+    // precondition: pts must be in relative coordinates (relative to x0,y0)
+    // fullCurve is true iff the curve in pts has not been split.
+    private void goTo(float[] pts, int off, final int type) {
+        float x = pts[off + type - 4];
+        float y = pts[off + type - 3];
         if (dashOn) {
             if (starting) {
-                this.sx1 = x1;
-                this.sy1 = y1;
-                firstDashOn = true;
-                starting = false;
+                firstSegmentsBuffer = Helpers.widenArray(firstSegmentsBuffer,
+                                      firstSegidx, type - 2);
+                firstSegmentsBuffer[firstSegidx++] = type;
+                System.arraycopy(pts, off, firstSegmentsBuffer, firstSegidx, type - 2);
+                firstSegidx += type - 2;
+            } else {
+                if (needsMoveTo) {
+                    out.moveTo(x0, y0);
+                    needsMoveTo = false;
+                }
+                emitSeg(pts, off, type);
             }
-            output.lineTo(x1, y1);
         } else {
-            if (starting) {
-                firstDashOn = false;
-                starting = false;
-            }
-            output.moveTo(x1, y1);
+            starting = false;
+            needsMoveTo = true;
         }
-        this.x0 = x1;
-        this.y0 = y1;
+        this.x0 = x;
+        this.y0 = y;
     }
 
     public void lineTo(float x1, float y1) {
-        // The widened line is squished to a 0 width one, so no drawing is done
-        if (det == 0) {
-            goTo(x1, y1);
-            return;
-        }
         float dx = x1 - x0;
         float dy = y1 - y0;
 
-
-        // Compute segment length in the untransformed
-        // coordinate system
+        float len = (float) Math.hypot(dx, dy);
 
-        float la = (dy*m00 - dx*m10)/det;
-        float lb = (dy*m01 - dx*m11)/det;
-        float origLen = (float) Math.hypot(la, lb);
-
-        if (origLen == 0) {
-            // Let the output LineSink deal with cases where dx, dy are 0.
-            goTo(x1, y1);
+        if (len == 0) {
             return;
         }
 
         // The scaling factors needed to get the dx and dy of the
         // transformed dash segments.
-        float cx = dx / origLen;
-        float cy = dy / origLen;
+        float cx = dx / len;
+        float cy = dy / len;
 
         while (true) {
             float leftInThisDashSegment = dash[idx] - phase;
-            if (origLen < leftInThisDashSegment) {
-                goTo(x1, y1);
+            if (len <= leftInThisDashSegment) {
+                curCurvepts[0] = x1;
+                curCurvepts[1] = y1;
+                goTo(curCurvepts, 0, 4);
                 // Advance phase within current dash segment
-                phase += origLen;
-                return;
-            } else if (origLen == leftInThisDashSegment) {
-                goTo(x1, y1);
-                phase = 0f;
-                idx = (idx + 1) % dash.length;
-                dashOn = !dashOn;
+                phase += len;
+                if (len == leftInThisDashSegment) {
+                    phase = 0f;
+                    idx = (idx + 1) % dash.length;
+                    dashOn = !dashOn;
+                }
                 return;
             }
 
-            float dashx, dashy;
             float dashdx = dash[idx] * cx;
             float dashdy = dash[idx] * cy;
             if (phase == 0) {
-                dashx = x0 + dashdx;
-                dashy = y0 + dashdy;
+                curCurvepts[0] = x0 + dashdx;
+                curCurvepts[1] = y0 + dashdy;
             } else {
-                float p = (leftInThisDashSegment) / dash[idx];
-                dashx = x0 + p * dashdx;
-                dashy = y0 + p * dashdy;
+                float p = leftInThisDashSegment / dash[idx];
+                curCurvepts[0] = x0 + p * dashdx;
+                curCurvepts[1] = y0 + p * dashdy;
             }
 
-            goTo(dashx, dashy);
+            goTo(curCurvepts, 0, 4);
 
-            origLen -= (dash[idx] - phase);
+            len -= leftInThisDashSegment;
             // Advance to next dash segment
             idx = (idx + 1) % dash.length;
             dashOn = !dashOn;
@@ -199,15 +217,289 @@
         }
     }
 
+    private LengthIterator li = null;
 
-    public void close() {
-        lineTo(sx, sy);
-        if (firstDashOn) {
-            output.lineTo(sx1, sy1);
+    // preconditions: curCurvepts must be an array of length at least 2 * type,
+    // that contains the curve we want to dash in the first type elements
+    private void somethingTo(int type) {
+        if (pointCurve(curCurvepts, type)) {
+            return;
+        }
+        if (li == null) {
+            li = new LengthIterator(4, 0.0001f);
+        }
+        li.initializeIterationOnCurve(curCurvepts, type);
+
+        int curCurveoff = 0; // initially the current curve is at curCurvepts[0...type]
+        float lastSplitT = 0;
+        float t = 0;
+        float leftInThisDashSegment = dash[idx] - phase;
+        while ((t = li.next(leftInThisDashSegment)) < 1) {
+            if (t != 0) {
+                Helpers.subdivideAt((t - lastSplitT) / (1 - lastSplitT),
+                        curCurvepts, curCurveoff,
+                        curCurvepts, 0,
+                        curCurvepts, type, type);
+                lastSplitT = t;
+                goTo(curCurvepts, 2, type);
+                curCurveoff = type;
+            }
+            // Advance to next dash segment
+            idx = (idx + 1) % dash.length;
+            dashOn = !dashOn;
+            phase = 0;
+            leftInThisDashSegment = dash[idx];
+        }
+        goTo(curCurvepts, curCurveoff+2, type);
+        phase += li.lastSegLen();
+        if (phase >= dash[idx]) {
+            phase = 0f;
+            idx = (idx + 1) % dash.length;
+            dashOn = !dashOn;
         }
     }
 
-    public void end() {
-        output.end();
+    private static boolean pointCurve(float[] curve, int type) {
+        for (int i = 2; i < type; i++) {
+            if (curve[i] != curve[i-2]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Objects of this class are used to iterate through curves. They return
+    // t values where the left side of the curve has a specified length.
+    // It does this by subdividing the input curve until a certain error
+    // condition has been met. A recursive subdivision procedure would
+    // return as many as 1<<limit curves, but this is an iterator and we
+    // don't need all the curves all at once, so what we carry out a
+    // lazy inorder traversal of the recursion tree (meaning we only move
+    // through the tree when we need the next subdivided curve). This saves
+    // us a lot of memory because at any one time we only need to store
+    // limit+1 curves - one for each level of the tree + 1.
+    // NOTE: the way we do things here is not enough to traverse a general
+    // tree; however, the trees we are interested in have the property that
+    // every non leaf node has exactly 2 children
+    private static class LengthIterator {
+        private enum Side {LEFT, RIGHT};
+        // Holds the curves at various levels of the recursion. The root
+        // (i.e. the original curve) is at recCurveStack[0] (but then it
+        // gets subdivided, the left half is put at 1, so most of the time
+        // only the right half of the original curve is at 0)
+        private float[][] recCurveStack;
+        // sides[i] indicates whether the node at level i+1 in the path from
+        // the root to the current leaf is a left or right child of its parent.
+        private Side[] sides;
+        private int curveType;
+        private final int limit;
+        private final float ERR;
+        private final float minTincrement;
+        // lastT and nextT delimit the current leaf.
+        private float nextT;
+        private float lenAtNextT;
+        private float lastT;
+        private float lenAtLastT;
+        private float lenAtLastSplit;
+        private float lastSegLen;
+        // the current level in the recursion tree. 0 is the root. limit
+        // is the deepest possible leaf.
+        private int recLevel;
+        private boolean done;
+
+        public LengthIterator(int reclimit, float err) {
+            this.limit = reclimit;
+            this.minTincrement = 1f / (1 << limit);
+            this.ERR = err;
+            this.recCurveStack = new float[reclimit+1][8];
+            this.sides = new Side[reclimit];
+            // if any methods are called without first initializing this object on
+            // a curve, we want it to fail ASAP.
+            this.nextT = Float.MAX_VALUE;
+            this.lenAtNextT = Float.MAX_VALUE;
+            this.lenAtLastSplit = Float.MIN_VALUE;
+            this.recLevel = Integer.MIN_VALUE;
+            this.lastSegLen = Float.MAX_VALUE;
+            this.done = true;
+        }
+
+        public void initializeIterationOnCurve(float[] pts, int type) {
+            System.arraycopy(pts, 0, recCurveStack[0], 0, type);
+            this.curveType = type;
+            this.recLevel = 0;
+            this.lastT = 0;
+            this.lenAtLastT = 0;
+            this.nextT = 0;
+            this.lenAtNextT = 0;
+            goLeft(); // initializes nextT and lenAtNextT properly
+            this.lenAtLastSplit = 0;
+            if (recLevel > 0) {
+                this.sides[0] = Side.LEFT;
+                this.done = false;
+            } else {
+                // the root of the tree is a leaf so we're done.
+                this.sides[0] = Side.RIGHT;
+                this.done = true;
+            }
+            this.lastSegLen = 0;
+        }
+
+        // returns the t value where the remaining curve should be split in
+        // order for the left subdivided curve to have length len. If len
+        // is >= than the length of the uniterated curve, it returns 1.
+        public float next(float len) {
+            float targetLength = lenAtLastSplit + len;
+            while(lenAtNextT < targetLength) {
+                if (done) {
+                    lastSegLen = lenAtNextT - lenAtLastSplit;
+                    return 1;
+                }
+                goToNextLeaf();
+            }
+            lenAtLastSplit = targetLength;
+            float t = binSearchForLen(lenAtLastSplit - lenAtLastT,
+                    recCurveStack[recLevel], curveType, lenAtNextT - lenAtLastT, ERR);
+            // t is relative to the current leaf, so we must make it a valid parameter
+            // of the original curve.
+            t = t * (nextT - lastT) + lastT;
+            if (t >= 1) {
+                t = 1;
+                done = true;
+            }
+            // even if done = true, if we're here, that means targetLength
+            // is equal to, or very, very close to the total length of the
+            // curve, so lastSegLen won't be too high. In cases where len
+            // overshoots the curve, this method will exit in the while
+            // loop, and lastSegLen will still be set to the right value.
+            lastSegLen = len;
+            return t;
+        }
+
+        public float lastSegLen() {
+            return lastSegLen;
+        }
+
+        // Returns t such that if leaf is subdivided at t the left
+        // curve will have length len. leafLen must be the length of leaf.
+        private static Curve bsc = new Curve();
+        private static float binSearchForLen(float len, float[] leaf, int type,
+                                             float leafLen, float err)
+        {
+            assert len <= leafLen;
+            bsc.set(leaf, type);
+            float errBound = err*len;
+            float left = 0, right = 1;
+            while (left < right) {
+                float m = (left + right) / 2;
+                if (m == left || m == right) {
+                    return m;
+                }
+                float x = bsc.xat(m);
+                float y = bsc.yat(m);
+                float leftLen = Helpers.linelen(leaf[0], leaf[1], x, y);
+                if (Math.abs(leftLen - len) < errBound) {
+                    return m;
+                }
+                if (leftLen < len) {
+                    left = m;
+                } else {
+                    right = m;
+                }
+            }
+            return left;
+        }
+
+        // go to the next leaf (in an inorder traversal) in the recursion tree
+        // preconditions: must be on a leaf, and that leaf must not be the root.
+        private void goToNextLeaf() {
+            // We must go to the first ancestor node that has an unvisited
+            // right child.
+            recLevel--;
+            while(sides[recLevel] == Side.RIGHT) {
+                if (recLevel == 0) {
+                    done = true;
+                    return;
+                }
+                recLevel--;
+            }
+
+            sides[recLevel] = Side.RIGHT;
+            System.arraycopy(recCurveStack[recLevel], 0, recCurveStack[recLevel+1], 0, curveType);
+            recLevel++;
+            goLeft();
+        }
+
+        // go to the leftmost node from the current node. Return its length.
+        private void goLeft() {
+            float len = onLeaf();
+            if (len >= 0) {
+                lastT = nextT;
+                lenAtLastT = lenAtNextT;
+                nextT += (1 << (limit - recLevel)) * minTincrement;
+                lenAtNextT += len;
+            } else {
+                Helpers.subdivide(recCurveStack[recLevel], 0,
+                                  recCurveStack[recLevel+1], 0,
+                                  recCurveStack[recLevel], 0, curveType);
+                sides[recLevel] = Side.LEFT;
+                recLevel++;
+                goLeft();
+            }
+        }
+
+        // this is a bit of a hack. It returns -1 if we're not on a leaf, and
+        // the length of the leaf if we are on a leaf.
+        private float onLeaf() {
+            float polylen = Helpers.polyLineLength(recCurveStack[recLevel], 0, curveType);
+            float linelen = Helpers.linelen(recCurveStack[recLevel][0], recCurveStack[recLevel][1],
+                    recCurveStack[recLevel][curveType - 2], recCurveStack[recLevel][curveType - 1]);
+            return (polylen - linelen < ERR || recLevel == limit) ?
+                   (polylen + linelen)/2 : -1;
+        }
+    }
+
+    @Override
+    public void curveTo(float x1, float y1,
+                        float x2, float y2,
+                        float x3, float y3)
+    {
+        curCurvepts[0] = x0;        curCurvepts[1] = y0;
+        curCurvepts[2] = x1;        curCurvepts[3] = y1;
+        curCurvepts[4] = x2;        curCurvepts[5] = y2;
+        curCurvepts[6] = x3;        curCurvepts[7] = y3;
+        somethingTo(8);
+    }
+
+    @Override
+    public void quadTo(float x1, float y1, float x2, float y2) {
+        curCurvepts[0] = x0;        curCurvepts[1] = y0;
+        curCurvepts[2] = x1;        curCurvepts[3] = y1;
+        curCurvepts[4] = x2;        curCurvepts[5] = y2;
+        somethingTo(6);
+    }
+
+    public void closePath() {
+        lineTo(sx, sy);
+        if (firstSegidx > 0) {
+            if (!dashOn || needsMoveTo) {
+                out.moveTo(sx, sy);
+            }
+            emitFirstSegments();
+        }
+        moveTo(sx, sy);
+    }
+
+    public void pathDone() {
+        if (firstSegidx > 0) {
+            out.moveTo(sx, sy);
+            emitFirstSegments();
+        }
+        out.pathDone();
+    }
+
+    @Override
+    public long getNativeConsumer() {
+        throw new InternalError("Dasher does not use a native consumer");
     }
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/Helpers.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,478 @@
+/*
+ * 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 sun.java2d.pisces;
+
+import java.util.Arrays;
+
+final class Helpers {
+    private Helpers() {
+        throw new Error("This is a non instantiable class");
+    }
+
+    static boolean within(final float x, final float y, final float err) {
+        final float d = y - x;
+        return (d <= err && d >= -err);
+    }
+
+    static boolean within(final double x, final double y, final double err) {
+        final double d = y - x;
+        return (d <= err && d >= -err);
+    }
+
+    static int quadraticRoots(final float a, final float b,
+                              final float c, float[] zeroes, final int off)
+    {
+        int ret = off;
+        float t;
+        if (a != 0f) {
+            final float dis = b*b - 4*a*c;
+            if (dis > 0) {
+                final float sqrtDis = (float)Math.sqrt(dis);
+                // depending on the sign of b we use a slightly different
+                // algorithm than the traditional one to find one of the roots
+                // so we can avoid adding numbers of different signs (which
+                // might result in loss of precision).
+                if (b >= 0) {
+                    zeroes[ret++] = (2 * c) / (-b - sqrtDis);
+                    zeroes[ret++] = (-b - sqrtDis) / (2 * a);
+                } else {
+                    zeroes[ret++] = (-b + sqrtDis) / (2 * a);
+                    zeroes[ret++] = (2 * c) / (-b + sqrtDis);
+                }
+            } else if (dis == 0f) {
+                t = (-b) / (2 * a);
+                zeroes[ret++] = t;
+            }
+        } else {
+            if (b != 0f) {
+                t = (-c) / b;
+                zeroes[ret++] = t;
+            }
+        }
+        return ret - off;
+    }
+
+    // find the roots of g(t) = a*t^3 + b*t^2 + c*t + d in [A,B)
+    // We will not use Cardano's method, since it is complicated and
+    // involves too many square and cubic roots. We will use Newton's method.
+    // TODO: this should probably return ALL roots. Then the user can do
+    // his own filtering of roots outside [A,B).
+    static int cubicRootsInAB(final float a, final float b,
+                              final float c, final float d,
+                              float[] pts, final int off, final float E,
+                              final float A, final float B)
+    {
+        if (a == 0) {
+            return quadraticRoots(b, c, d, pts, off);
+        }
+        // the coefficients of g'(t). no dc variable because dc=c
+        // we use these to get the critical points of g(t), which
+        // we then use to chose starting points for Newton's method. These
+        // should be very close to the actual roots.
+        final float da = 3 * a;
+        final float db = 2 * b;
+        int numCritPts = quadraticRoots(da, db, c, pts, off+1);
+        numCritPts = filterOutNotInAB(pts, off+1, numCritPts, A, B) - off - 1;
+        // need them sorted.
+        if (numCritPts == 2 && pts[off+1] > pts[off+2]) {
+            float tmp = pts[off+1];
+            pts[off+1] = pts[off+2];
+            pts[off+2] = tmp;
+        }
+
+        int ret = off;
+
+        // we don't actually care much about the extrema themselves. We
+        // only use them to ensure that g(t) is monotonic in each
+        // interval [pts[i],pts[i+1] (for i in off...off+numCritPts+1).
+        // This will allow us to determine intervals containing exactly
+        // one root.
+        // The end points of the interval are always local extrema.
+        pts[off] = A;
+        pts[off + numCritPts + 1] = B;
+        numCritPts += 2;
+
+        float x0 = pts[off], fx0 = evalCubic(a, b, c, d, x0);
+        for (int i = off; i < off + numCritPts - 1; i++) {
+            float x1 = pts[i+1], fx1 = evalCubic(a, b, c, d, x1);
+            if (fx0 == 0f) {
+                pts[ret++] = x0;
+            } else if (fx1 * fx0 < 0f) { // have opposite signs
+                pts[ret++] = CubicNewton(a, b, c, d,
+                        x0 + fx0 * (x1 - x0) / (fx0 - fx1), E);
+            }
+            x0 = x1;
+            fx0 = fx1;
+        }
+        return ret - off;
+    }
+
+    // precondition: the polynomial to be evaluated must not be 0 at x0.
+    static float CubicNewton(final float a, final float b,
+                             final float c, final float d,
+                             float x0, final float err)
+    {
+        // considering how this function is used, 10 should be more than enough
+        final int itlimit = 10;
+        float fx0 = evalCubic(a, b, c, d, x0);
+        float x1;
+        int count = 0;
+        while(true) {
+            x1 = x0 - (fx0 / evalCubic(0, 3 * a, 2 * b, c, x0));
+            if (Math.abs(x1 - x0) < err * Math.abs(x1 + x0) || count == itlimit) {
+                break;
+            }
+            x0 = x1;
+            fx0 = evalCubic(a, b, c, d, x0);
+            count++;
+        }
+        return x1;
+    }
+
+    // fills the input array with numbers 0, INC, 2*INC, ...
+    static void fillWithIdxes(final float[] data, final int[] idxes) {
+        if (idxes.length > 0) {
+            idxes[0] = 0;
+            for (int i = 1; i < idxes.length; i++) {
+                idxes[i] = idxes[i-1] + (int)data[idxes[i-1]];
+            }
+        }
+    }
+
+    static void fillWithIdxes(final int[] idxes, final int inc) {
+        if (idxes.length > 0) {
+            idxes[0] = 0;
+            for (int i = 1; i < idxes.length; i++) {
+                idxes[i] = idxes[i-1] + inc;
+            }
+        }
+    }
+
+    // These use a hardcoded factor of 2 for increasing sizes. Perhaps this
+    // should be provided as an argument.
+    static float[] widenArray(float[] in, final int cursize, final int numToAdd) {
+        if (in == null) {
+            return new float[5 * numToAdd];
+        }
+        if (in.length >= cursize + numToAdd) {
+            return in;
+        }
+        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
+    }
+    static int[] widenArray(int[] in, final int cursize, final int numToAdd) {
+        if (in.length >= cursize + numToAdd) {
+            return in;
+        }
+        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
+    }
+
+    static float evalCubic(final float a, final float b,
+                           final float c, final float d,
+                           final float t)
+    {
+        return t * (t * (t * a + b) + c) + d;
+    }
+
+    static float evalQuad(final float a, final float b,
+                          final float c, final float t)
+    {
+        return t * (t * a + b) + c;
+    }
+
+    // returns the index 1 past the last valid element remaining after filtering
+    static int filterOutNotInAB(float[] nums, final int off, final int len,
+                                final float a, final float b)
+    {
+        int ret = off;
+        for (int i = off; i < off + len; i++) {
+            if (nums[i] > a && nums[i] < b) {
+                nums[ret++] = nums[i];
+            }
+        }
+        return ret;
+    }
+
+    static float polyLineLength(float[] poly, final int off, final int nCoords) {
+        assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
+        float acc = 0;
+        for (int i = off + 2; i < off + nCoords; i += 2) {
+            acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
+        }
+        return acc;
+    }
+
+    static float linelen(float x1, float y1, float x2, float y2) {
+        return (float)Math.hypot(x2 - x1, y2 - y1);
+    }
+
+    static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
+                          float[] right, int rightoff, int type)
+    {
+        switch(type) {
+        case 6:
+            Helpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
+            break;
+        case 8:
+            Helpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
+            break;
+        default:
+            throw new InternalError("Unsupported curve type");
+        }
+    }
+
+    static void isort(float[] a, int off, int len) {
+        for (int i = off + 1; i < off + len; i++) {
+            float ai = a[i];
+            int j = i - 1;
+            for (; j >= off && a[j] > ai; j--) {
+                a[j+1] = a[j];
+            }
+            a[j+1] = ai;
+        }
+    }
+
+    // Most of these are copied from classes in java.awt.geom because we need
+    // float versions of these functions, and Line2D, CubicCurve2D,
+    // QuadCurve2D don't provide them.
+    /**
+     * Subdivides the cubic curve specified by the coordinates
+     * stored in the <code>src</code> array at indices <code>srcoff</code>
+     * through (<code>srcoff</code>&nbsp;+&nbsp;7) and stores the
+     * resulting two subdivided curves into the two result arrays at the
+     * corresponding indices.
+     * Either or both of the <code>left</code> and <code>right</code>
+     * arrays may be <code>null</code> or a reference to the same array
+     * as the <code>src</code> array.
+     * Note that the last point in the first subdivided curve is the
+     * same as the first point in the second subdivided curve. Thus,
+     * it is possible to pass the same array for <code>left</code>
+     * and <code>right</code> and to use offsets, such as <code>rightoff</code>
+     * equals (<code>leftoff</code> + 6), in order
+     * to avoid allocating extra storage for this common point.
+     * @param src the array holding the coordinates for the source curve
+     * @param srcoff the offset into the array of the beginning of the
+     * the 6 source coordinates
+     * @param left the array for storing the coordinates for the first
+     * half of the subdivided curve
+     * @param leftoff the offset into the array of the beginning of the
+     * the 6 left coordinates
+     * @param right the array for storing the coordinates for the second
+     * half of the subdivided curve
+     * @param rightoff the offset into the array of the beginning of the
+     * the 6 right coordinates
+     * @since 1.7
+     */
+    static void subdivideCubic(float src[], int srcoff,
+                               float left[], int leftoff,
+                               float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx1 = src[srcoff + 2];
+        float ctrly1 = src[srcoff + 3];
+        float ctrlx2 = src[srcoff + 4];
+        float ctrly2 = src[srcoff + 5];
+        float x2 = src[srcoff + 6];
+        float y2 = src[srcoff + 7];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 6] = x2;
+            right[rightoff + 7] = y2;
+        }
+        x1 = (x1 + ctrlx1) / 2.0f;
+        y1 = (y1 + ctrly1) / 2.0f;
+        x2 = (x2 + ctrlx2) / 2.0f;
+        y2 = (y2 + ctrly2) / 2.0f;
+        float centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        float centery = (ctrly1 + ctrly2) / 2.0f;
+        ctrlx1 = (x1 + centerx) / 2.0f;
+        ctrly1 = (y1 + centery) / 2.0f;
+        ctrlx2 = (x2 + centerx) / 2.0f;
+        ctrly2 = (y2 + centery) / 2.0f;
+        centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        centery = (ctrly1 + ctrly2) / 2.0f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx1;
+            left[leftoff + 5] = ctrly1;
+            left[leftoff + 6] = centerx;
+            left[leftoff + 7] = centery;
+        }
+        if (right != null) {
+            right[rightoff + 0] = centerx;
+            right[rightoff + 1] = centery;
+            right[rightoff + 2] = ctrlx2;
+            right[rightoff + 3] = ctrly2;
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+    }
+
+
+    static void subdivideCubicAt(float t, float src[], int srcoff,
+                                 float left[], int leftoff,
+                                 float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx1 = src[srcoff + 2];
+        float ctrly1 = src[srcoff + 3];
+        float ctrlx2 = src[srcoff + 4];
+        float ctrly2 = src[srcoff + 5];
+        float x2 = src[srcoff + 6];
+        float y2 = src[srcoff + 7];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 6] = x2;
+            right[rightoff + 7] = y2;
+        }
+        x1 = x1 + t * (ctrlx1 - x1);
+        y1 = y1 + t * (ctrly1 - y1);
+        x2 = ctrlx2 + t * (x2 - ctrlx2);
+        y2 = ctrly2 + t * (y2 - ctrly2);
+        float centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
+        float centery = ctrly1 + t * (ctrly2 - ctrly1);
+        ctrlx1 = x1 + t * (centerx - x1);
+        ctrly1 = y1 + t * (centery - y1);
+        ctrlx2 = centerx + t * (x2 - centerx);
+        ctrly2 = centery + t * (y2 - centery);
+        centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
+        centery = ctrly1 + t * (ctrly2 - ctrly1);
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx1;
+            left[leftoff + 5] = ctrly1;
+            left[leftoff + 6] = centerx;
+            left[leftoff + 7] = centery;
+        }
+        if (right != null) {
+            right[rightoff + 0] = centerx;
+            right[rightoff + 1] = centery;
+            right[rightoff + 2] = ctrlx2;
+            right[rightoff + 3] = ctrly2;
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+    }
+
+    static void subdivideQuad(float src[], int srcoff,
+                              float left[], int leftoff,
+                              float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = (x1 + ctrlx) / 2.0f;
+        y1 = (y1 + ctrly) / 2.0f;
+        x2 = (x2 + ctrlx) / 2.0f;
+        y2 = (y2 + ctrly) / 2.0f;
+        ctrlx = (x1 + x2) / 2.0f;
+        ctrly = (y1 + y2) / 2.0f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    static void subdivideQuadAt(float t, float src[], int srcoff,
+                                float left[], int leftoff,
+                                float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = x1 + t * (ctrlx - x1);
+        y1 = y1 + t * (ctrly - y1);
+        x2 = ctrlx + t * (x2 - ctrlx);
+        y2 = ctrly + t * (y2 - ctrly);
+        ctrlx = x1 + t * (x2 - x1);
+        ctrly = y1 + t * (y2 - y1);
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    static void subdivideAt(float t, float src[], int srcoff,
+                            float left[], int leftoff,
+                            float right[], int rightoff, int size)
+    {
+        switch(size) {
+        case 8:
+            subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
+            break;
+        case 6:
+            subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
+            break;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/java2d/pisces/LineSink.java	Tue Nov 09 11:45:00 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +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 sun.java2d.pisces;
-
-/**
- * The <code>LineSink</code> interface accepts a series of line
- * drawing commands: <code>moveTo</code>, <code>lineTo</code>,
- * <code>close</code> (equivalent to a <code>lineTo</code> command
- * with an argument equal to the argument of the last
- * <code>moveTo</code> command), and <code>end</code>.
- *
- * <p> A <code>Flattener</code> may be used to connect a general path
- * source to a <code>LineSink</code>.
- *
- * <p> The <code>Renderer</code> class implements the
- * <code>LineSink</code> interface.
- *
- */
-public interface LineSink {
-
-    /**
-     * Moves the current drawing position to the point <code>(x0,
-     * y0)</code>.
-     *
-     * @param x0 the X coordinate
-     * @param y0 the Y coordinate
-     */
-    public void moveTo(float x0, float y0);
-
-    /**
-     * Provides a hint that the current segment should be joined to
-     * the following segment using an explicit miter or round join if
-     * required.
-     *
-     * <p> An application-generated path will generally have no need
-     * to contain calls to this method; they are typically introduced
-     * by a <code>Flattener</code> to mark segment divisions that
-     * appear in its input, and consumed by a <code>Stroker</code>
-     * that is responsible for emitting the miter or round join
-     * segments.
-     *
-     * <p> Other <code>LineSink</code> classes should simply pass this
-     * hint to their output sink as needed.
-     */
-    public void lineJoin();
-
-    /**
-     * Draws a line from the current drawing position to the point
-     * <code>(x1, y1)</code> and sets the current drawing position to
-     * <code>(x1, y1)</code>.
-     *
-     * @param x1 the X coordinate
-     * @param y1 the Y coordinate
-     */
-    public void lineTo(float x1, float y1);
-
-    /**
-     * Closes the current path by drawing a line from the current
-     * drawing position to the point specified by the moset recent
-     * <code>moveTo</code> command.
-     */
-    public void close();
-
-    /**
-     * Ends the current path.  It may be necessary to end a path in
-     * order to allow end caps to be drawn.
-     */
-    public void end();
-
-}
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,6 +25,8 @@
 
 package sun.java2d.pisces;
 
+import java.util.Arrays;
+
 /**
  * An object used to cache pre-rendered complex paths.
  *
@@ -32,115 +34,153 @@
  */
 public final class PiscesCache {
 
-    int bboxX0, bboxY0, bboxX1, bboxY1;
+    final int bboxX0, bboxY0, bboxX1, bboxY1;
+
+    // rowAARLE[i] holds the encoding of the pixel row with y = bboxY0+i.
+    // The format of each of the inner arrays is: rowAARLE[i][0,1] = (x0, n)
+    // where x0 is the first x in row i with nonzero alpha, and n is the
+    // number of RLE entries in this row. rowAARLE[i][j,j+1] for j>1 is
+    // (val,runlen)
+    final int[][] rowAARLE;
 
-    byte[] rowAARLE;
-    int alphaRLELength;
+    // RLE encodings are added in increasing y rows and then in increasing
+    // x inside those rows. Therefore, at any one time there is a well
+    // defined position (x,y) where a run length is about to be added (or
+    // the row terminated). x0,y0 is this (x,y)-(bboxX0,bboxY0). They
+    // are used to get indices into the current tile.
+    private int x0 = Integer.MIN_VALUE, y0 = Integer.MIN_VALUE;
+
+    // touchedTile[i][j] is the sum of all the alphas in the tile with
+    // y=i*TILE_SIZE+bboxY0 and x=j*TILE_SIZE+bboxX0.
+    private final int[][] touchedTile;
 
-    int[] rowOffsetsRLE;
-    int[] minTouched;
-    int alphaRows;
+    static final int TILE_SIZE_LG = 5;
+    static final int TILE_SIZE = 1 << TILE_SIZE_LG; // 32
+    private static final int INIT_ROW_SIZE = 8; // enough for 3 run lengths
 
-    private PiscesCache() {}
+    PiscesCache(int minx, int miny, int maxx, int maxy) {
+        assert maxy >= miny && maxx >= minx;
+        bboxX0 = minx;
+        bboxY0 = miny;
+        bboxX1 = maxx + 1;
+        bboxY1 = maxy + 1;
+        // we could just leave the inner arrays as null and allocate them
+        // lazily (which would be beneficial for shapes with gaps), but we
+        // assume there won't be too many of those so we allocate everything
+        // up front (which is better for other cases)
+        rowAARLE = new int[bboxY1 - bboxY0 + 1][INIT_ROW_SIZE];
+        x0 = 0;
+        y0 = -1; // -1 makes the first assert in startRow succeed
+        // the ceiling of (maxy - miny + 1) / TILE_SIZE;
+        int nyTiles = (maxy - miny + TILE_SIZE) >> TILE_SIZE_LG;
+        int nxTiles = (maxx - minx + TILE_SIZE) >> TILE_SIZE_LG;
 
-    public static PiscesCache createInstance() {
-        return new PiscesCache();
+        touchedTile = new int[nyTiles][nxTiles];
     }
 
-    private static final float ROWAA_RLE_FACTOR = 1.5f;
-    private static final float TOUCHED_FACTOR = 1.5f;
-    private static final int MIN_TOUCHED_LEN = 64;
-
-    private void reallocRowAARLE(int newLength) {
-        if (rowAARLE == null) {
-            rowAARLE = new byte[newLength];
-        } else if (rowAARLE.length < newLength) {
-            int len = Math.max(newLength,
-                               (int)(rowAARLE.length*ROWAA_RLE_FACTOR));
-            byte[] newRowAARLE = new byte[len];
-            System.arraycopy(rowAARLE, 0, newRowAARLE, 0, rowAARLE.length);
-            rowAARLE = newRowAARLE;
-        }
-    }
-
-    private void reallocRowInfo(int newHeight) {
-        if (minTouched == null) {
-            int len = Math.max(newHeight, MIN_TOUCHED_LEN);
-            minTouched = new int[len];
-            rowOffsetsRLE = new int[len];
-        } else if (minTouched.length < newHeight) {
-            int len = Math.max(newHeight,
-                               (int)(minTouched.length*TOUCHED_FACTOR));
-            int[] newMinTouched = new int[len];
-            int[] newRowOffsetsRLE = new int[len];
-            System.arraycopy(minTouched, 0, newMinTouched, 0,
-                             alphaRows);
-            System.arraycopy(rowOffsetsRLE, 0, newRowOffsetsRLE, 0,
-                             alphaRows);
-            minTouched = newMinTouched;
-            rowOffsetsRLE = newRowOffsetsRLE;
+    void addRLERun(int val, int runLen) {
+        if (runLen > 0) {
+            addTupleToRow(y0, val, runLen);
+            if (val != 0) {
+                // the x and y of the current row, minus bboxX0, bboxY0
+                int tx = x0 >> TILE_SIZE_LG;
+                int ty = y0 >> TILE_SIZE_LG;
+                int tx1 = (x0 + runLen - 1) >> TILE_SIZE_LG;
+                // while we forbid rows from starting before bboxx0, our users
+                // can still store rows that go beyond bboxx1 (although this
+                // shouldn't happen), so it's a good idea to check that i
+                // is not going out of bounds in touchedTile[ty]
+                if (tx1 >= touchedTile[ty].length) {
+                    tx1 = touchedTile[ty].length - 1;
+                }
+                if (tx <= tx1) {
+                    int nextTileXCoord = (tx + 1) << TILE_SIZE_LG;
+                    if (nextTileXCoord > x0+runLen) {
+                        touchedTile[ty][tx] += val * runLen;
+                    } else {
+                        touchedTile[ty][tx] += val * (nextTileXCoord - x0);
+                    }
+                    tx++;
+                }
+                // don't go all the way to tx1 - we need to handle the last
+                // tile as a special case (just like we did with the first
+                for (; tx < tx1; tx++) {
+//                    try {
+                    touchedTile[ty][tx] += (val << TILE_SIZE_LG);
+//                    } catch (RuntimeException e) {
+//                        System.out.println("x0, y0: " + x0 + ", " + y0);
+//                        System.out.printf("tx, ty, tx1: %d, %d, %d %n", tx, ty, tx1);
+//                        System.out.printf("bboxX/Y0/1: %d, %d, %d, %d %n",
+//                                bboxX0, bboxY0, bboxX1, bboxY1);
+//                        throw e;
+//                    }
+                }
+                // they will be equal unless x0>>TILE_SIZE_LG == tx1
+                if (tx == tx1) {
+                    int lastXCoord = Math.min(x0 + runLen, (tx + 1) << TILE_SIZE_LG);
+                    int txXCoord = tx << TILE_SIZE_LG;
+                    touchedTile[ty][tx] += val * (lastXCoord - txXCoord);
+                }
+            }
+            x0 += runLen;
         }
     }
 
-    void addRLERun(byte val, int runLen) {
-        reallocRowAARLE(alphaRLELength + 2);
-        rowAARLE[alphaRLELength++] = val;
-        rowAARLE[alphaRLELength++] = (byte)runLen;
+    void startRow(int y, int x) {
+        // rows are supposed to be added by increasing y.
+        assert y - bboxY0 > y0;
+        assert y <= bboxY1; // perhaps this should be < instead of <=
+
+        y0 = y - bboxY0;
+        // this should be a new, uninitialized row.
+        assert rowAARLE[y0][1] == 0;
+
+        x0 = x - bboxX0;
+        assert x0 >= 0 : "Input must not be to the left of bbox bounds";
+
+        // the way addTupleToRow is implemented it would work for this but it's
+        // not a good idea to use it because it is meant for adding
+        // RLE tuples, not the first tuple (which is special).
+        rowAARLE[y0][0] = x;
+        rowAARLE[y0][1] = 2;
     }
 
-    void startRow(int y, int x0, int x1) {
-        if (alphaRows == 0) {
-            bboxY0 = y;
-            bboxY1 = y+1;
-            bboxX0 = x0;
-            bboxX1 = x1+1;
-        } else {
-            if (bboxX0 > x0) bboxX0 = x0;
-            if (bboxX1 < x1 + 1) bboxX1 = x1 + 1;
-            while (bboxY1++ < y) {
-                reallocRowInfo(alphaRows+1);
-                minTouched[alphaRows] = 0;
-                // Assuming last 2 entries in rowAARLE are 0,0
-                rowOffsetsRLE[alphaRows] = alphaRLELength-2;
-                alphaRows++;
-            }
-        }
-        reallocRowInfo(alphaRows+1);
-        minTouched[alphaRows] = x0;
-        rowOffsetsRLE[alphaRows] = alphaRLELength;
-        alphaRows++;
+    int alphaSumInTile(int x, int y) {
+        x -= bboxX0;
+        y -= bboxY0;
+        return touchedTile[y>>TILE_SIZE_LG][x>>TILE_SIZE_LG];
+    }
+
+    int minTouched(int rowidx) {
+        return rowAARLE[rowidx][0];
     }
 
-    public synchronized void dispose() {
-        rowAARLE = null;
-        alphaRLELength = 0;
+    int rowLength(int rowidx) {
+        return rowAARLE[rowidx][1];
+    }
 
-        minTouched = null;
-        rowOffsetsRLE = null;
-        alphaRows = 0;
-
-        bboxX0 = bboxY0 = bboxX1 = bboxY1 = 0;
+    private void addTupleToRow(int row, int a, int b) {
+        int end = rowAARLE[row][1];
+        rowAARLE[row] = Helpers.widenArray(rowAARLE[row], end, 2);
+        rowAARLE[row][end++] = a;
+        rowAARLE[row][end++] = b;
+        rowAARLE[row][1] = end;
     }
 
-    public void print(java.io.PrintStream out) {
-        synchronized (out) {
-        out.println("bbox = ["+
-                    bboxX0+", "+bboxY0+" => "+
-                    bboxX1+", "+bboxY1+"]");
-
-        out.println("alphRLELength = "+alphaRLELength);
-
-        for (int y = bboxY0; y < bboxY1; y++) {
-            int i = y-bboxY0;
-            out.println("row["+i+"] == {"+
-                        "minX = "+minTouched[i]+
-                        ", off = "+rowOffsetsRLE[i]+"}");
+    @Override
+    public String toString() {
+        String ret = "bbox = ["+
+                      bboxX0+", "+bboxY0+" => "+
+                      bboxX1+", "+bboxY1+"]\n";
+        for (int[] row : rowAARLE) {
+            if (row != null) {
+                ret += ("minTouchedX=" + row[0] +
+                        "\tRLE Entries: " + Arrays.toString(
+                                Arrays.copyOfRange(row, 2, row[1])) + "\n");
+            } else {
+                ret += "[]\n";
+            }
         }
-
-        for (int i = 0; i < alphaRLELength; i += 2) {
-            out.println("rle["+i+"] = "+
-                        (rowAARLE[i+1]&0xff)+" of "+(rowAARLE[i]&0xff));
-        }
-    }
+        return ret;
     }
 }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Tue Nov 09 22:53:18 2010 -0800
@@ -27,7 +27,7 @@
 
 import java.awt.Shape;
 import java.awt.BasicStroke;
-import java.awt.geom.FlatteningPathIterator;
+import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Path2D;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.PathIterator;
@@ -38,8 +38,6 @@
 import sun.java2d.pipe.AATileGenerator;
 
 public class PiscesRenderingEngine extends RenderingEngine {
-    public static double defaultFlat = 0.1;
-
     private static enum NormMode {OFF, ON_NO_AA, ON_WITH_AA}
 
     /**
@@ -78,20 +76,29 @@
                  miterlimit,
                  dashes,
                  dashphase,
-                 new LineSink() {
+                 new PathConsumer2D() {
                      public void moveTo(float x0, float y0) {
                          p2d.moveTo(x0, y0);
                      }
-                     public void lineJoin() {}
                      public void lineTo(float x1, float y1) {
                          p2d.lineTo(x1, y1);
                      }
-                     public void close() {
+                     public void closePath() {
                          p2d.closePath();
                      }
-                     public void end() {}
+                     public void pathDone() {}
+                     public void curveTo(float x1, float y1,
+                                         float x2, float y2,
+                                         float x3, float y3) {
+                         p2d.curveTo(x1, y1, x2, y2, x3, y3);
+                     }
+                     public void quadTo(float x1, float y1, float x2, float y2) {
+                         p2d.quadTo(x1, y1, x2, y2);
+                     }
+                     public long getNativeConsumer() {
+                         throw new InternalError("Not using a native peer");
+                     }
                  });
-
         return p2d;
     }
 
@@ -133,22 +140,7 @@
         NormMode norm = (normalize) ?
                 ((antialias) ? NormMode.ON_WITH_AA : NormMode.ON_NO_AA)
                 : NormMode.OFF;
-        strokeTo(src, at, bs, thin, norm, antialias,
-                 new LineSink() {
-                     public void moveTo(float x0, float y0) {
-                         consumer.moveTo(x0, y0);
-                     }
-                     public void lineJoin() {}
-                     public void lineTo(float x1, float y1) {
-                         consumer.lineTo(x1, y1);
-                     }
-                     public void close() {
-                         consumer.closePath();
-                     }
-                     public void end() {
-                         consumer.pathDone();
-                     }
-                 });
+        strokeTo(src, at, bs, thin, norm, antialias, consumer);
     }
 
     void strokeTo(Shape src,
@@ -157,7 +149,7 @@
                   boolean thin,
                   NormMode normalize,
                   boolean antialias,
-                  LineSink lsink)
+                  PathConsumer2D pc2d)
     {
         float lw;
         if (thin) {
@@ -178,7 +170,7 @@
                  bs.getMiterLimit(),
                  bs.getDashArray(),
                  bs.getDashPhase(),
-                 lsink);
+                 pc2d);
     }
 
     private float userSpaceLineWidth(AffineTransform at, float lw) {
@@ -256,28 +248,113 @@
                   float miterlimit,
                   float dashes[],
                   float dashphase,
-                  LineSink lsink)
+                  PathConsumer2D pc2d)
     {
-        float a00 = 1f, a01 = 0f, a10 = 0f, a11 = 1f;
+        // We use inat and outat so that in Stroker and Dasher we can work only
+        // with the pre-transformation coordinates. This will repeat a lot of
+        // computations done in the path iterator, but the alternative is to
+        // work with transformed paths and compute untransformed coordinates
+        // as needed. This would be faster but I do not think the complexity
+        // of working with both untransformed and transformed coordinates in
+        // the same code is worth it.
+        // However, if a path's width is constant after a transformation,
+        // we can skip all this untransforming.
+
+        // If normalization is off we save some transformations by not
+        // transforming the input to pisces. Instead, we apply the
+        // transformation after the path processing has been done.
+        // We can't do this if normalization is on, because it isn't a good
+        // idea to normalize before the transformation is applied.
+        AffineTransform inat = null;
+        AffineTransform outat = null;
+
+        PathIterator pi = null;
+
         if (at != null && !at.isIdentity()) {
-            a00 = (float)at.getScaleX();
-            a01 = (float)at.getShearX();
-            a10 = (float)at.getShearY();
-            a11 = (float)at.getScaleY();
+            final double a = at.getScaleX();
+            final double b = at.getShearX();
+            final double c = at.getShearY();
+            final double d = at.getScaleY();
+            final double det = a * d - c * b;
+            if (Math.abs(det) <= 2 * Float.MIN_VALUE) {
+                // this rendering engine takes one dimensional curves and turns
+                // them into 2D shapes by giving them width.
+                // However, if everything is to be passed through a singular
+                // transformation, these 2D shapes will be squashed down to 1D
+                // again so, nothing can be drawn.
+
+                // Every path needs an initial moveTo and a pathDone. If these
+                // aren't there this causes a SIGSEV in libawt.so (at the time
+                // of writing of this comment (September 16, 2010)). Actually,
+                // I'm not sure if the moveTo is necessary to avoid the SIGSEV
+                // but the pathDone is definitely needed.
+                pc2d.moveTo(0, 0);
+                pc2d.pathDone();
+                return;
+            }
+
+            // If the transform is a constant multiple of an orthogonal transformation
+            // then every length is just multiplied by a constant, so we just
+            // need to transform input paths to stroker and tell stroker
+            // the scaled width. This condition is satisfied if
+            // a*b == -c*d && a*a+c*c == b*b+d*d. In the actual check below, we
+            // leave a bit of room for error.
+            if (nearZero(a*b + c*d, 2) && nearZero(a*a+c*c - (b*b+d*d), 2)) {
+                double scale = Math.sqrt(a*a + c*c);
+                if (dashes != null) {
+                    dashes = java.util.Arrays.copyOf(dashes, dashes.length);
+                    for (int i = 0; i < dashes.length; i++) {
+                        dashes[i] = (float)(scale * dashes[i]);
+                    }
+                    dashphase = (float)(scale * dashphase);
+                }
+                width = (float)(scale * width);
+                pi = src.getPathIterator(at);
+                if (normalize != NormMode.OFF) {
+                    pi = new NormalizingPathIterator(pi, normalize);
+                }
+                // leave inat and outat null.
+            } else {
+                // We only need the inverse if normalization is on. Otherwise
+                // we just don't transform the input paths, do all the stroking
+                // and then transform out output (instead of making PathIterator
+                // apply the transformation, us applying the inverse, and then
+                // us applying the transform again to our output).
+                outat = at;
+                if (normalize != NormMode.OFF) {
+                    try {
+                        inat = outat.createInverse();
+                    } catch (NoninvertibleTransformException e) {
+                        // we made sure this can't happen
+                        e.printStackTrace();
+                    }
+                    pi = src.getPathIterator(at);
+                    pi = new NormalizingPathIterator(pi, normalize);
+                } else {
+                    pi = src.getPathIterator(null);
+                }
+            }
+        } else {
+            // either at is null or it's the identity. In either case
+            // we don't transform the path.
+            pi = src.getPathIterator(null);
+            if (normalize != NormMode.OFF) {
+                pi = new NormalizingPathIterator(pi, normalize);
+            }
         }
-        lsink = new Stroker(lsink, width, caps, join, miterlimit, a00, a01, a10, a11);
+
+        pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, outat);
+        pc2d = new Stroker(pc2d, width, caps, join, miterlimit);
         if (dashes != null) {
-            lsink = new Dasher(lsink, dashes, dashphase, a00, a01, a10, a11);
+            pc2d = new Dasher(pc2d, dashes, dashphase);
         }
-        PathIterator pi;
-        if (normalize != NormMode.OFF) {
-            pi = new FlatteningPathIterator(
-                    new NormalizingPathIterator(src.getPathIterator(at), normalize),
-                    defaultFlat);
-        } else {
-            pi = src.getPathIterator(at, defaultFlat);
-        }
-        pathTo(pi, lsink);
+        pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, inat);
+
+        pathTo(pi, pc2d);
+    }
+
+    private static boolean nearZero(double num, int nulps) {
+        return Math.abs(num) < nulps * Math.ulp(num);
     }
 
     private static class NormalizingPathIterator implements PathIterator {
@@ -337,10 +414,10 @@
             }
 
             // normalize endpoint
-            float x_adjust = (float)Math.floor(coords[lastCoord] + lval) + rval -
-                         coords[lastCoord];
-            float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) + rval -
-                         coords[lastCoord + 1];
+            float x_adjust = (float)Math.floor(coords[lastCoord] + lval) +
+                         rval - coords[lastCoord];
+            float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) +
+                         rval - coords[lastCoord + 1];
 
             coords[lastCoord    ] += x_adjust;
             coords[lastCoord + 1] += y_adjust;
@@ -393,27 +470,9 @@
         }
     }
 
-    void pathTo(PathIterator pi, LineSink lsink) {
-        float coords[] = new float[2];
-        while (!pi.isDone()) {
-            switch (pi.currentSegment(coords)) {
-            case PathIterator.SEG_MOVETO:
-                lsink.moveTo(coords[0], coords[1]);
-                break;
-            case PathIterator.SEG_LINETO:
-                lsink.lineJoin();
-                lsink.lineTo(coords[0], coords[1]);
-                break;
-            case PathIterator.SEG_CLOSE:
-                lsink.lineJoin();
-                lsink.close();
-                break;
-            default:
-                throw new InternalError("unknown flattened segment type");
-            }
-            pi.next();
-        }
-        lsink.end();
+    static void pathTo(PathIterator pi, PathConsumer2D pc2d) {
+        RenderingEngine.feedConsumer(pi, pc2d);
+        pc2d.pathDone();
     }
 
     /**
@@ -471,32 +530,29 @@
                                               boolean normalize,
                                               int bbox[])
     {
-        PiscesCache pc = PiscesCache.createInstance();
         Renderer r;
         NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF;
         if (bs == null) {
             PathIterator pi;
             if (normalize) {
-                pi = new FlatteningPathIterator(
-                        new NormalizingPathIterator(s.getPathIterator(at), norm),
-                        defaultFlat);
+                pi = new NormalizingPathIterator(s.getPathIterator(at), norm);
             } else {
-                pi = s.getPathIterator(at, defaultFlat);
+                pi = s.getPathIterator(at);
             }
             r = new Renderer(3, 3,
                              clip.getLoX(), clip.getLoY(),
                              clip.getWidth(), clip.getHeight(),
-                             pi.getWindingRule(), pc);
+                             pi.getWindingRule());
             pathTo(pi, r);
         } else {
             r = new Renderer(3, 3,
                              clip.getLoX(), clip.getLoY(),
                              clip.getWidth(), clip.getHeight(),
-                             PathIterator.WIND_NON_ZERO, pc);
+                             PathIterator.WIND_NON_ZERO);
             strokeTo(s, at, bs, thin, norm, true, r);
         }
         r.endRendering();
-        PiscesTileGenerator ptg = new PiscesTileGenerator(pc, r.MAX_AA_ALPHA);
+        PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA);
         ptg.getBbox(bbox);
         return ptg;
     }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,40 +25,54 @@
 
 package sun.java2d.pisces;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import sun.java2d.pipe.AATileGenerator;
 
-public class PiscesTileGenerator implements AATileGenerator {
-    public static final int TILE_SIZE = 32;
+public final class PiscesTileGenerator implements AATileGenerator {
+    public static final int TILE_SIZE = PiscesCache.TILE_SIZE;
+
+    // perhaps we should be using weak references here, but right now
+    // that's not necessary. The way the renderer is, this map will
+    // never contain more than one element - the one with key 64, since
+    // we only do 8x8 supersampling.
+    private static final Map<Integer, byte[]> alphaMapsCache = new
+                   ConcurrentHashMap<Integer, byte[]>();
 
     PiscesCache cache;
     int x, y;
-    int maxalpha;
+    final int maxalpha;
+    private final int maxTileAlphaSum;
+
+    // The alpha map used by this object (taken out of our map cache) to convert
+    // pixel coverage counts gotten from PiscesCache (which are in the range
+    // [0, maxalpha]) into alpha values, which are in [0,256).
     byte alphaMap[];
 
-    public PiscesTileGenerator(PiscesCache cache, int maxalpha) {
-        this.cache = cache;
+    public PiscesTileGenerator(Renderer r, int maxalpha) {
+        this.cache = r.getCache();
         this.x = cache.bboxX0;
         this.y = cache.bboxY0;
         this.alphaMap = getAlphaMap(maxalpha);
         this.maxalpha = maxalpha;
+        this.maxTileAlphaSum = TILE_SIZE*TILE_SIZE*maxalpha;
     }
 
-    static int prevMaxAlpha;
-    static byte prevAlphaMap[];
+    private static byte[] buildAlphaMap(int maxalpha) {
+        byte[] alMap = new byte[maxalpha+1];
+        int halfmaxalpha = maxalpha>>2;
+        for (int i = 0; i <= maxalpha; i++) {
+            alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
+        }
+        return alMap;
+    }
 
-    public synchronized static byte[] getAlphaMap(int maxalpha) {
-        if (maxalpha != prevMaxAlpha) {
-            prevAlphaMap = new byte[maxalpha+300];
-            int halfmaxalpha = maxalpha>>2;
-            for (int i = 0; i <= maxalpha; i++) {
-                prevAlphaMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
-            }
-            for (int i = maxalpha; i < prevAlphaMap.length; i++) {
-                prevAlphaMap[i] = (byte) 255;
-            }
-            prevMaxAlpha = maxalpha;
+    public static byte[] getAlphaMap(int maxalpha) {
+        if (!alphaMapsCache.containsKey(maxalpha)) {
+            alphaMapsCache.put(maxalpha, buildAlphaMap(maxalpha));
         }
-        return prevAlphaMap;
+        return alphaMapsCache.get(maxalpha);
     }
 
     public void getBbox(int bbox[]) {
@@ -96,53 +110,24 @@
      *         value for partial coverage of the tile
      */
     public int getTypicalAlpha() {
-        if (true) return 0x80;
-        // Decode run-length encoded alpha mask data
-        // The data for row j begins at cache.rowOffsetsRLE[j]
-        // and is encoded as a set of 2-byte pairs (val, runLen)
-        // terminated by a (0, 0) pair.
-
-        int x0 = this.x;
-        int x1 = x0 + TILE_SIZE;
-        int y0 = this.y;
-        int y1 = y0 + TILE_SIZE;
-        if (x1 > cache.bboxX1) x1 = cache.bboxX1;
-        if (y1 > cache.bboxY1) y1 = cache.bboxY1;
-        y0 -= cache.bboxY0;
-        y1 -= cache.bboxY0;
-
-        int ret = -1;
-        for (int cy = y0; cy < y1; cy++) {
-            int pos = cache.rowOffsetsRLE[cy];
-            int cx = cache.minTouched[cy];
-
-            if (cx > x0) {
-                if (ret > 0) return 0x80;
-                ret = 0x00;
-            }
-            while (cx < x1) {
-                int runLen = cache.rowAARLE[pos + 1] & 0xff;
-                if (runLen == 0) {
-                    if (ret > 0) return 0x80;
-                    ret = 0x00;
-                    break;
-                }
-                cx += runLen;
-                if (cx > x0) {
-                    int val = cache.rowAARLE[pos] & 0xff;
-                    if (ret != val) {
-                        if (ret < 0) {
-                            if (val != 0x00 && val != maxalpha) return 0x80;
-                            ret = val;
-                        } else {
-                            return 0x80;
-                        }
-                    }
-                }
-                pos += 2;
-            }
-        }
-        return ret;
+        int al = cache.alphaSumInTile(x, y);
+        // Note: if we have a filled rectangle that doesn't end on a tile
+        // border, we could still return 0xff, even though al!=maxTileAlphaSum
+        // This is because if we return 0xff, our users will fill a rectangle
+        // starting at x,y that has width = Math.min(TILE_SIZE, bboxX1-x),
+        // and height min(TILE_SIZE,bboxY1-y), which is what should happen.
+        // However, to support this, we would have to use 2 Math.min's
+        // and 2 multiplications per tile, instead of just 2 multiplications
+        // to compute maxTileAlphaSum. The savings offered would probably
+        // not be worth it, considering how rare this case is.
+        // Note: I have not tested this, so in the future if it is determined
+        // that it is worth it, it should be implemented. Perhaps this method's
+        // interface should be changed to take arguments the width and height
+        // of the current tile. This would eliminate the 2 Math.min calls that
+        // would be needed here, since our caller needs to compute these 2
+        // values anyway.
+        return (al == 0x00 ? 0x00 :
+            (al == maxTileAlphaSum ? 0xff : 0x80));
     }
 
     /**
@@ -179,22 +164,24 @@
 
         int idx = offset;
         for (int cy = y0; cy < y1; cy++) {
-            int pos = cache.rowOffsetsRLE[cy];
-            int cx = cache.minTouched[cy];
+            int[] row = cache.rowAARLE[cy];
+            assert row != null;
+            int cx = cache.minTouched(cy);
             if (cx > x1) cx = x1;
 
-            if (cx > x0) {
-                //System.out.println("L["+(cx-x0)+"]");
-                for (int i = x0; i < cx; i++) {
-                    tile[idx++] = 0x00;
-                }
+            for (int i = x0; i < cx; i++) {
+                tile[idx++] = 0x00;
             }
-            while (cx < x1) {
+
+            int pos = 2;
+            while (cx < x1 && pos < row[1]) {
                 byte val;
                 int runLen = 0;
+                assert row[1] > 2;
                 try {
-                    val = alphaMap[cache.rowAARLE[pos] & 0xff];
-                    runLen = cache.rowAARLE[pos + 1] & 0xff;
+                    val = alphaMap[row[pos]];
+                    runLen = row[pos + 1];
+                    assert runLen > 0;
                 } catch (RuntimeException e0) {
                     System.out.println("maxalpha = "+maxalpha);
                     System.out.println("tile["+x0+", "+y0+
@@ -202,14 +189,12 @@
                     System.out.println("cx = "+cx+", cy = "+cy);
                     System.out.println("idx = "+idx+", pos = "+pos);
                     System.out.println("len = "+runLen);
-                    cache.print(System.out);
+                    System.out.print(cache.toString());
                     e0.printStackTrace();
                     System.exit(1);
                     return;
                 }
-                if (runLen == 0) {
-                    break;
-                }
+
                 int rx0 = cx;
                 cx += runLen;
                 int rx1 = cx;
@@ -228,7 +213,7 @@
                         System.out.println("idx = "+idx+", pos = "+pos);
                         System.out.println("rx0 = "+rx0+", rx1 = "+rx1);
                         System.out.println("len = "+runLen);
-                        cache.print(System.out);
+                        System.out.print(cache.toString());
                         e.printStackTrace();
                         System.exit(1);
                         return;
@@ -265,4 +250,4 @@
      * No further calls will be made on this instance.
      */
     public void dispose() {}
-}
+}
\ No newline at end of file
--- a/jdk/src/share/classes/sun/java2d/pisces/Renderer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Renderer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -26,250 +26,552 @@
 package sun.java2d.pisces;
 
 import java.util.Arrays;
+import java.util.Iterator;
 
-public class Renderer implements LineSink {
+import sun.awt.geom.PathConsumer2D;
 
-///////////////////////////////////////////////////////////////////////////////
-// Scan line iterator and edge crossing data.
-//////////////////////////////////////////////////////////////////////////////
+public class Renderer implements PathConsumer2D {
 
-    private int[] crossings;
+    private class ScanlineIterator {
+
+        private int[] crossings;
 
-    // This is an array of indices into the edge array. It is initialized to
-    // [i * SIZEOF_STRUCT_EDGE for i in range(0, edgesSize/SIZEOF_STRUCT_EDGE)]
-    // (where range(i, j) is i,i+1,...,j-1 -- just like in python).
-    // The reason for keeping this is because we need the edges array sorted
-    // by y0, but we don't want to move all that data around, so instead we
-    // sort the indices into the edge array, and use edgeIndices to access
-    // the edges array. This is meant to simulate a pointer array (hence the name)
-    private int[] edgePtrs;
+        // crossing bounds. The bounds are not necessarily tight (the scan line
+        // at minY, for example, might have no crossings). The x bounds will
+        // be accumulated as crossings are computed.
+        private int minY, maxY;
+        private int nextY;
 
-    // crossing bounds. The bounds are not necessarily tight (the scan line
-    // at minY, for example, might have no crossings). The x bounds will
-    // be accumulated as crossings are computed.
-    private int minY, maxY;
-    private int minX, maxX;
-    private int nextY;
+        // indices into the segment pointer lists. They indicate the "active"
+        // sublist in the segment lists (the portion of the list that contains
+        // all the segments that cross the next scan line).
+        private int elo, ehi;
+        private final int[] edgePtrs;
+        private int qlo, qhi;
+        private final int[] quadPtrs;
+        private int clo, chi;
+        private final int[] curvePtrs;
+
+        private static final int INIT_CROSSINGS_SIZE = 10;
+
+        private ScanlineIterator() {
+            crossings = new int[INIT_CROSSINGS_SIZE];
 
-    // indices into the edge pointer list. They indicate the "active" sublist in
-    // the edge list (the portion of the list that contains all the edges that
-    // cross the next scan line).
-    private int lo, hi;
+            edgePtrs = new int[numEdges];
+            Helpers.fillWithIdxes(edgePtrs, SIZEOF_EDGE);
+            qsort(edges, edgePtrs, YMIN, 0, numEdges - 1);
 
-    private static final int INIT_CROSSINGS_SIZE = 50;
-    private void ScanLineItInitialize() {
-        crossings = new int[INIT_CROSSINGS_SIZE];
-        edgePtrs = new int[edgesSize / SIZEOF_STRUCT_EDGE];
-        for (int i = 0; i < edgePtrs.length; i++) {
-            edgePtrs[i] = i * SIZEOF_STRUCT_EDGE;
-        }
+            quadPtrs = new int[numQuads];
+            Helpers.fillWithIdxes(quadPtrs, SIZEOF_QUAD);
+            qsort(quads, quadPtrs, YMIN, 0, numQuads - 1);
+
+            curvePtrs = new int[numCurves];
+            Helpers.fillWithIdxes(curvePtrs, SIZEOF_CURVE);
+            qsort(curves, curvePtrs, YMIN, 0, numCurves - 1);
 
-        qsort(0, edgePtrs.length - 1);
+            // We don't care if we clip some of the line off with ceil, since
+            // no scan line crossings will be eliminated (in fact, the ceil is
+            // the y of the first scan line crossing).
+            nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
+            maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
 
-        // We don't care if we clip some of the line off with ceil, since
-        // no scan line crossings will be eliminated (in fact, the ceil is
-        // the y of the first scan line crossing).
-        nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
-        maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
+            for (elo = 0; elo < numEdges && edges[edgePtrs[elo]+YMAX] <= minY; elo++)
+                ;
+            // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive)
+            for (ehi = elo; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= minY; ehi++)
+                edgeSetCurY(edgePtrs[ehi], minY);// TODO: make minY a float to avoid casts
 
-        for (lo = 0; lo < edgePtrs.length && edges[edgePtrs[lo]+Y1] <= nextY; lo++)
-            ;
-        for (hi = lo; hi < edgePtrs.length && edges[edgePtrs[hi]+CURY] <= nextY; hi++)
-            ; // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive)
-        for (int i = lo; i < hi; i++) {
-            setCurY(edgePtrs[i], nextY);
+            for (qlo = 0; qlo < numQuads && quads[quadPtrs[qlo]+YMAX] <= minY; qlo++)
+                ;
+            for (qhi = qlo; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= minY; qhi++)
+                quadSetCurY(quadPtrs[qhi], minY);
+
+            for (clo = 0; clo < numCurves && curves[curvePtrs[clo]+YMAX] <= minY; clo++)
+                ;
+            for (chi = clo; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= minY; chi++)
+                curveSetCurY(curvePtrs[chi], minY);
         }
 
-        // We accumulate X in the iterator because accumulating it in addEdge
-        // like we do with Y does not do much good: if there's an edge
-        // (0,0)->(1000,10000), and if y gets clipped to 1000, then the x
-        // bound should be 100, but the accumulator from addEdge would say 1000,
-        // so we'd still have to accumulate the X bounds as we add crossings.
-        minX = boundsMinX;
-        maxX = boundsMaxX;
-    }
+        private int next() {
+            // we go through the active lists and remove segments that don't cross
+            // the nextY scanline.
+            int crossingIdx = 0;
+            for (int i = elo; i < ehi; i++) {
+                if (edges[edgePtrs[i]+YMAX] <= nextY) {
+                    edgePtrs[i] = edgePtrs[elo++];
+                }
+            }
+            for (int i = qlo; i < qhi; i++) {
+                if (quads[quadPtrs[i]+YMAX] <= nextY) {
+                    quadPtrs[i] = quadPtrs[qlo++];
+                }
+            }
+            for (int i = clo; i < chi; i++) {
+                if (curves[curvePtrs[i]+YMAX] <= nextY) {
+                    curvePtrs[i] = curvePtrs[clo++];
+                }
+            }
 
-    private int ScanLineItCurrentY() {
-        return nextY - 1;
-    }
+            crossings = Helpers.widenArray(crossings, 0, ehi-elo+qhi-qlo+chi-clo);
 
-    private int ScanLineItGoToNextYAndComputeCrossings() {
-        // we go through the active list and remove the ones that don't cross
-        // the nextY scanline.
-        int crossingIdx = 0;
-        for (int i = lo; i < hi; i++) {
-            if (edges[edgePtrs[i]+Y1] <= nextY) {
-                edgePtrs[i] = edgePtrs[lo++];
+            // Now every edge between lo and hi crosses nextY. Compute it's
+            // crossing and put it in the crossings array.
+            for (int i = elo; i < ehi; i++) {
+                int ptr = edgePtrs[i];
+                addCrossing(nextY, (int)edges[ptr+CURX], edges[ptr+OR], crossingIdx);
+                edgeGoToNextY(ptr);
+                crossingIdx++;
+            }
+            for (int i = qlo; i < qhi; i++) {
+                int ptr = quadPtrs[i];
+                addCrossing(nextY, (int)quads[ptr+CURX], quads[ptr+OR], crossingIdx);
+                quadGoToNextY(ptr);
+                crossingIdx++;
             }
-        }
-        if (hi - lo > crossings.length) {
-            int newSize = Math.max(hi - lo, crossings.length * 2);
-            crossings = Arrays.copyOf(crossings, newSize);
-        }
-        // Now every edge between lo and hi crosses nextY. Compute it's
-        // crossing and put it in the crossings array.
-        for (int i = lo; i < hi; i++) {
-            addCrossing(nextY, getCurCrossing(edgePtrs[i]), (int)edges[edgePtrs[i]+OR], crossingIdx);
-            gotoNextY(edgePtrs[i]);
-            crossingIdx++;
+            for (int i = clo; i < chi; i++) {
+                int ptr = curvePtrs[i];
+                addCrossing(nextY, (int)curves[ptr+CURX], curves[ptr+OR], crossingIdx);
+                curveGoToNextY(ptr);
+                crossingIdx++;
+            }
+
+            nextY++;
+            // Expand active lists to include new edges.
+            for (; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= nextY; ehi++) {
+                edgeSetCurY(edgePtrs[ehi], nextY);
+            }
+            for (; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= nextY; qhi++) {
+                quadSetCurY(quadPtrs[qhi], nextY);
+            }
+            for (; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= nextY; chi++) {
+                curveSetCurY(curvePtrs[chi], nextY);
+            }
+            Arrays.sort(crossings, 0, crossingIdx);
+            return crossingIdx;
         }
 
-        nextY++;
-        // Expand active list to include new edges.
-        for (; hi < edgePtrs.length && edges[edgePtrs[hi]+CURY] <= nextY; hi++) {
-            setCurY(edgePtrs[hi], nextY);
+        private boolean hasNext() {
+            return nextY < maxY;
         }
 
-        Arrays.sort(crossings, 0, crossingIdx);
-        return crossingIdx;
-    }
-
-    private boolean ScanLineItHasNext() {
-        return nextY < maxY;
-    }
+        private int curY() {
+            return nextY - 1;
+        }
 
-    private void addCrossing(int y, int x, int or, int idx) {
-        if (x < minX) {
-            minX = x;
+        private void addCrossing(int y, int x, float or, int idx) {
+            x <<= 1;
+            crossings[idx] = ((or > 0) ? (x | 0x1) : x);
         }
-        if (x > maxX) {
-            maxX = x;
-        }
-        x <<= 1;
-        crossings[idx] = ((or == 1) ? (x | 0x1) : x);
     }
-
-
     // quicksort implementation for sorting the edge indices ("pointers")
     // by increasing y0. first, last are indices into the "pointer" array
     // It sorts the pointer array from first (inclusive) to last (inclusive)
-    private void qsort(int first, int last) {
+    private static void qsort(final float[] data, final int[] ptrs,
+                              final int fieldForCmp, int first, int last)
+    {
         if (last > first) {
-            int p = partition(first, last);
+            int p = partition(data, ptrs, fieldForCmp, first, last);
             if (first < p - 1) {
-                qsort(first, p - 1);
+                qsort(data, ptrs, fieldForCmp, first, p - 1);
             }
             if (p < last) {
-                qsort(p, last);
+                qsort(data, ptrs, fieldForCmp, p, last);
             }
         }
     }
 
     // i, j are indices into edgePtrs.
-    private int partition(int i, int j) {
-        int pivotVal = edgePtrs[i];
+    private static int partition(final float[] data, final int[] ptrs,
+                                 final int fieldForCmp, int i, int j)
+    {
+        int pivotValFieldForCmp = ptrs[i]+fieldForCmp;
         while (i <= j) {
             // edges[edgePtrs[i]+1] is equivalent to (*(edgePtrs[i])).y0 in C
-            while (edges[edgePtrs[i]+CURY] < edges[pivotVal+CURY]) { i++; }
-            while (edges[edgePtrs[j]+CURY] > edges[pivotVal+CURY]) { j--; }
+            while (data[ptrs[i]+fieldForCmp] < data[pivotValFieldForCmp])
+                i++;
+            while (data[ptrs[j]+fieldForCmp] > data[pivotValFieldForCmp])
+                j--;
             if (i <= j) {
-                int tmp = edgePtrs[i];
-                edgePtrs[i] = edgePtrs[j];
-                edgePtrs[j] = tmp;
+                int tmp = ptrs[i];
+                ptrs[i] = ptrs[j];
+                ptrs[j] = tmp;
                 i++;
                 j--;
             }
         }
         return i;
     }
-
 //============================================================================
 
 
 //////////////////////////////////////////////////////////////////////////////
 //  EDGE LIST
 //////////////////////////////////////////////////////////////////////////////
+// TODO(maybe): very tempting to use fixed point here. A lot of opportunities
+// for shifts and just removing certain operations altogether.
+// TODO: it might be worth it to make an EdgeList class. It would probably
+// clean things up a bit and not impact performance much.
 
-    private static final int INIT_NUM_EDGES = 1000;
-    private static final int SIZEOF_STRUCT_EDGE = 5;
+    // common to all types of input path segments.
+    private static final int YMIN = 0;
+    private static final int YMAX = 1;
+    private static final int CURX = 2;
+    // this and OR are meant to be indeces into "int" fields, but arrays must
+    // be homogenous, so every field is a float. However floats can represent
+    // exactly up to 26 bit ints, so we're ok.
+    private static final int CURY = 3;
+    private static final int OR   = 4;
+
+    // for straight lines only:
+    private static final int SLOPE = 5;
+
+    // for quads and cubics:
+    private static final int X0 = 5;
+    private static final int Y0 = 6;
+    private static final int XL = 7;
+    private static final int COUNT = 8;
+    private static final int CURSLOPE = 9;
+    private static final int DX = 10;
+    private static final int DY = 11;
+    private static final int DDX = 12;
+    private static final int DDY = 13;
+
+    // for cubics only
+    private static final int DDDX = 14;
+    private static final int DDDY = 15;
+
+    private float edgeMinY = Float.POSITIVE_INFINITY;
+    private float edgeMaxY = Float.NEGATIVE_INFINITY;
+    private float edgeMinX = Float.POSITIVE_INFINITY;
+    private float edgeMaxX = Float.NEGATIVE_INFINITY;
+
+    private static final int SIZEOF_EDGE = 6;
+    private float[] edges = null;
+    private int numEdges;
+    // these are static because we need them to be usable from ScanlineIterator
+    private void edgeSetCurY(final int idx, int y) {
+        edges[idx+CURX] += (y - edges[idx+CURY]) * edges[idx+SLOPE];
+        edges[idx+CURY] = y;
+    }
+    private void edgeGoToNextY(final int idx) {
+        edges[idx+CURY] += 1;
+        edges[idx+CURX] += edges[idx+SLOPE];
+    }
+
+
+    private static final int SIZEOF_QUAD = 14;
+    private float[] quads = null;
+    private int numQuads;
+    // This function should be called exactly once, to set the first scanline
+    // of the curve. Before it is called, the curve should think its first
+    // scanline is CEIL(YMIN).
+    private void quadSetCurY(final int idx, final int y) {
+        assert y < quads[idx+YMAX];
+        assert (quads[idx+CURY] > y);
+        assert (quads[idx+CURY] == Math.ceil(quads[idx+CURY]));
 
-    // The following array is a poor man's struct array:
-    // it simulates a struct array by having
-    // edges[SIZEOF_STRUCT_EDGE * i + j] be the jth field in the ith element
-    // of an array of edge structs.
-    private float[] edges;
-    private int edgesSize; // size of the edge list.
-    private static final int Y1    = 0;
-    private static final int SLOPE = 1;
-    private static final int OR    = 2; // the orientation. This can be -1 or 1.
-                                     // -1 means up, 1 means down.
-    private static final int CURY  = 3; // j = 5 corresponds to the "current Y".
-                             // Each edge keeps track of the last scanline
-                             // crossing it computed, and this is the y coord of
-                             // that scanline.
-    private static final int CURX = 4; //the x coord of the current crossing.
+        while (quads[idx+CURY] < ((float)y)) {
+            quadGoToNextY(idx);
+        }
+    }
+    private void quadGoToNextY(final int idx) {
+        quads[idx+CURY] += 1;
+        // this will get overriden if the while executes.
+        quads[idx+CURX] += quads[idx+CURSLOPE];
+        int count = (int)quads[idx+COUNT];
+        // this loop should never execute more than once because our
+        // curve is monotonic in Y. Still we put it in because you can
+        // never be too sure when dealing with floating point.
+        while(quads[idx+CURY] >= quads[idx+Y0] && count > 0) {
+            float x0 = quads[idx+X0], y0 = quads[idx+Y0];
+            count = executeQuadAFDIteration(idx);
+            float x1 = quads[idx+X0], y1 = quads[idx+Y0];
+            // our quads are monotonic, so this shouldn't happen, but
+            // it is conceivable that for very flat quads with different
+            // y values at their endpoints AFD might give us a horizontal
+            // segment.
+            if (y1 == y0) {
+                continue;
+            }
+            quads[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
+            quads[idx+CURX] = x0 + (quads[idx+CURY] - y0) * quads[idx+CURSLOPE];
+        }
+    }
+
 
-    // Note that while the array is declared as a float[] not all of it's
-    // elements should be floats. currentY and Orientation should be ints (or int and
-    // byte respectively), but they all need to be the same type. This isn't
-    // really a problem because floats can represent exactly all 23 bit integers,
-    // which should be more than enough.
-    // Note, also, that we only need x1 for slope computation, so we don't need
-    // to store it. x0, y0 don't need to be stored either. They can be put into
-    // curx, cury, and it's ok if they're lost when curx and cury are changed.
-    // We take this undeniably ugly and error prone approach (instead of simply
-    // making an Edge class) for performance reasons. Also, it would probably be nicer
-    // to have one array for each field, but that would defeat the purpose because
-    // it would make poor use of the processor cache, since we tend to access
-    // all the fields for one edge at a time.
+    private static final int SIZEOF_CURVE = 16;
+    private float[] curves = null;
+    private int numCurves;
+    private void curveSetCurY(final int idx, final int y) {
+        assert y < curves[idx+YMAX];
+        assert (curves[idx+CURY] > y);
+        assert (curves[idx+CURY] == Math.ceil(curves[idx+CURY]));
 
-    private float edgeMinY;
-    private float edgeMaxY;
+        while (curves[idx+CURY] < ((float)y)) {
+            curveGoToNextY(idx);
+        }
+    }
+    private void curveGoToNextY(final int idx) {
+        curves[idx+CURY] += 1;
+        // this will get overriden if the while executes.
+        curves[idx+CURX] += curves[idx+CURSLOPE];
+        int count = (int)curves[idx+COUNT];
+        // this loop should never execute more than once because our
+        // curve is monotonic in Y. Still we put it in because you can
+        // never be too sure when dealing with floating point.
+        while(curves[idx+CURY] >= curves[idx+Y0] && count > 0) {
+            float x0 = curves[idx+X0], y0 = curves[idx+Y0];
+            count = executeCurveAFDIteration(idx);
+            float x1 = curves[idx+X0], y1 = curves[idx+Y0];
+            // our curves are monotonic, so this shouldn't happen, but
+            // it is conceivable that for very flat curves with different
+            // y values at their endpoints AFD might give us a horizontal
+            // segment.
+            if (y1 == y0) {
+                continue;
+            }
+            curves[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
+            curves[idx+CURX] = x0 + (curves[idx+CURY] - y0) * curves[idx+CURSLOPE];
+        }
+    }
 
 
-    private void addEdge(float x0, float y0, float x1, float y1) {
-        float or = (y0 < y1) ? 1f : -1f; // orientation: 1 = UP; -1 = DOWN
-        if (or == -1) {
-            float tmp = y0;
-            y0 = y1;
-            y1 = tmp;
-            tmp = x0;
-            x0 = x1;
-            x1 = tmp;
+    private static final float DEC_BND = 20f;
+    private static final float INC_BND = 8f;
+    // Flattens using adaptive forward differencing. This only carries out
+    // one iteration of the AFD loop. All it does is update AFD variables (i.e.
+    // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
+    private int executeQuadAFDIteration(int idx) {
+        int count = (int)quads[idx+COUNT];
+        float ddx = quads[idx+DDX];
+        float ddy = quads[idx+DDY];
+        float dx = quads[idx+DX];
+        float dy = quads[idx+DY];
+
+        while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
+            ddx = ddx / 4;
+            ddy = ddy / 4;
+            dx = (dx - ddx) / 2;
+            dy = (dy - ddy) / 2;
+            count <<= 1;
+        }
+        // can only do this on even "count" values, because we must divide count by 2
+        while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
+            dx = 2 * dx + ddx;
+            dy = 2 * dy + ddy;
+            ddx = 4 * ddx;
+            ddy = 4 * ddy;
+            count >>= 1;
+        }
+        count--;
+        if (count > 0) {
+            quads[idx+X0] += dx;
+            dx += ddx;
+            quads[idx+Y0] += dy;
+            dy += ddy;
+        } else {
+            quads[idx+X0] = quads[idx+XL];
+            quads[idx+Y0] = quads[idx+YMAX];
+        }
+        quads[idx+COUNT] = count;
+        quads[idx+DDX] = ddx;
+        quads[idx+DDY] = ddy;
+        quads[idx+DX] = dx;
+        quads[idx+DY] = dy;
+        return count;
+    }
+    private int executeCurveAFDIteration(int idx) {
+        int count = (int)curves[idx+COUNT];
+        float ddx = curves[idx+DDX];
+        float ddy = curves[idx+DDY];
+        float dx = curves[idx+DX];
+        float dy = curves[idx+DY];
+        float dddx = curves[idx+DDDX];
+        float dddy = curves[idx+DDDY];
+
+        while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
+            dddx /= 8;
+            dddy /= 8;
+            ddx = ddx/4 - dddx;
+            ddy = ddy/4 - dddy;
+            dx = (dx - ddx) / 2;
+            dy = (dy - ddy) / 2;
+            count <<= 1;
+        }
+        // can only do this on even "count" values, because we must divide count by 2
+        while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
+            dx = 2 * dx + ddx;
+            dy = 2 * dy + ddy;
+            ddx = 4 * (ddx + dddx);
+            ddy = 4 * (ddy + dddy);
+            dddx = 8 * dddx;
+            dddy = 8 * dddy;
+            count >>= 1;
+        }
+        count--;
+        if (count > 0) {
+            curves[idx+X0] += dx;
+            dx += ddx;
+            ddx += dddx;
+            curves[idx+Y0] += dy;
+            dy += ddy;
+            ddy += dddy;
+        } else {
+            curves[idx+X0] = curves[idx+XL];
+            curves[idx+Y0] = curves[idx+YMAX];
         }
-        // skip edges that don't cross a scanline
-        if (Math.ceil(y0) >= Math.ceil(y1)) {
+        curves[idx+COUNT] = count;
+        curves[idx+DDDX] = dddx;
+        curves[idx+DDDY] = dddy;
+        curves[idx+DDX] = ddx;
+        curves[idx+DDY] = ddy;
+        curves[idx+DX] = dx;
+        curves[idx+DY] = dy;
+        return count;
+    }
+
+
+    private void initLine(final int idx, float[] pts, int or) {
+        edges[idx+SLOPE] = (pts[2] - pts[0]) / (pts[3] - pts[1]);
+        edges[idx+CURX] = pts[0] + (edges[idx+CURY] - pts[1]) * edges[idx+SLOPE];
+    }
+
+    private void initQuad(final int idx, float[] points, int or) {
+        final int countlg = 3;
+        final int count = 1 << countlg;
+
+        // the dx and dy refer to forward differencing variables, not the last
+        // coefficients of the "points" polynomial
+        final float ddx, ddy, dx, dy;
+        c.set(points, 6);
+
+        ddx = c.dbx / (1 << (2 * countlg));
+        ddy = c.dby / (1 << (2 * countlg));
+        dx = c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
+        dy = c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
+
+        quads[idx+DDX] = ddx;
+        quads[idx+DDY] = ddy;
+        quads[idx+DX] = dx;
+        quads[idx+DY] = dy;
+        quads[idx+COUNT] = count;
+        quads[idx+XL] = points[4];
+        quads[idx+X0] = points[0];
+        quads[idx+Y0] = points[1];
+        executeQuadAFDIteration(idx);
+        float x1 = quads[idx+X0], y1 = quads[idx+Y0];
+        quads[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
+        quads[idx+CURX] = points[0] + (quads[idx+CURY] - points[1])*quads[idx+CURSLOPE];
+    }
+
+    private void initCurve(final int idx, float[] points, int or) {
+        final int countlg = 3;
+        final int count = 1 << countlg;
+
+        // the dx and dy refer to forward differencing variables, not the last
+        // coefficients of the "points" polynomial
+        final float dddx, dddy, ddx, ddy, dx, dy;
+        c.set(points, 8);
+        dddx = 2f * c.dax / (1 << (3 * countlg));
+        dddy = 2f * c.day / (1 << (3 * countlg));
+
+        ddx = dddx + c.dbx / (1 << (2 * countlg));
+        ddy = dddy + c.dby / (1 << (2 * countlg));
+        dx = c.ax / (1 << (3 * countlg)) + c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
+        dy = c.ay / (1 << (3 * countlg)) + c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
+
+        curves[idx+DDDX] = dddx;
+        curves[idx+DDDY] = dddy;
+        curves[idx+DDX] = ddx;
+        curves[idx+DDY] = ddy;
+        curves[idx+DX] = dx;
+        curves[idx+DY] = dy;
+        curves[idx+COUNT] = count;
+        curves[idx+XL] = points[6];
+        curves[idx+X0] = points[0];
+        curves[idx+Y0] = points[1];
+        executeCurveAFDIteration(idx);
+        float x1 = curves[idx+X0], y1 = curves[idx+Y0];
+        curves[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
+        curves[idx+CURX] = points[0] + (curves[idx+CURY] - points[1])*curves[idx+CURSLOPE];
+    }
+
+    private void addPathSegment(float[] pts, final int type, final int or) {
+        int idx;
+        float[] addTo;
+        switch (type) {
+        case 4:
+            idx = numEdges * SIZEOF_EDGE;
+            addTo = edges = Helpers.widenArray(edges, numEdges*SIZEOF_EDGE, SIZEOF_EDGE);
+            numEdges++;
+            break;
+        case 6:
+            idx = numQuads * SIZEOF_QUAD;
+            addTo = quads = Helpers.widenArray(quads, numQuads*SIZEOF_QUAD, SIZEOF_QUAD);
+            numQuads++;
+            break;
+        case 8:
+            idx = numCurves * SIZEOF_CURVE;
+            addTo = curves = Helpers.widenArray(curves, numCurves*SIZEOF_CURVE, SIZEOF_CURVE);
+            numCurves++;
+            break;
+        default:
+            throw new InternalError();
+        }
+        // set the common fields, except CURX, for which we must know the kind
+        // of curve. NOTE: this must be done before the type specific fields
+        // are initialized, because those depend on the common ones.
+        addTo[idx+YMIN] = pts[1];
+        addTo[idx+YMAX] = pts[type-1];
+        addTo[idx+OR] = or;
+        addTo[idx+CURY] = (float)Math.ceil(pts[1]);
+        switch (type) {
+        case 4:
+            initLine(idx, pts, or);
+            break;
+        case 6:
+            initQuad(idx, pts, or);
+            break;
+        case 8:
+            initCurve(idx, pts, or);
+            break;
+        default:
+            throw new InternalError();
+        }
+    }
+
+    // precondition: the curve in pts must be monotonic and increasing in y.
+    private void somethingTo(float[] pts, final int type, final int or) {
+        // NOTE: it's very important that we check for or >= 0 below (as
+        // opposed to or == 1, or or > 0, or anything else). That's
+        // because if we check for or==1, when the curve being added
+        // is a horizontal line, or will be 0 so or==1 will be false and
+        // x0 and y0 will be updated to pts[0] and pts[1] instead of pts[type-2]
+        // and pts[type-1], which is the correct thing to do.
+        this.x0 = or >= 0 ? pts[type - 2] : pts[0];
+        this.y0 = or >= 0 ? pts[type - 1] : pts[1];
+
+        float minY = pts[1], maxY = pts[type - 1];
+        if (Math.ceil(minY) >= Math.ceil(maxY) ||
+            Math.ceil(minY) >= boundsMaxY || maxY < boundsMinY)
+        {
             return;
         }
 
-        int newSize = edgesSize + SIZEOF_STRUCT_EDGE;
-        if (edges.length < newSize) {
-            edges = Arrays.copyOf(edges, newSize * 2);
-        }
-        edges[edgesSize+CURX] = x0;
-        edges[edgesSize+CURY] = y0;
-        edges[edgesSize+Y1] = y1;
-        edges[edgesSize+SLOPE] = (x1 - x0) / (y1 - y0);
-        edges[edgesSize+OR] = or;
-        // the crossing values can't be initialized meaningfully yet. This
-        // will have to wait until setCurY is called
-        edgesSize += SIZEOF_STRUCT_EDGE;
+        if (minY < edgeMinY) { edgeMinY = minY; }
+        if (maxY > edgeMaxY) { edgeMaxY = maxY; }
 
-        // Accumulate edgeMinY and edgeMaxY
-        if (y0 < edgeMinY) { edgeMinY = y0; }
-        if (y1 > edgeMaxY) { edgeMaxY = y1; }
+        int minXidx = (pts[0] < pts[type-2] ? 0 : type - 2);
+        float minX = pts[minXidx];
+        float maxX = pts[type - 2 - minXidx];
+        if (minX < edgeMinX) { edgeMinX = minX; }
+        if (maxX > edgeMaxX) { edgeMaxX = maxX; }
+        addPathSegment(pts, type, or);
     }
 
-    // As far as the following methods care, this edges extends to infinity.
-    // They can compute the x intersect of any horizontal line.
-    // precondition: idx is the index to the start of the desired edge.
-    // So, if the ith edge is wanted, idx should be SIZEOF_STRUCT_EDGE * i
-    private void setCurY(int idx, int y) {
-        // compute the x crossing of edge at idx and horizontal line y
-        // currentXCrossing = (y - y0)*slope + x0
-        edges[idx + CURX] = (y - edges[idx + CURY]) * edges[idx + SLOPE] + edges[idx+CURX];
-        edges[idx + CURY] = (float)y;
-    }
+// END EDGE LIST
+//////////////////////////////////////////////////////////////////////////////
 
-    private void gotoNextY(int idx) {
-        edges[idx + CURY] += 1f; // i.e. curY += 1
-        edges[idx + CURX] += edges[idx + SLOPE]; // i.e. curXCrossing += slope
-    }
-
-    private int getCurCrossing(int idx) {
-        return (int)edges[idx + CURX];
-    }
-//====================================================================================
 
     public static final int WIND_EVEN_ODD = 0;
     public static final int WIND_NON_ZERO = 1;
@@ -284,16 +586,13 @@
     final int MAX_AA_ALPHA;
 
     // Cache to store RLE-encoded coverage mask of the current primitive
-    final PiscesCache cache;
+    PiscesCache cache;
 
     // Bounds of the drawing region, at subpixel precision.
-    final private int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
-
-    // Pixel bounding box for current primitive
-    private int pix_bboxX0, pix_bboxY0, pix_bboxX1, pix_bboxY1;
+    private final int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
 
     // Current winding rule
-    final private int windingRule;
+    private final int windingRule;
 
     // Current drawing position, i.e., final point of last segment
     private float x0, y0;
@@ -304,8 +603,8 @@
     public Renderer(int subpixelLgPositionsX, int subpixelLgPositionsY,
                     int pix_boundsX, int pix_boundsY,
                     int pix_boundsWidth, int pix_boundsHeight,
-                    int windingRule,
-                    PiscesCache cache) {
+                    int windingRule)
+    {
         this.SUBPIXEL_LG_POSITIONS_X = subpixelLgPositionsX;
         this.SUBPIXEL_LG_POSITIONS_Y = subpixelLgPositionsY;
         this.SUBPIXEL_MASK_X = (1 << (SUBPIXEL_LG_POSITIONS_X)) - 1;
@@ -314,23 +613,12 @@
         this.SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
         this.MAX_AA_ALPHA = (SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y);
 
-        this.edges = new float[SIZEOF_STRUCT_EDGE * INIT_NUM_EDGES];
-        edgeMinY = Float.POSITIVE_INFINITY;
-        edgeMaxY = Float.NEGATIVE_INFINITY;
-        edgesSize = 0;
-
         this.windingRule = windingRule;
-        this.cache = cache;
 
         this.boundsMinX = pix_boundsX * SUBPIXEL_POSITIONS_X;
         this.boundsMinY = pix_boundsY * SUBPIXEL_POSITIONS_Y;
         this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X;
         this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y;
-
-        this.pix_bboxX0 = pix_boundsX;
-        this.pix_bboxY0 = pix_boundsY;
-        this.pix_bboxX1 = pix_boundsX + pix_boundsWidth;
-        this.pix_bboxY1 = pix_boundsY + pix_boundsHeight;
     }
 
     private float tosubpixx(float pix_x) {
@@ -341,7 +629,7 @@
     }
 
     public void moveTo(float pix_x0, float pix_y0) {
-        close();
+        closePath();
         this.pix_sx0 = pix_x0;
         this.pix_sy0 = pix_y0;
         this.y0 = tosubpixy(pix_y0);
@@ -350,39 +638,102 @@
 
     public void lineJoin() { /* do nothing */ }
 
-    public void lineTo(float pix_x1, float pix_y1) {
-        float x1 = tosubpixx(pix_x1);
-        float y1 = tosubpixy(pix_y1);
+    private final float[][] pts = new float[2][8];
+    private final float[] ts = new float[4];
+
+    private static void invertPolyPoints(float[] pts, int off, int type) {
+        for (int i = off, j = off + type - 2; i < j; i += 2, j -= 2) {
+            float tmp = pts[i];
+            pts[i] = pts[j];
+            pts[j] = tmp;
+            tmp = pts[i+1];
+            pts[i+1] = pts[j+1];
+            pts[j+1] = tmp;
+        }
+    }
 
-        // Ignore horizontal lines
-        if (y0 == y1) {
-            this.x0 = x1;
-            return;
+    // return orientation before making the curve upright.
+    private static int makeMonotonicCurveUpright(float[] pts, int off, int type) {
+        float y0 = pts[off + 1];
+        float y1 = pts[off + type - 1];
+        if (y0 > y1) {
+            invertPolyPoints(pts, off, type);
+            return -1;
+        } else if (y0 < y1) {
+            return 1;
         }
-
-        addEdge(x0, y0, x1, y1);
+        return 0;
+    }
 
-        this.x0 = x1;
-        this.y0 = y1;
+    public void lineTo(float pix_x1, float pix_y1) {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(pix_x1); pts[0][3] = tosubpixy(pix_y1);
+        int or = makeMonotonicCurveUpright(pts[0], 0, 4);
+        somethingTo(pts[0], 4, or);
     }
 
-    public void close() {
+    Curve c = new Curve();
+    private void curveOrQuadTo(int type) {
+        c.set(pts[0], type);
+        int numTs = c.dxRoots(ts, 0);
+        numTs += c.dyRoots(ts, numTs);
+        numTs = Helpers.filterOutNotInAB(ts, 0, numTs, 0, 1);
+        Helpers.isort(ts, 0, numTs);
+
+        Iterator<float[]> it = Curve.breakPtsAtTs(pts, type, ts, numTs);
+        while(it.hasNext()) {
+            float[] curCurve = it.next();
+            int or = makeMonotonicCurveUpright(curCurve, 0, type);
+            somethingTo(curCurve, type, or);
+        }
+    }
+
+    @Override public void curveTo(float x1, float y1,
+                                  float x2, float y2,
+                                  float x3, float y3)
+    {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
+        pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
+        pts[0][6] = tosubpixx(x3); pts[0][7] = tosubpixy(y3);
+        curveOrQuadTo(8);
+    }
+
+    @Override public void quadTo(float x1, float y1, float x2, float y2) {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
+        pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
+        curveOrQuadTo(6);
+    }
+
+    public void closePath() {
         // lineTo expects its input in pixel coordinates.
         lineTo(pix_sx0, pix_sy0);
     }
 
-    public void end() {
-        close();
+    public void pathDone() {
+        closePath();
     }
 
-    private void _endRendering() {
+
+    @Override
+    public long getNativeConsumer() {
+        throw new InternalError("Renderer does not use a native consumer.");
+    }
+
+    private void _endRendering(final int pix_bboxx0, final int pix_bboxy0,
+                               final int pix_bboxx1, final int pix_bboxy1)
+    {
         // Mask to determine the relevant bit of the crossing sum
         // 0x1 if EVEN_ODD, all bits if NON_ZERO
         int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0;
 
         // add 1 to better deal with the last pixel in a pixel row.
-        int width = ((boundsMaxX - boundsMinX) >> SUBPIXEL_LG_POSITIONS_X) + 1;
-        byte[] alpha = new byte[width+1];
+        int width = pix_bboxx1 - pix_bboxx0 + 1;
+        int[] alpha = new int[width+1];
+
+        int bboxx0 = pix_bboxx0 << SUBPIXEL_LG_POSITIONS_X;
+        int bboxx1 = pix_bboxx1 << SUBPIXEL_LG_POSITIONS_X;
 
         // Now we iterate through the scanlines. We must tell emitRow the coord
         // of the first non-transparent pixel, so we must keep accumulators for
@@ -394,33 +745,34 @@
         int pix_minX = Integer.MAX_VALUE;
 
         int y = boundsMinY; // needs to be declared here so we emit the last row properly.
-        ScanLineItInitialize();
-        for ( ; ScanLineItHasNext(); ) {
-            int numCrossings = ScanLineItGoToNextYAndComputeCrossings();
-            y = ScanLineItCurrentY();
+        ScanlineIterator it = this.new ScanlineIterator();
+        for ( ; it.hasNext(); ) {
+            int numCrossings = it.next();
+            int[] crossings = it.crossings;
+            y = it.curY();
 
             if (numCrossings > 0) {
                 int lowx = crossings[0] >> 1;
                 int highx = crossings[numCrossings - 1] >> 1;
-                int x0 = Math.max(lowx, boundsMinX);
-                int x1 = Math.min(highx, boundsMaxX);
+                int x0 = Math.max(lowx, bboxx0);
+                int x1 = Math.min(highx, bboxx1);
 
                 pix_minX = Math.min(pix_minX, x0 >> SUBPIXEL_LG_POSITIONS_X);
                 pix_maxX = Math.max(pix_maxX, x1 >> SUBPIXEL_LG_POSITIONS_X);
             }
 
             int sum = 0;
-            int prev = boundsMinX;
+            int prev = bboxx0;
             for (int i = 0; i < numCrossings; i++) {
                 int curxo = crossings[i];
                 int curx = curxo >> 1;
                 int crorientation = ((curxo & 0x1) == 0x1) ? 1 : -1;
                 if ((sum & mask) != 0) {
-                    int x0 = Math.max(prev, boundsMinX);
-                    int x1 = Math.min(curx, boundsMaxX);
+                    int x0 = Math.max(prev, bboxx0);
+                    int x1 = Math.min(curx, bboxx1);
                     if (x0 < x1) {
-                        x0 -= boundsMinX; // turn x0, x1 from coords to indeces
-                        x1 -= boundsMinX; // in the alpha array.
+                        x0 -= bboxx0; // turn x0, x1 from coords to indeces
+                        x1 -= bboxx0; // in the alpha array.
 
                         int pix_x = x0 >> SUBPIXEL_LG_POSITIONS_X;
                         int pix_xmaxm1 = (x1 - 1) >> SUBPIXEL_LG_POSITIONS_X;
@@ -442,6 +794,9 @@
                 prev = curx;
             }
 
+            // even if this last row had no crossings, alpha will be zeroed
+            // from the last emitRow call. But this doesn't matter because
+            // maxX < minX, so no row will be emitted to the cache.
             if ((y & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y) {
                 emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
                 pix_minX = Integer.MAX_VALUE;
@@ -453,47 +808,53 @@
         if (pix_maxX >= pix_minX) {
             emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
         }
-        pix_bboxX0 = minX >> SUBPIXEL_LG_POSITIONS_X;
-        pix_bboxX1 = maxX >> SUBPIXEL_LG_POSITIONS_X;
-        pix_bboxY0 = minY >> SUBPIXEL_LG_POSITIONS_Y;
-        pix_bboxY1 = maxY >> SUBPIXEL_LG_POSITIONS_Y;
     }
 
-
     public void endRendering() {
-        // Set up the cache to accumulate the bounding box
-        if (cache != null) {
-            cache.bboxX0 = Integer.MAX_VALUE;
-            cache.bboxY0 = Integer.MAX_VALUE;
-            cache.bboxX1 = Integer.MIN_VALUE;
-            cache.bboxY1 = Integer.MIN_VALUE;
+        final int bminx = boundsMinX >> SUBPIXEL_LG_POSITIONS_X;
+        final int bmaxx = boundsMaxX >> SUBPIXEL_LG_POSITIONS_X;
+        final int bminy = boundsMinY >> SUBPIXEL_LG_POSITIONS_Y;
+        final int bmaxy = boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y;
+        final int eminx = ((int)Math.floor(edgeMinX)) >> SUBPIXEL_LG_POSITIONS_X;
+        final int emaxx = ((int)Math.ceil(edgeMaxX)) >> SUBPIXEL_LG_POSITIONS_X;
+        final int eminy = ((int)Math.floor(edgeMinY)) >> SUBPIXEL_LG_POSITIONS_Y;
+        final int emaxy = ((int)Math.ceil(edgeMaxY)) >> SUBPIXEL_LG_POSITIONS_Y;
+
+        final int minX = Math.max(bminx, eminx);
+        final int maxX = Math.min(bmaxx, emaxx);
+        final int minY = Math.max(bminy, eminy);
+        final int maxY = Math.min(bmaxy, emaxy);
+        if (minX > maxX || minY > maxY) {
+            this.cache = new PiscesCache(bminx, bminy, bmaxx, bmaxy);
+            return;
         }
 
-        _endRendering();
+        this.cache = new PiscesCache(minX, minY, maxX, maxY);
+        _endRendering(minX, minY, maxX, maxY);
     }
 
-    public void getBoundingBox(int[] pix_bbox) {
-        pix_bbox[0] = pix_bboxX0;
-        pix_bbox[1] = pix_bboxY0;
-        pix_bbox[2] = pix_bboxX1 - pix_bboxX0;
-        pix_bbox[3] = pix_bboxY1 - pix_bboxY0;
+    public PiscesCache getCache() {
+        if (cache == null) {
+            throw new InternalError("cache not yet initialized");
+        }
+        return cache;
     }
 
-    private void emitRow(byte[] alphaRow, int pix_y, int pix_from, int pix_to) {
+    private void emitRow(int[] alphaRow, int pix_y, int pix_from, int pix_to) {
         // Copy rowAA data into the cache if one is present
         if (cache != null) {
             if (pix_to >= pix_from) {
-                cache.startRow(pix_y, pix_from, pix_to);
+                cache.startRow(pix_y, pix_from);
 
                 // Perform run-length encoding and store results in the cache
-                int from = pix_from - (boundsMinX >> SUBPIXEL_LG_POSITIONS_X);
-                int to = pix_to - (boundsMinX >> SUBPIXEL_LG_POSITIONS_X);
+                int from = pix_from - cache.bboxX0;
+                int to = pix_to - cache.bboxX0;
 
                 int runLen = 1;
-                byte startVal = alphaRow[from];
+                int startVal = alphaRow[from];
                 for (int i = from + 1; i <= to; i++) {
-                    byte nextVal = (byte)(startVal + alphaRow[i]);
-                    if (nextVal == startVal && runLen < 255) {
+                    int nextVal = startVal + alphaRow[i];
+                    if (nextVal == startVal) {
                         runLen++;
                     } else {
                         cache.addRLERun(startVal, runLen);
@@ -502,9 +863,8 @@
                     }
                 }
                 cache.addRLERun(startVal, runLen);
-                cache.addRLERun((byte)0, 0);
             }
         }
-        java.util.Arrays.fill(alphaRow, (byte)0);
+        java.util.Arrays.fill(alphaRow, 0);
     }
 }
--- a/jdk/src/share/classes/sun/java2d/pisces/Stroker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Stroker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,10 +25,18 @@
 
 package sun.java2d.pisces;
 
-public class Stroker implements LineSink {
+import java.util.Arrays;
+import java.util.Iterator;
+
+import sun.awt.geom.PathConsumer2D;
+
+// TODO: some of the arithmetic here is too verbose and prone to hard to
+// debug typos. We should consider making a small Point/Vector class that
+// has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
+public class Stroker implements PathConsumer2D {
 
     private static final int MOVE_TO = 0;
-    private static final int LINE_TO = 1;
+    private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad
     private static final int CLOSE = 2;
 
     /**
@@ -61,57 +69,37 @@
      */
     public static final int CAP_SQUARE = 2;
 
-    private final LineSink output;
+    private final PathConsumer2D out;
 
     private final int capStyle;
     private final int joinStyle;
 
-    private final float m00, m01, m10, m11, det;
-
     private final float lineWidth2;
-    private final float scaledLineWidth2;
 
-    // For any pen offset (pen_dx, pen_dy) that does not depend on
-    // the line orientation, the pen should be transformed so that:
-    //
-    // pen_dx' = m00*pen_dx + m01*pen_dy
-    // pen_dy' = m10*pen_dx + m11*pen_dy
-    //
-    // For a round pen, this means:
-    //
-    // pen_dx(r, theta) = r*cos(theta)
-    // pen_dy(r, theta) = r*sin(theta)
-    //
-    // pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
-    // pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
-    private int numPenSegments;
-    private final float[] pen_dx;
-    private final float[] pen_dy;
-    private boolean[] penIncluded;
-    private final float[] join;
-
-    private final float[] offset = new float[2];
-    private float[] reverse = new float[100];
+    private final float[][] offset = new float[3][2];
     private final float[] miter = new float[2];
     private final float miterLimitSq;
 
     private int prev;
-    private int rindex;
-    private boolean started;
-    private boolean lineToOrigin;
-    private boolean joinToOrigin;
 
-    private float sx0, sy0, sx1, sy1, x0, y0, px0, py0;
-    private float mx0, my0, omx, omy;
+    // The starting point of the path, and the slope there.
+    private float sx0, sy0, sdx, sdy;
+    // the current point and the slope there.
+    private float cx0, cy0, cdx, cdy; // c stands for current
+    // vectors that when added to (sx0,sy0) and (cx0,cy0) respectively yield the
+    // first and last points on the left parallel path. Since this path is
+    // parallel, it's slope at any point is parallel to the slope of the
+    // original path (thought they may have different directions), so these
+    // could be computed from sdx,sdy and cdx,cdy (and vice versa), but that
+    // would be error prone and hard to read, so we keep these anyway.
+    private float smx, smy, cmx, cmy;
 
-    private float m00_2_m01_2;
-    private float m10_2_m11_2;
-    private float m00_m10_m01_m11;
+    private final PolyStack reverse = new PolyStack();
 
     /**
      * Constructs a <code>Stroker</code>.
      *
-     * @param output an output <code>LineSink</code>.
+     * @param pc2d an output <code>PathConsumer2D</code>.
      * @param lineWidth the desired line width in pixels
      * @param capStyle the desired end cap style, one of
      * <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
@@ -120,183 +108,61 @@
      * <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
      * <code>JOIN_BEVEL</code>.
      * @param miterLimit the desired miter limit
-     * @param transform a <code>Transform4</code> object indicating
-     * the transform that has been previously applied to all incoming
-     * coordinates.  This is required in order to produce consistently
-     * shaped end caps and joins.
      */
-    public Stroker(LineSink output,
+    public Stroker(PathConsumer2D pc2d,
                    float lineWidth,
                    int capStyle,
                    int joinStyle,
-                   float miterLimit,
-                   float m00, float m01, float m10, float m11) {
-        this.output = output;
+                   float miterLimit)
+    {
+        this.out = pc2d;
 
         this.lineWidth2 = lineWidth / 2;
-        this.scaledLineWidth2 = m00 * lineWidth2;
         this.capStyle = capStyle;
         this.joinStyle = joinStyle;
 
-        m00_2_m01_2 = m00*m00 + m01*m01;
-        m10_2_m11_2 = m10*m10 + m11*m11;
-        m00_m10_m01_m11 = m00*m10 + m01*m11;
-
-        this.m00 = m00;
-        this.m01 = m01;
-        this.m10 = m10;
-        this.m11 = m11;
-        det = m00*m11 - m01*m10;
-
-        float limit = miterLimit * lineWidth2 * det;
+        float limit = miterLimit * lineWidth2;
         this.miterLimitSq = limit*limit;
 
-        this.numPenSegments = (int)(3.14159f * lineWidth);
-        this.pen_dx = new float[numPenSegments];
-        this.pen_dy = new float[numPenSegments];
-        this.penIncluded = new boolean[numPenSegments];
-        this.join = new float[2*numPenSegments];
-
-        for (int i = 0; i < numPenSegments; i++) {
-            double theta = (i * 2.0 * Math.PI)/numPenSegments;
-
-            double cos = Math.cos(theta);
-            double sin = Math.sin(theta);
-            pen_dx[i] = (float)(lineWidth2 * (m00*cos + m01*sin));
-            pen_dy[i] = (float)(lineWidth2 * (m10*cos + m11*sin));
-        }
-
-        prev = CLOSE;
-        rindex = 0;
-        started = false;
-        lineToOrigin = false;
+        this.prev = CLOSE;
     }
 
-    private void computeOffset(float x0, float y0,
-                               float x1, float y1, float[] m) {
-        float lx = x1 - x0;
-        float ly = y1 - y0;
-
-        float dx, dy;
-        if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
-            float ilen = (float)Math.hypot(lx, ly);
-            if (ilen == 0) {
-                dx = dy = 0;
-            } else {
-                dx = (ly * scaledLineWidth2)/ilen;
-                dy = -(lx * scaledLineWidth2)/ilen;
-            }
+    private static void computeOffset(final float lx, final float ly,
+                                      final float w, final float[] m)
+    {
+        final float len = (float)Math.hypot(lx, ly);
+        if (len == 0) {
+            m[0] = m[1] = 0;
         } else {
-            int sdet = (det > 0) ? 1 : -1;
-            float a = ly * m00 - lx * m10;
-            float b = ly * m01 - lx * m11;
-            float dh = (float)Math.hypot(a, b);
-            float div = sdet * lineWidth2/dh;
-
-            float ddx = ly * m00_2_m01_2 - lx * m00_m10_m01_m11;
-            float ddy = ly * m00_m10_m01_m11 - lx * m10_2_m11_2;
-            dx = ddx*div;
-            dy = ddy*div;
-        }
-
-        m[0] = dx;
-        m[1] = dy;
-    }
-
-    private void ensureCapacity(int newrindex) {
-        if (reverse.length < newrindex) {
-            reverse = java.util.Arrays.copyOf(reverse, 6*reverse.length/5);
+            m[0] = (ly * w)/len;
+            m[1] = -(lx * w)/len;
         }
     }
 
-    private boolean isCCW(float x0, float y0,
-                          float x1, float y1,
-                          float x2, float y2) {
-        return (x1 - x0) * (y2 - y1) < (y1 - y0) * (x2 - x1);
-    }
-
-    private boolean side(float x,  float y,
-                         float x0, float y0,
-                         float x1, float y1) {
-        return (y0 - y1)*x + (x1 - x0)*y + (x0*y1 - x1*y0) > 0;
-    }
-
-    private int computeRoundJoin(float cx, float cy,
-                                 float xa, float ya,
-                                 float xb, float yb,
-                                 int side,
-                                 boolean flip,
-                                 float[] join) {
-        float px, py;
-        int ncoords = 0;
-
-        boolean centerSide;
-        if (side == 0) {
-            centerSide = side(cx, cy, xa, ya, xb, yb);
-        } else {
-            centerSide = (side == 1);
-        }
-        for (int i = 0; i < numPenSegments; i++) {
-            px = cx + pen_dx[i];
-            py = cy + pen_dy[i];
-
-            boolean penSide = side(px, py, xa, ya, xb, yb);
-            penIncluded[i] = (penSide != centerSide);
-        }
-
-        int start = -1, end = -1;
-        for (int i = 0; i < numPenSegments; i++) {
-            if (penIncluded[i] &&
-                !penIncluded[(i + numPenSegments - 1) % numPenSegments]) {
-                start = i;
-            }
-            if (penIncluded[i] &&
-                !penIncluded[(i + 1) % numPenSegments]) {
-                end = i;
-            }
-        }
-
-        if (end < start) {
-            end += numPenSegments;
-        }
-
-        if (start != -1 && end != -1) {
-            float dxa = cx + pen_dx[start] - xa;
-            float dya = cy + pen_dy[start] - ya;
-            float dxb = cx + pen_dx[start] - xb;
-            float dyb = cy + pen_dy[start] - yb;
-
-            boolean rev = (dxa*dxa + dya*dya > dxb*dxb + dyb*dyb);
-            int i = rev ? end : start;
-            int incr = rev ? -1 : 1;
-            while (true) {
-                int idx = i % numPenSegments;
-                px = cx + pen_dx[idx];
-                py = cy + pen_dy[idx];
-                join[ncoords++] = px;
-                join[ncoords++] = py;
-                if (i == (rev ? start : end)) {
-                    break;
-                }
-                i += incr;
-            }
-        }
-
-        return ncoords/2;
+    // Returns true if the vectors (dx1, dy1) and (dx2, dy2) are
+    // clockwise (if dx1,dy1 needs to be rotated clockwise to close
+    // the smallest angle between it and dx2,dy2).
+    // This is equivalent to detecting whether a point q is on the right side
+    // of a line passing through points p1, p2 where p2 = p1+(dx1,dy1) and
+    // q = p2+(dx2,dy2), which is the same as saying p1, p2, q are in a
+    // clockwise order.
+    // NOTE: "clockwise" here assumes coordinates with 0,0 at the bottom left.
+    private static boolean isCW(final float dx1, final float dy1,
+                                final float dx2, final float dy2)
+    {
+        return dx1 * dy2 <= dy1 * dx2;
     }
 
     // pisces used to use fixed point arithmetic with 16 decimal digits. I
-    // didn't want to change the values of the constants below when I converted
+    // didn't want to change the values of the constant below when I converted
     // it to floating point, so that's why the divisions by 2^16 are there.
     private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
-    private static final float ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000/65536f;
 
     private void drawRoundJoin(float x, float y,
                                float omx, float omy, float mx, float my,
-                               int side,
-                               boolean flip,
                                boolean rev,
-                               float threshold) {
+                               float threshold)
+    {
         if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
             return;
         }
@@ -314,54 +180,148 @@
             mx = -mx;
             my = -my;
         }
+        drawRoundJoin(x, y, omx, omy, mx, my, rev);
+    }
 
-        float bx0 = x + omx;
-        float by0 = y + omy;
-        float bx1 = x + mx;
-        float by1 = y + my;
+    private void drawRoundJoin(float cx, float cy,
+                               float omx, float omy,
+                               float mx, float my,
+                               boolean rev)
+    {
+        // The sign of the dot product of mx,my and omx,omy is equal to the
+        // the sign of the cosine of ext
+        // (ext is the angle between omx,omy and mx,my).
+        double cosext = omx * mx + omy * my;
+        // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
+        // need 1 curve to approximate the circle section that joins omx,omy
+        // and mx,my.
+        final int numCurves = cosext >= 0 ? 1 : 2;
 
-        int npoints = computeRoundJoin(x, y,
-                                       bx0, by0, bx1, by1, side, flip,
-                                       join);
-        for (int i = 0; i < npoints; i++) {
-            emitLineTo(join[2*i], join[2*i + 1], rev);
+        switch (numCurves) {
+        case 1:
+            drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev);
+            break;
+        case 2:
+            // we need to split the arc into 2 arcs spanning the same angle.
+            // The point we want will be one of the 2 intersections of the
+            // perpendicular bisector of the chord (omx,omy)->(mx,my) and the
+            // circle. We could find this by scaling the vector
+            // (omx+mx, omy+my)/2 so that it has length=lineWidth2 (and thus lies
+            // on the circle), but that can have numerical problems when the angle
+            // between omx,omy and mx,my is close to 180 degrees. So we compute a
+            // normal of (omx,omy)-(mx,my). This will be the direction of the
+            // perpendicular bisector. To get one of the intersections, we just scale
+            // this vector that its length is lineWidth2 (this works because the
+            // perpendicular bisector goes through the origin). This scaling doesn't
+            // have numerical problems because we know that lineWidth2 divided by
+            // this normal's length is at least 0.5 and at most sqrt(2)/2 (because
+            // we know the angle of the arc is > 90 degrees).
+            float nx = my - omy, ny = omx - mx;
+            float nlen = (float)Math.sqrt(nx*nx + ny*ny);
+            float scale = lineWidth2/nlen;
+            float mmx = nx * scale, mmy = ny * scale;
+
+            // if (isCW(omx, omy, mx, my) != isCW(mmx, mmy, mx, my)) then we've
+            // computed the wrong intersection so we get the other one.
+            // The test above is equivalent to if (rev).
+            if (rev) {
+                mmx = -mmx;
+                mmy = -mmy;
+            }
+            drawBezApproxForArc(cx, cy, omx, omy, mmx, mmy, rev);
+            drawBezApproxForArc(cx, cy, mmx, mmy, mx, my, rev);
+            break;
         }
     }
 
-    // Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
-    // and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
-    private void computeMiter(float x0, float y0, float x1, float y1,
-                              float x0p, float y0p, float x1p, float y1p,
-                              float[] m) {
+    // the input arc defined by omx,omy and mx,my must span <= 90 degrees.
+    private void drawBezApproxForArc(final float cx, final float cy,
+                                     final float omx, final float omy,
+                                     final float mx, final float my,
+                                     boolean rev)
+    {
+        float cosext2 = (omx * mx + omy * my) / (2 * lineWidth2 * lineWidth2);
+        // cv is the length of P1-P0 and P2-P3 divided by the radius of the arc
+        // (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that
+        // define the bezier curve we're computing.
+        // It is computed using the constraints that P1-P0 and P3-P2 are parallel
+        // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
+        float cv = (float)((4.0 / 3.0) * Math.sqrt(0.5-cosext2) /
+                           (1.0 + Math.sqrt(cosext2+0.5)));
+        // if clockwise, we need to negate cv.
+        if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
+            cv = -cv;
+        }
+        final float x1 = cx + omx;
+        final float y1 = cy + omy;
+        final float x2 = x1 - cv * omy;
+        final float y2 = y1 + cv * omx;
+
+        final float x4 = cx + mx;
+        final float y4 = cy + my;
+        final float x3 = x4 + cv * my;
+        final float y3 = y4 - cv * mx;
+
+        emitCurveTo(x1, y1, x2, y2, x3, y3, x4, y4, rev);
+    }
+
+    private void drawRoundCap(float cx, float cy, float mx, float my) {
+        final float C = 0.5522847498307933f;
+        // the first and second arguments of the following two calls
+        // are really will be ignored by emitCurveTo (because of the false),
+        // but we put them in anyway, as opposed to just giving it 4 zeroes,
+        // because it's just 4 additions and it's not good to rely on this
+        // sort of assumption (right now it's true, but that may change).
+        emitCurveTo(cx+mx,      cy+my,
+                    cx+mx-C*my, cy+my+C*mx,
+                    cx-my+C*mx, cy+mx+C*my,
+                    cx-my,      cy+mx,
+                    false);
+        emitCurveTo(cx-my,      cy+mx,
+                    cx-my-C*mx, cy+mx-C*my,
+                    cx-mx-C*my, cy-my+C*mx,
+                    cx-mx,      cy-my,
+                    false);
+    }
+
+    // Return the intersection point of the lines (x0, y0) -> (x1, y1)
+    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
+    private void computeMiter(final float x0, final float y0,
+                              final float x1, final float y1,
+                              final float x0p, final float y0p,
+                              final float x1p, final float y1p,
+                              final float[] m, int off)
+    {
         float x10 = x1 - x0;
         float y10 = y1 - y0;
         float x10p = x1p - x0p;
         float y10p = y1p - y0p;
 
+        // if this is 0, the lines are parallel. If they go in the
+        // same direction, there is no intersection so m[off] and
+        // m[off+1] will contain infinity, so no miter will be drawn.
+        // If they go in the same direction that means that the start of the
+        // current segment and the end of the previous segment have the same
+        // tangent, in which case this method won't even be involved in
+        // miter drawing because it won't be called by drawMiter (because
+        // (mx == omx && my == omy) will be true, and drawMiter will return
+        // immediately).
         float den = x10*y10p - x10p*y10;
-        if (den == 0) {
-            m[0] = x0;
-            m[1] = y0;
-            return;
-        }
-
-        float t = x1p*(y0 - y0p) - x0*y10p + x0p*(y1p - y0);
-        m[0] = x0 + (t*x10)/den;
-        m[1] = y0 + (t*y10)/den;
+        float t = x10p*(y0-y0p) - y10p*(x0-x0p);
+        t /= den;
+        m[off++] = x0 + t*x10;
+        m[off] = y0 + t*y10;
     }
 
-    private void drawMiter(float px0, float py0,
-                           float x0, float y0,
-                           float x1, float y1,
+    private void drawMiter(final float pdx, final float pdy,
+                           final float x0, final float y0,
+                           final float dx, final float dy,
                            float omx, float omy, float mx, float my,
-                           boolean rev) {
-        if (mx == omx && my == omy) {
-            return;
-        }
-        if (px0 == x0 && py0 == y0) {
-            return;
-        }
-        if (x0 == x1 && y0 == y1) {
+                           boolean rev)
+    {
+        if ((mx == omx && my == omy) ||
+            (pdx == 0 && pdy == 0) ||
+            (dx == 0 && dy == 0)) {
             return;
         }
 
@@ -372,297 +332,734 @@
             my = -my;
         }
 
-        computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy,
-                     x0 + mx, y0 + my, x1 + mx, y1 + my,
-                     miter);
+        computeMiter((x0 - pdx) + omx, (y0 - pdy) + omy, x0 + omx, y0 + omy,
+                     (dx + x0) + mx, (dy + y0) + my, x0 + mx, y0 + my,
+                     miter, 0);
 
-        // Compute miter length in untransformed coordinates
-        float dx = miter[0] - x0;
-        float dy = miter[1] - y0;
-        float a = dy*m00 - dx*m10;
-        float b = dy*m01 - dx*m11;
-        float lenSq = a*a + b*b;
+        float lenSq = (miter[0]-x0)*(miter[0]-x0) + (miter[1]-y0)*(miter[1]-y0);
 
         if (lenSq < miterLimitSq) {
             emitLineTo(miter[0], miter[1], rev);
         }
     }
 
-
     public void moveTo(float x0, float y0) {
-        // System.out.println("Stroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-
-        if (lineToOrigin) {
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        }
-
-        if (prev == LINE_TO) {
+        if (prev == DRAWING_OP_TO) {
             finish();
         }
-
-        this.sx0 = this.x0 = x0;
-        this.sy0 = this.y0 = y0;
-        this.rindex = 0;
-        this.started = false;
-        this.joinSegment = false;
+        this.sx0 = this.cx0 = x0;
+        this.sy0 = this.cy0 = y0;
+        this.cdx = this.sdx = 1;
+        this.cdy = this.sdy = 0;
         this.prev = MOVE_TO;
     }
 
-    boolean joinSegment = false;
-
-    public void lineJoin() {
-        // System.out.println("Stroker.lineJoin()");
-        this.joinSegment = true;
-    }
-
     public void lineTo(float x1, float y1) {
-        // System.out.println("Stroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
+        float dx = x1 - cx0;
+        float dy = y1 - cy0;
+        if (dx == 0f && dy == 0f) {
+            dx = 1;
+        }
+        computeOffset(dx, dy, lineWidth2, offset[0]);
+        float mx = offset[0][0];
+        float my = offset[0][1];
 
-        if (lineToOrigin) {
-            if (x1 == sx0 && y1 == sy0) {
-                // staying in the starting point
-                return;
-            }
+        drawJoin(cdx, cdy, cx0, cy0, dx, dy, cmx, cmy, mx, my);
 
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        } else if (x1 == x0 && y1 == y0) {
-            return;
-        } else if (x1 == sx0 && y1 == sy0) {
-            lineToOrigin = true;
-            joinToOrigin = joinSegment;
-            joinSegment = false;
-            return;
-        }
+        emitLineTo(cx0 + mx, cy0 + my);
+        emitLineTo(x1 + mx, y1 + my);
+
+        emitLineTo(cx0 - mx, cy0 - my, true);
+        emitLineTo(x1 - mx, y1 - my, true);
 
-        lineToImpl(x1, y1, joinSegment);
-        joinSegment = false;
+        this.cmx = mx;
+        this.cmy = my;
+        this.cdx = dx;
+        this.cdy = dy;
+        this.cx0 = x1;
+        this.cy0 = y1;
+        this.prev = DRAWING_OP_TO;
     }
 
-    private void lineToImpl(float x1, float y1, boolean joinSegment) {
-        computeOffset(x0, y0, x1, y1, offset);
-        float mx = offset[0];
-        float my = offset[1];
-
-        if (!started) {
-            emitMoveTo(x0 + mx, y0 + my);
-            this.sx1 = x1;
-            this.sy1 = y1;
-            this.mx0 = mx;
-            this.my0 = my;
-            started = true;
-        } else {
-            boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
-            if (joinSegment) {
-                if (joinStyle == JOIN_MITER) {
-                    drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my,
-                              ccw);
-                } else if (joinStyle == JOIN_ROUND) {
-                    drawRoundJoin(x0, y0,
-                                  omx, omy,
-                                  mx, my, 0, false, ccw,
-                                  ROUND_JOIN_THRESHOLD);
-                }
-            } else {
-                // Draw internal joins as round
-                drawRoundJoin(x0, y0,
-                              omx, omy,
-                              mx, my, 0, false, ccw,
-                              ROUND_JOIN_INTERNAL_THRESHOLD);
+    public void closePath() {
+        if (prev != DRAWING_OP_TO) {
+            if (prev == CLOSE) {
+                return;
             }
-
-            emitLineTo(x0, y0, !ccw);
-        }
-
-        emitLineTo(x0 + mx, y0 + my, false);
-        emitLineTo(x1 + mx, y1 + my, false);
-
-        emitLineTo(x0 - mx, y0 - my, true);
-        emitLineTo(x1 - mx, y1 - my, true);
-
-        this.omx = mx;
-        this.omy = my;
-        this.px0 = x0;
-        this.py0 = y0;
-        this.x0 = x1;
-        this.y0 = y1;
-        this.prev = LINE_TO;
-    }
-
-    public void close() {
-        // System.out.println("Stroker.close()");
-
-        if (lineToOrigin) {
-            // ignore the previous lineTo
-            lineToOrigin = false;
-        }
-
-        if (!started) {
+            emitMoveTo(cx0, cy0 - lineWidth2);
+            this.cmx = this.smx = 0;
+            this.cmy = this.smy = -lineWidth2;
+            this.cdx = this.sdx = 1;
+            this.cdy = this.sdy = 0;
             finish();
             return;
         }
 
-        computeOffset(x0, y0, sx0, sy0, offset);
-        float mx = offset[0];
-        float my = offset[1];
-
-        // Draw penultimate join
-        boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
-        if (joinSegment) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, ccw);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false, ccw,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        } else {
-            // Draw internal joins as round
-            drawRoundJoin(x0, y0,
-                          omx, omy,
-                          mx, my, 0, false, ccw,
-                          ROUND_JOIN_INTERNAL_THRESHOLD);
+        if (cx0 != sx0 || cy0 != sy0) {
+            lineTo(sx0, sy0);
         }
 
-        emitLineTo(x0 + mx, y0 + my);
-        emitLineTo(sx0 + mx, sy0 + my);
-
-        ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
+        drawJoin(cdx, cdy, cx0, cy0, sdx, sdy, cmx, cmy, smx, smy);
 
-        // Draw final join on the outside
-        if (!ccw) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(x0, y0, sx0, sy0, sx1, sy1,
-                          mx, my, mx0, my0, false);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, false, false,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        }
-
-        emitLineTo(sx0 + mx0, sy0 + my0);
-        emitLineTo(sx0 - mx0, sy0 - my0);  // same as reverse[0], reverse[1]
+        emitLineTo(sx0 + smx, sy0 + smy);
 
-        // Draw final join on the inside
-        if (ccw) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(x0, y0, sx0, sy0, sx1, sy1,
-                          -mx, -my, -mx0, -my0, false);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0,
-                              true, false,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        }
+        emitMoveTo(sx0 - smx, sy0 - smy);
+        emitReverse();
 
-        emitLineTo(sx0 - mx, sy0 - my);
-        emitLineTo(x0 - mx, y0 - my);
-        for (int i = rindex - 2; i >= 0; i -= 2) {
-            emitLineTo(reverse[i], reverse[i + 1]);
-        }
-
-        this.x0 = this.sx0;
-        this.y0 = this.sy0;
-        this.rindex = 0;
-        this.started = false;
-        this.joinSegment = false;
         this.prev = CLOSE;
         emitClose();
     }
 
-    public void end() {
-        // System.out.println("Stroker.end()");
+    private void emitReverse() {
+        while(!reverse.isEmpty()) {
+            reverse.pop(out);
+        }
+    }
 
-        if (lineToOrigin) {
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        }
-
-        if (prev == LINE_TO) {
+    public void pathDone() {
+        if (prev == DRAWING_OP_TO) {
             finish();
         }
 
-        output.end();
-        this.joinSegment = false;
-        this.prev = MOVE_TO;
-    }
-
-    double userSpaceLineLength(double dx, double dy) {
-        double a = (dy*m00 - dx*m10)/det;
-        double b = (dy*m01 - dx*m11)/det;
-        return Math.hypot(a, b);
+        out.pathDone();
+        // this shouldn't matter since this object won't be used
+        // after the call to this method.
+        this.prev = CLOSE;
     }
 
     private void finish() {
         if (capStyle == CAP_ROUND) {
-            drawRoundJoin(x0, y0,
-                          omx, omy, -omx, -omy, 1, false, false,
-                          ROUND_JOIN_THRESHOLD);
+            drawRoundCap(cx0, cy0, cmx, cmy);
         } else if (capStyle == CAP_SQUARE) {
-            float dx = px0 - x0;
-            float dy = py0 - y0;
-            float len = (float)userSpaceLineLength(dx, dy);
-            float s = lineWidth2/len;
-
-            float capx = x0 - dx*s;
-            float capy = y0 - dy*s;
-
-            emitLineTo(capx + omx, capy + omy);
-            emitLineTo(capx - omx, capy - omy);
+            emitLineTo(cx0 - cmy + cmx, cy0 + cmx + cmy);
+            emitLineTo(cx0 - cmy - cmx, cy0 + cmx - cmy);
         }
 
-        for (int i = rindex - 2; i >= 0; i -= 2) {
-            emitLineTo(reverse[i], reverse[i + 1]);
-        }
-        this.rindex = 0;
+        emitReverse();
 
         if (capStyle == CAP_ROUND) {
-            drawRoundJoin(sx0, sy0,
-                          -mx0, -my0, mx0, my0, 1, false, false,
-                          ROUND_JOIN_THRESHOLD);
+            drawRoundCap(sx0, sy0, -smx, -smy);
         } else if (capStyle == CAP_SQUARE) {
-            float dx = sx1 - sx0;
-            float dy = sy1 - sy0;
-            float len = (float)userSpaceLineLength(dx, dy);
-            float s = lineWidth2/len;
-
-            float capx = sx0 - dx*s;
-            float capy = sy0 - dy*s;
-
-            emitLineTo(capx - mx0, capy - my0);
-            emitLineTo(capx + mx0, capy + my0);
+            emitLineTo(sx0 + smy - smx, sy0 - smx - smy);
+            emitLineTo(sx0 + smy + smx, sy0 - smx + smy);
         }
 
         emitClose();
-        this.joinSegment = false;
     }
 
-    private void emitMoveTo(float x0, float y0) {
-        // System.out.println("Stroker.emitMoveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-        output.moveTo(x0, y0);
+    private void emitMoveTo(final float x0, final float y0) {
+        out.moveTo(x0, y0);
     }
 
-    private void emitLineTo(float x1, float y1) {
-        // System.out.println("Stroker.emitLineTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-        output.lineTo(x1, y1);
+    private void emitLineTo(final float x1, final float y1) {
+        out.lineTo(x1, y1);
     }
 
-    private void emitLineTo(float x1, float y1, boolean rev) {
+    private void emitLineTo(final float x1, final float y1,
+                            final boolean rev)
+    {
         if (rev) {
-            ensureCapacity(rindex + 2);
-            reverse[rindex++] = x1;
-            reverse[rindex++] = y1;
+            reverse.pushLine(x1, y1);
         } else {
             emitLineTo(x1, y1);
         }
     }
 
+    private void emitQuadTo(final float x0, final float y0,
+                            final float x1, final float y1,
+                            final float x2, final float y2, final boolean rev)
+    {
+        if (rev) {
+            reverse.pushQuad(x0, y0, x1, y1);
+        } else {
+            out.quadTo(x1, y1, x2, y2);
+        }
+    }
+
+    private void emitCurveTo(final float x0, final float y0,
+                             final float x1, final float y1,
+                             final float x2, final float y2,
+                             final float x3, final float y3, final boolean rev)
+    {
+        if (rev) {
+            reverse.pushCubic(x0, y0, x1, y1, x2, y2);
+        } else {
+            out.curveTo(x1, y1, x2, y2, x3, y3);
+        }
+    }
+
     private void emitClose() {
-        // System.out.println("Stroker.emitClose()");
-        output.close();
+        out.closePath();
+    }
+
+    private void drawJoin(float pdx, float pdy,
+                          float x0, float y0,
+                          float dx, float dy,
+                          float omx, float omy,
+                          float mx, float my)
+    {
+        if (prev != DRAWING_OP_TO) {
+            emitMoveTo(x0 + mx, y0 + my);
+            this.sdx = dx;
+            this.sdy = dy;
+            this.smx = mx;
+            this.smy = my;
+        } else {
+            boolean cw = isCW(pdx, pdy, dx, dy);
+            if (joinStyle == JOIN_MITER) {
+                drawMiter(pdx, pdy, x0, y0, dx, dy, omx, omy, mx, my, cw);
+            } else if (joinStyle == JOIN_ROUND) {
+                drawRoundJoin(x0, y0,
+                              omx, omy,
+                              mx, my, cw,
+                              ROUND_JOIN_THRESHOLD);
+            }
+            emitLineTo(x0, y0, !cw);
+        }
+        prev = DRAWING_OP_TO;
+    }
+
+    private static boolean within(final float x1, final float y1,
+                                  final float x2, final float y2,
+                                  final float ERR)
+    {
+        assert ERR > 0 : "";
+        // compare taxicab distance. ERR will always be small, so using
+        // true distance won't give much benefit
+        return (Helpers.within(x1, x2, ERR) &&  // we want to avoid calling Math.abs
+                Helpers.within(y1, y2, ERR)); // this is just as good.
+    }
+
+    private void getLineOffsets(float x1, float y1,
+                                float x2, float y2,
+                                float[] left, float[] right) {
+        computeOffset(x2 - x1, y2 - y1, lineWidth2, offset[0]);
+        left[0] = x1 + offset[0][0];
+        left[1] = y1 + offset[0][1];
+        left[2] = x2 + offset[0][0];
+        left[3] = y2 + offset[0][1];
+        right[0] = x1 - offset[0][0];
+        right[1] = y1 - offset[0][1];
+        right[2] = x2 - offset[0][0];
+        right[3] = y2 - offset[0][1];
+    }
+
+    private int computeOffsetCubic(float[] pts, final int off,
+                                   float[] leftOff, float[] rightOff)
+    {
+        // if p1=p2 or p3=p4 it means that the derivative at the endpoint
+        // vanishes, which creates problems with computeOffset. Usually
+        // this happens when this stroker object is trying to winden
+        // a curve with a cusp. What happens is that curveTo splits
+        // the input curve at the cusp, and passes it to this function.
+        // because of inaccuracies in the splitting, we consider points
+        // equal if they're very close to each other.
+        final float x1 = pts[off + 0], y1 = pts[off + 1];
+        final float x2 = pts[off + 2], y2 = pts[off + 3];
+        final float x3 = pts[off + 4], y3 = pts[off + 5];
+        final float x4 = pts[off + 6], y4 = pts[off + 7];
+
+        float dx4 = x4 - x3;
+        float dy4 = y4 - y3;
+        float dx1 = x2 - x1;
+        float dy1 = y2 - y1;
+
+        // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
+        // in which case ignore if p1 == p2
+        final boolean p1eqp2 = within(x1,y1,x2,y2, 6 * Math.ulp(y2));
+        final boolean p3eqp4 = within(x3,y3,x4,y4, 6 * Math.ulp(y4));
+        if (p1eqp2 && p3eqp4) {
+            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
+            return 4;
+        } else if (p1eqp2) {
+            dx1 = x3 - x1;
+            dy1 = y3 - y1;
+        } else if (p3eqp4) {
+            dx4 = x4 - x2;
+            dy4 = y4 - y2;
+        }
+
+        // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
+        float dotsq = (dx1 * dx4 + dy1 * dy4);
+        dotsq = dotsq * dotsq;
+        float l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
+        if (Helpers.within(dotsq, l1sq * l4sq, 4 * Math.ulp(dotsq))) {
+            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
+            return 4;
+        }
+
+//      What we're trying to do in this function is to approximate an ideal
+//      offset curve (call it I) of the input curve B using a bezier curve Bp.
+//      The constraints I use to get the equations are:
+//
+//      1. The computed curve Bp should go through I(0) and I(1). These are
+//      x1p, y1p, x4p, y4p, which are p1p and p4p. We still need to find
+//      4 variables: the x and y components of p2p and p3p (i.e. x2p, y2p, x3p, y3p).
+//
+//      2. Bp should have slope equal in absolute value to I at the endpoints. So,
+//      (by the way, the operator || in the comments below means "aligned with".
+//      It is defined on vectors, so when we say I'(0) || Bp'(0) we mean that
+//      vectors I'(0) and Bp'(0) are aligned, which is the same as saying
+//      that the tangent lines of I and Bp at 0 are parallel. Mathematically
+//      this means (I'(t) || Bp'(t)) <==> (I'(t) = c * Bp'(t)) where c is some
+//      nonzero constant.)
+//      I'(0) || Bp'(0) and I'(1) || Bp'(1). Obviously, I'(0) || B'(0) and
+//      I'(1) || B'(1); therefore, Bp'(0) || B'(0) and Bp'(1) || B'(1).
+//      We know that Bp'(0) || (p2p-p1p) and Bp'(1) || (p4p-p3p) and the same
+//      is true for any bezier curve; therefore, we get the equations
+//          (1) p2p = c1 * (p2-p1) + p1p
+//          (2) p3p = c2 * (p4-p3) + p4p
+//      We know p1p, p4p, p2, p1, p3, and p4; therefore, this reduces the number
+//      of unknowns from 4 to 2 (i.e. just c1 and c2).
+//      To eliminate these 2 unknowns we use the following constraint:
+//
+//      3. Bp(0.5) == I(0.5). Bp(0.5)=(x,y) and I(0.5)=(xi,yi), and I should note
+//      that I(0.5) is *the only* reason for computing dxm,dym. This gives us
+//          (3) Bp(0.5) = (p1p + 3 * (p2p + p3p) + p4p)/8, which is equivalent to
+//          (4) p2p + p3p = (Bp(0.5)*8 - p1p - p4p) / 3
+//      We can substitute (1) and (2) from above into (4) and we get:
+//          (5) c1*(p2-p1) + c2*(p4-p3) = (Bp(0.5)*8 - p1p - p4p)/3 - p1p - p4p
+//      which is equivalent to
+//          (6) c1*(p2-p1) + c2*(p4-p3) = (4/3) * (Bp(0.5) * 2 - p1p - p4p)
+//
+//      The right side of this is a 2D vector, and we know I(0.5), which gives us
+//      Bp(0.5), which gives us the value of the right side.
+//      The left side is just a matrix vector multiplication in disguise. It is
+//
+//      [x2-x1, x4-x3][c1]
+//      [y2-y1, y4-y3][c2]
+//      which, is equal to
+//      [dx1, dx4][c1]
+//      [dy1, dy4][c2]
+//      At this point we are left with a simple linear system and we solve it by
+//      getting the inverse of the matrix above. Then we use [c1,c2] to compute
+//      p2p and p3p.
+
+        float x = 0.125f * (x1 + 3 * (x2 + x3) + x4);
+        float y = 0.125f * (y1 + 3 * (y2 + y3) + y4);
+        // (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
+        // c*B'(0.5) for some constant c.
+        float dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
+
+        // this computes the offsets at t=0, 0.5, 1, using the property that
+        // for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
+        // the (dx/dt, dy/dt) vectors at the endpoints.
+        computeOffset(dx1, dy1, lineWidth2, offset[0]);
+        computeOffset(dxm, dym, lineWidth2, offset[1]);
+        computeOffset(dx4, dy4, lineWidth2, offset[2]);
+        float x1p = x1 + offset[0][0]; // start
+        float y1p = y1 + offset[0][1]; // point
+        float xi  = x + offset[1][0]; // interpolation
+        float yi  = y + offset[1][1]; // point
+        float x4p = x4 + offset[2][0]; // end
+        float y4p = y4 + offset[2][1]; // point
+
+        float invdet43 = 4f / (3f * (dx1 * dy4 - dy1 * dx4));
+
+        float two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
+        float two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
+        float c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
+        float c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
+
+        float x2p, y2p, x3p, y3p;
+        x2p = x1p + c1*dx1;
+        y2p = y1p + c1*dy1;
+        x3p = x4p + c2*dx4;
+        y3p = y4p + c2*dy4;
+
+        leftOff[0] = x1p; leftOff[1] = y1p;
+        leftOff[2] = x2p; leftOff[3] = y2p;
+        leftOff[4] = x3p; leftOff[5] = y3p;
+        leftOff[6] = x4p; leftOff[7] = y4p;
+
+        x1p = x1 - offset[0][0]; y1p = y1 - offset[0][1];
+        xi = xi - 2 * offset[1][0]; yi = yi - 2 * offset[1][1];
+        x4p = x4 - offset[2][0]; y4p = y4 - offset[2][1];
+
+        two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
+        two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
+        c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
+        c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
+
+        x2p = x1p + c1*dx1;
+        y2p = y1p + c1*dy1;
+        x3p = x4p + c2*dx4;
+        y3p = y4p + c2*dy4;
+
+        rightOff[0] = x1p; rightOff[1] = y1p;
+        rightOff[2] = x2p; rightOff[3] = y2p;
+        rightOff[4] = x3p; rightOff[5] = y3p;
+        rightOff[6] = x4p; rightOff[7] = y4p;
+        return 8;
+    }
+
+    // compute offset curves using bezier spline through t=0.5 (i.e.
+    // ComputedCurve(0.5) == IdealParallelCurve(0.5))
+    // return the kind of curve in the right and left arrays.
+    private int computeOffsetQuad(float[] pts, final int off,
+                                  float[] leftOff, float[] rightOff)
+    {
+        final float x1 = pts[off + 0], y1 = pts[off + 1];
+        final float x2 = pts[off + 2], y2 = pts[off + 3];
+        final float x3 = pts[off + 4], y3 = pts[off + 5];
+
+        float dx3 = x3 - x2;
+        float dy3 = y3 - y2;
+        float dx1 = x2 - x1;
+        float dy1 = y2 - y1;
+
+        // if p1=p2 or p3=p4 it means that the derivative at the endpoint
+        // vanishes, which creates problems with computeOffset. Usually
+        // this happens when this stroker object is trying to winden
+        // a curve with a cusp. What happens is that curveTo splits
+        // the input curve at the cusp, and passes it to this function.
+        // because of inaccuracies in the splitting, we consider points
+        // equal if they're very close to each other.
+
+        // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
+        // in which case ignore.
+        final boolean p1eqp2 = within(x1,y1,x2,y2, 6 * Math.ulp(y2));
+        final boolean p2eqp3 = within(x2,y2,x3,y3, 6 * Math.ulp(y3));
+        if (p1eqp2 || p2eqp3) {
+            getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
+            return 4;
+        }
+
+        // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
+        float dotsq = (dx1 * dx3 + dy1 * dy3);
+        dotsq = dotsq * dotsq;
+        float l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
+        if (Helpers.within(dotsq, l1sq * l3sq, 4 * Math.ulp(dotsq))) {
+            getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
+            return 4;
+        }
+
+        // this computes the offsets at t=0, 0.5, 1, using the property that
+        // for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
+        // the (dx/dt, dy/dt) vectors at the endpoints.
+        computeOffset(dx1, dy1, lineWidth2, offset[0]);
+        computeOffset(dx3, dy3, lineWidth2, offset[1]);
+        float x1p = x1 + offset[0][0]; // start
+        float y1p = y1 + offset[0][1]; // point
+        float x3p = x3 + offset[1][0]; // end
+        float y3p = y3 + offset[1][1]; // point
+
+        computeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
+        leftOff[0] = x1p; leftOff[1] = y1p;
+        leftOff[4] = x3p; leftOff[5] = y3p;
+        x1p = x1 - offset[0][0]; y1p = y1 - offset[0][1];
+        x3p = x3 - offset[1][0]; y3p = y3 - offset[1][1];
+        computeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
+        rightOff[0] = x1p; rightOff[1] = y1p;
+        rightOff[4] = x3p; rightOff[5] = y3p;
+        return 6;
+    }
+
+    // This is where the curve to be processed is put. We give it
+    // enough room to store 2 curves: one for the current subdivision, the
+    // other for the rest of the curve.
+    private float[][] middle = new float[2][8];
+    private float[] lp = new float[8];
+    private float[] rp = new float[8];
+    private static final int MAX_N_CURVES = 11;
+    private float[] subdivTs = new float[MAX_N_CURVES - 1];
+
+    private void somethingTo(final int type) {
+        // need these so we can update the state at the end of this method
+        final float xf = middle[0][type-2], yf = middle[0][type-1];
+        float dxs = middle[0][2] - middle[0][0];
+        float dys = middle[0][3] - middle[0][1];
+        float dxf = middle[0][type - 2] - middle[0][type - 4];
+        float dyf = middle[0][type - 1] - middle[0][type - 3];
+        switch(type) {
+        case 6:
+            if ((dxs == 0f && dys == 0f) ||
+                (dxf == 0f && dyf == 0f)) {
+               dxs = dxf = middle[0][4] - middle[0][0];
+               dys = dyf = middle[0][5] - middle[0][1];
+            }
+            break;
+        case 8:
+            boolean p1eqp2 = (dxs == 0f && dys == 0f);
+            boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+            if (p1eqp2) {
+                dxs = middle[0][4] - middle[0][0];
+                dys = middle[0][5] - middle[0][1];
+                if (dxs == 0f && dys == 0f) {
+                    dxs = middle[0][6] - middle[0][0];
+                    dys = middle[0][7] - middle[0][1];
+                }
+            }
+            if (p3eqp4) {
+                dxf = middle[0][6] - middle[0][2];
+                dyf = middle[0][7] - middle[0][3];
+                if (dxf == 0f && dyf == 0f) {
+                    dxf = middle[0][6] - middle[0][0];
+                    dyf = middle[0][7] - middle[0][1];
+                }
+            }
+        }
+        if (dxs == 0f && dys == 0f) {
+            // this happens iff the "curve" is just a point
+            lineTo(middle[0][0], middle[0][1]);
+            return;
+        }
+        // if these vectors are too small, normalize them, to avoid future
+        // precision problems.
+        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
+            double len = Math.hypot(dxs, dys);
+            dxs = (float)(dxs / len);
+            dys = (float)(dys / len);
+        }
+        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
+            double len = Math.hypot(dxf, dyf);
+            dxf = (float)(dxf / len);
+            dyf = (float)(dyf / len);
+        }
+
+        computeOffset(dxs, dys, lineWidth2, offset[0]);
+        final float mx = offset[0][0];
+        final float my = offset[0][1];
+        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
+
+        int nSplits = findSubdivPoints(middle[0], subdivTs, type,lineWidth2);
+
+        int kind = 0;
+        Iterator<float[]> it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
+        while(it.hasNext()) {
+            float[] curCurve = it.next();
+
+            kind = 0;
+            switch (type) {
+            case 8:
+                kind = computeOffsetCubic(curCurve, 0, lp, rp);
+                break;
+            case 6:
+                kind = computeOffsetQuad(curCurve, 0, lp, rp);
+                break;
+            }
+            if (kind != 0) {
+                emitLineTo(lp[0], lp[1]);
+                switch(kind) {
+                case 8:
+                    emitCurveTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], lp[6], lp[7], false);
+                    emitCurveTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7], true);
+                    break;
+                case 6:
+                    emitQuadTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], false);
+                    emitQuadTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], true);
+                    break;
+                case 4:
+                    emitLineTo(lp[2], lp[3]);
+                    emitLineTo(rp[0], rp[1], true);
+                    break;
+                }
+                emitLineTo(rp[kind - 2], rp[kind - 1], true);
+            }
+        }
+
+        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
+        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
+        this.cdx = dxf;
+        this.cdy = dyf;
+        this.cx0 = xf;
+        this.cy0 = yf;
+        this.prev = DRAWING_OP_TO;
+    }
+
+    // finds values of t where the curve in pts should be subdivided in order
+    // to get good offset curves a distance of w away from the middle curve.
+    // Stores the points in ts, and returns how many of them there were.
+    private static Curve c = new Curve();
+    private static int findSubdivPoints(float[] pts, float[] ts,
+                                        final int type, final float w)
+    {
+        final float x12 = pts[2] - pts[0];
+        final float y12 = pts[3] - pts[1];
+        // if the curve is already parallel to either axis we gain nothing
+        // from rotating it.
+        if (y12 != 0f && x12 != 0f) {
+            // we rotate it so that the first vector in the control polygon is
+            // parallel to the x-axis. This will ensure that rotated quarter
+            // circles won't be subdivided.
+            final float hypot = (float)Math.sqrt(x12 * x12 + y12 * y12);
+            final float cos = x12 / hypot;
+            final float sin = y12 / hypot;
+            final float x1 = cos * pts[0] + sin * pts[1];
+            final float y1 = cos * pts[1] - sin * pts[0];
+            final float x2 = cos * pts[2] + sin * pts[3];
+            final float y2 = cos * pts[3] - sin * pts[2];
+            final float x3 = cos * pts[4] + sin * pts[5];
+            final float y3 = cos * pts[5] - sin * pts[4];
+            switch(type) {
+            case 8:
+                final float x4 = cos * pts[6] + sin * pts[7];
+                final float y4 = cos * pts[7] - sin * pts[6];
+                c.set(x1, y1, x2, y2, x3, y3, x4, y4);
+                break;
+            case 6:
+                c.set(x1, y1, x2, y2, x3, y3);
+                break;
+            }
+        } else {
+            c.set(pts, type);
+        }
+
+        int ret = 0;
+        // we subdivide at values of t such that the remaining rotated
+        // curves are monotonic in x and y.
+        ret += c.dxRoots(ts, ret);
+        ret += c.dyRoots(ts, ret);
+        // subdivide at inflection points.
+        if (type == 8) {
+            // quadratic curves can't have inflection points
+            ret += c.infPoints(ts, ret);
+        }
+
+        // now we must subdivide at points where one of the offset curves will have
+        // a cusp. This happens at ts where the radius of curvature is equal to w.
+        ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f);
+        ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f);
+        Helpers.isort(ts, 0, ret);
+        return ret;
+    }
+
+    @Override public void curveTo(float x1, float y1,
+                                  float x2, float y2,
+                                  float x3, float y3)
+    {
+        middle[0][0] = cx0; middle[0][1] = cy0;
+        middle[0][2] = x1; middle[0][3] = y1;
+        middle[0][4] = x2; middle[0][5] = y2;
+        middle[0][6] = x3; middle[0][7] = y3;
+        somethingTo(8);
+    }
+
+    @Override public long getNativeConsumer() {
+        throw new InternalError("Stroker doesn't use a native consumer");
+    }
+
+    @Override public void quadTo(float x1, float y1, float x2, float y2) {
+        middle[0][0] = cx0; middle[0][1] = cy0;
+        middle[0][2] = x1; middle[0][3] = y1;
+        middle[0][4] = x2; middle[0][5] = y2;
+        somethingTo(6);
+    }
+
+    // a stack of polynomial curves where each curve shares endpoints with
+    // adjacent ones.
+    private static final class PolyStack {
+        float[] curves;
+        int end;
+        int[] curveTypes;
+        int numCurves;
+
+        private static final int INIT_SIZE = 50;
+
+        PolyStack() {
+            curves = new float[8 * INIT_SIZE];
+            curveTypes = new int[INIT_SIZE];
+            end = 0;
+            numCurves = 0;
+        }
+
+        public boolean isEmpty() {
+            return numCurves == 0;
+        }
+
+        private void ensureSpace(int n) {
+            if (end + n >= curves.length) {
+                int newSize = (end + n) * 2;
+                curves = Arrays.copyOf(curves, newSize);
+            }
+            if (numCurves >= curveTypes.length) {
+                int newSize = numCurves * 2;
+                curveTypes = Arrays.copyOf(curveTypes, newSize);
+            }
+        }
+
+        public void pushCubic(float x0, float y0,
+                              float x1, float y1,
+                              float x2, float y2)
+        {
+            ensureSpace(6);
+            curveTypes[numCurves++] = 8;
+            // assert(x0 == lastX && y0 == lastY)
+
+            // we reverse the coordinate order to make popping easier
+            curves[end++] = x2;    curves[end++] = y2;
+            curves[end++] = x1;    curves[end++] = y1;
+            curves[end++] = x0;    curves[end++] = y0;
+        }
+
+        public void pushQuad(float x0, float y0,
+                             float x1, float y1)
+        {
+            ensureSpace(4);
+            curveTypes[numCurves++] = 6;
+            // assert(x0 == lastX && y0 == lastY)
+            curves[end++] = x1;    curves[end++] = y1;
+            curves[end++] = x0;    curves[end++] = y0;
+        }
+
+        public void pushLine(float x, float y) {
+            ensureSpace(2);
+            curveTypes[numCurves++] = 4;
+            // assert(x0 == lastX && y0 == lastY)
+            curves[end++] = x;    curves[end++] = y;
+        }
+
+        @SuppressWarnings("unused")
+        public int pop(float[] pts) {
+            int ret = curveTypes[numCurves - 1];
+            numCurves--;
+            end -= (ret - 2);
+            System.arraycopy(curves, end, pts, 0, ret - 2);
+            return ret;
+        }
+
+        public void pop(PathConsumer2D io) {
+            numCurves--;
+            int type = curveTypes[numCurves];
+            end -= (type - 2);
+            switch(type) {
+            case 8:
+                io.curveTo(curves[end+0], curves[end+1],
+                           curves[end+2], curves[end+3],
+                           curves[end+4], curves[end+5]);
+                break;
+            case 6:
+                io.quadTo(curves[end+0], curves[end+1],
+                           curves[end+2], curves[end+3]);
+                 break;
+            case 4:
+                io.lineTo(curves[end], curves[end+1]);
+            }
+        }
+
+        @Override
+        public String toString() {
+            String ret = "";
+            int nc = numCurves;
+            int end = this.end;
+            while (nc > 0) {
+                nc--;
+                int type = curveTypes[numCurves];
+                end -= (type - 2);
+                switch(type) {
+                case 8:
+                    ret += "cubic: ";
+                    break;
+                case 6:
+                    ret += "quad: ";
+                    break;
+                case 4:
+                    ret += "line: ";
+                    break;
+                }
+                ret += Arrays.toString(Arrays.copyOfRange(curves, end, end+type-2)) + "\n";
+            }
+            return ret;
+        }
     }
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,229 @@
+/*
+ * 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 sun.java2d.pisces;
+
+import sun.awt.geom.PathConsumer2D;
+import java.awt.geom.AffineTransform;
+
+public class TransformingPathConsumer2D {
+    public static PathConsumer2D
+        transformConsumer(PathConsumer2D out,
+                          AffineTransform at)
+    {
+        if (at == null) {
+            return out;
+        }
+        float Mxx = (float) at.getScaleX();
+        float Mxy = (float) at.getShearX();
+        float Mxt = (float) at.getTranslateX();
+        float Myx = (float) at.getShearY();
+        float Myy = (float) at.getScaleY();
+        float Myt = (float) at.getTranslateY();
+        if (Mxy == 0f && Myx == 0f) {
+            if (Mxx == 1f && Myy == 1f) {
+                if (Mxt == 0f && Myt == 0f) {
+                    return out;
+                } else {
+                    return new TranslateFilter(out, Mxt, Myt);
+                }
+            } else {
+                return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
+            }
+        } else {
+            return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt);
+        }
+    }
+
+    static class TranslateFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float tx;
+        float ty;
+
+        TranslateFilter(PathConsumer2D out,
+                        float tx, float ty)
+        {
+            this.out = out;
+            this.tx = tx;
+            this.ty = ty;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 + tx, y0 + ty);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 + tx, y1 + ty);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 + tx, y1 + ty,
+                       x2 + tx, y2 + ty);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 + tx, y1 + ty,
+                        x2 + tx, y2 + ty,
+                        x3 + tx, y3 + ty);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+
+    static class ScaleFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float sx;
+        float sy;
+        float tx;
+        float ty;
+
+        ScaleFilter(PathConsumer2D out,
+                    float sx, float sy, float tx, float ty)
+        {
+            this.out = out;
+            this.sx = sx;
+            this.sy = sy;
+            this.tx = tx;
+            this.ty = ty;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 * sx + tx, y0 * sy + ty);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 * sx + tx, y1 * sy + ty);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 * sx + tx, y1 * sy + ty,
+                       x2 * sx + tx, y2 * sy + ty);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 * sx + tx, y1 * sy + ty,
+                        x2 * sx + tx, y2 * sy + ty,
+                        x3 * sx + tx, y3 * sy + ty);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+
+    static class TransformFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float Mxx;
+        float Mxy;
+        float Mxt;
+        float Myx;
+        float Myy;
+        float Myt;
+
+        TransformFilter(PathConsumer2D out,
+                        float Mxx, float Mxy, float Mxt,
+                        float Myx, float Myy, float Myt)
+        {
+            this.out = out;
+            this.Mxx = Mxx;
+            this.Mxy = Mxy;
+            this.Mxt = Mxt;
+            this.Myx = Myx;
+            this.Myy = Myy;
+            this.Myt = Myt;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 * Mxx + y0 * Mxy + Mxt,
+                       x0 * Myx + y0 * Myy + Myt);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 * Mxx + y1 * Mxy + Mxt,
+                       x1 * Myx + y1 * Myy + Myt);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 * Mxx + y1 * Mxy + Mxt,
+                       x1 * Myx + y1 * Myy + Myt,
+                       x2 * Mxx + y2 * Mxy + Mxt,
+                       x2 * Myx + y2 * Myy + Myt);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 * Mxx + y1 * Mxy + Mxt,
+                        x1 * Myx + y1 * Myy + Myt,
+                        x2 * Mxx + y2 * Mxy + Mxt,
+                        x2 * Myx + y2 * Myy + Myt,
+                        x3 * Mxx + y3 * Mxy + Mxt,
+                        x3 * Myx + y3 * Myy + Myt);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/net/InetAddressCachePolicy.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/net/InetAddressCachePolicy.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,7 +25,6 @@
 
 package sun.net;
 
-import java.net.InetAddress;
 import java.security.PrivilegedAction;
 import java.security.Security;
 
@@ -57,7 +56,7 @@
      * caching. For security reasons, this caching is made forever when
      * a security manager is set.
      */
-    private static int cachePolicy;
+    private static int cachePolicy = FOREVER;
 
     /* The Java-level namelookup cache policy for negative lookups:
      *
@@ -67,31 +66,24 @@
      * default value is 0. It can be set to some other value for
      * performance reasons.
      */
-    private static int negativeCachePolicy;
+    private static int negativeCachePolicy = NEVER;
 
     /*
      * Whether or not the cache policy for successful lookups was set
      * using a property (cmd line).
      */
-    private static boolean set = false;
+    private static boolean propertySet;
 
     /*
      * Whether or not the cache policy for negative lookups was set
      * using a property (cmd line).
      */
-    private static boolean negativeSet = false;
+    private static boolean propertyNegativeSet;
 
     /*
      * Initialize
      */
     static {
-
-        set = false;
-        negativeSet = false;
-
-        cachePolicy = FOREVER;
-        negativeCachePolicy =  0;
-
         Integer tmp = null;
 
         try {
@@ -110,7 +102,7 @@
             if (cachePolicy < 0) {
                 cachePolicy = FOREVER;
             }
-            set = true;
+            propertySet = true;
         } else {
             tmp = java.security.AccessController.doPrivileged
                 (new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
@@ -119,7 +111,14 @@
                 if (cachePolicy < 0) {
                     cachePolicy = FOREVER;
                 }
-                set = true;
+                propertySet = true;
+            } else {
+                /* No properties defined for positive caching. If there is no
+                 * security manager then use the default positive cache value.
+                 */
+                if (System.getSecurityManager() == null) {
+                    cachePolicy = DEFAULT_POSITIVE;
+                }
             }
         }
 
@@ -140,7 +139,7 @@
             if (negativeCachePolicy < 0) {
                 negativeCachePolicy = FOREVER;
             }
-            negativeSet = true;
+            propertyNegativeSet = true;
         } else {
             tmp = java.security.AccessController.doPrivileged
                 (new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
@@ -149,17 +148,13 @@
                 if (negativeCachePolicy < 0) {
                     negativeCachePolicy = FOREVER;
                 }
-                negativeSet = true;
+                propertyNegativeSet = true;
             }
         }
     }
 
     public static synchronized int get() {
-        if (!set && System.getSecurityManager() == null) {
-            return DEFAULT_POSITIVE;
-        } else {
-            return cachePolicy;
-        }
+        return cachePolicy;
     }
 
     public static synchronized int getNegative() {
@@ -174,21 +169,17 @@
      * should be cached
      */
     public static synchronized void setIfNotSet(int newPolicy) {
-
         /*
          * When setting the new value we may want to signal that the
          * cache should be flushed, though this doesn't seem strictly
          * necessary.
          */
-
-        if (!set) {
+        if (!propertySet) {
             checkValue(newPolicy, cachePolicy);
             cachePolicy = newPolicy;
         }
-
     }
 
-
     /**
      * Sets the cache policy for negative lookups if the user has not
      * already specified a cache policy for it using a
@@ -197,14 +188,12 @@
      * should be cached
      */
     public static synchronized void setNegativeIfNotSet(int newPolicy) {
-
         /*
          * When setting the new value we may want to signal that the
          * cache should be flushed, though this doesn't seem strictly
          * necessary.
          */
-
-        if (!negativeSet) {
+        if (!propertyNegativeSet) {
             // Negative caching does not seem to have any security
             // implications.
             // checkValue(newPolicy, negativeCachePolicy);
@@ -213,13 +202,11 @@
     }
 
     private static void checkValue(int newPolicy, int oldPolicy) {
-
         /*
          * If malicious code gets a hold of this method, prevent
          * setting the cache policy to something laxer or some
          * invalid negative value.
          */
-
         if (newPolicy == FOREVER)
             return;
 
@@ -229,7 +216,6 @@
 
             throw new
                 SecurityException("can't make InetAddress cache more lax");
-
         }
     }
 }
--- a/jdk/src/share/classes/sun/net/NetworkClient.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/net/NetworkClient.java	Tue Nov 09 22:53:18 2010 -0800
@@ -40,6 +40,12 @@
  * @author      Jonathan Payne
  */
 public class NetworkClient {
+    /* Default value of read timeout, if not specified (infinity) */
+    public static final int DEFAULT_READ_TIMEOUT = -1;
+
+    /* Default value of connect timeout, if not specified (infinity) */
+    public static final int DEFAULT_CONNECT_TIMEOUT = -1;
+
     protected Proxy     proxy = Proxy.NO_PROXY;
     /** Socket for communicating with server. */
     protected Socket    serverSocket = null;
@@ -53,8 +59,8 @@
     protected static int defaultSoTimeout;
     protected static int defaultConnectTimeout;
 
-    protected int readTimeout = -1;
-    protected int connectTimeout = -1;
+    protected int readTimeout = DEFAULT_READ_TIMEOUT;
+    protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
     /* Name of encoding to use for output */
     protected static String encoding;
 
@@ -71,16 +77,12 @@
                         return null;
             }
         });
-        if (vals[0] == 0)
-            defaultSoTimeout = -1;
-        else
+        if (vals[0] != 0) {
             defaultSoTimeout = vals[0];
-
-        if (vals[1] == 0)
-            defaultConnectTimeout = -1;
-        else
+        }
+        if (vals[1] != 0) {
             defaultConnectTimeout = vals[1];
-
+        }
 
         encoding = encs[0];
         try {
@@ -232,7 +234,23 @@
         return connectTimeout;
     }
 
+    /**
+     * Sets the read timeout.
+     *
+     * Note: Public URLConnection (and protocol specific implementations)
+     * protect against negative timeout values being set. This implemenation,
+     * and protocol specific implementations, use -1 to represent the default
+     * read timeout.
+     *
+     * This method may be invoked with the default timeout value when the
+     * protocol handler is trying to reset the timeout after doing a
+     * potentially blocking internal operation, e.g. cleaning up unread
+     * response data, buffering error stream response data, etc
+     */
     public void setReadTimeout(int timeout) {
+        if (timeout == DEFAULT_READ_TIMEOUT)
+            timeout = defaultSoTimeout;
+
         if (serverSocket != null && timeout >= 0) {
             try {
                 serverSocket.setSoTimeout(timeout);
--- a/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Tue Nov 09 22:53:18 2010 -0800
@@ -46,6 +46,7 @@
 import java.util.StringTokenizer;
 import java.util.Iterator;
 import java.security.Permission;
+import sun.net.NetworkClient;
 import sun.net.www.MessageHeader;
 import sun.net.www.MeteredStream;
 import sun.net.www.URLConnection;
@@ -102,11 +103,11 @@
     static final int BIN = 2;
     static final int DIR = 3;
     int type = NONE;
-    /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
+    /* Redefine timeouts from java.net.URLConnection as we need -1 to mean
      * not set. This is to ensure backward compatibility.
      */
-    private int connectTimeout = -1;
-    private int readTimeout = -1;
+    private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;;
+    private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;;
 
     /**
      * For FTP URLs we need to have a special InputStream because we
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Nov 09 22:53:18 2010 -0800
@@ -359,11 +359,11 @@
 
     private TunnelState tunnelState = TunnelState.NONE;
 
-    /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
+    /* Redefine timeouts from java.net.URLConnection as we need -1 to mean
      * not set. This is to ensure backward compatibility.
      */
-    private int connectTimeout = -1;
-    private int readTimeout = -1;
+    private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;
+    private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;
 
     /* Logging support */
     private static final PlatformLogger logger =
@@ -1041,9 +1041,9 @@
                     throw new ProtocolException("Server rejected operation");
                 }
             }
-            if (oldTimeout > 0) {
-                http.setReadTimeout(oldTimeout);
-            }
+
+            http.setReadTimeout(oldTimeout);
+
             responseCode = -1;
             responses.reset();
             // Proceed
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -109,6 +109,10 @@
     // 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.HttpsURLConnection.DefaultHostnameVerifier";
+
     /** Returns the default HTTPS port (443) */
     @Override
     protected int getDefaultPort() { return httpsPortNumber; }
@@ -427,13 +431,93 @@
             }
             s.addHandshakeCompletedListener(this);
 
-            // if the HostnameVerifier is not set, try to enable endpoint
-            // identification during handshaking
-            boolean enabledIdentification = false;
-            if (hv instanceof DefaultHostnameVerifier &&
-                (s instanceof SSLSocketImpl) &&
-                ((SSLSocketImpl)s).trySetHostnameVerification("HTTPS")) {
-                enabledIdentification = true;
+            // 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();
@@ -449,7 +533,7 @@
             }
 
             // check URL spoofing if it has not been checked under handshaking
-            if (!enabledIdentification) {
+            if (needToCheckSpoofing) {
                 checkURLSpoofing(hv);
             }
         } else {
@@ -463,8 +547,7 @@
     // Server identity checking is done according to RFC 2818: HTTP over TLS
     // Section 3.1 Server Identity
     private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
-            throws IOException
-    {
+            throws IOException {
         //
         // Get authenticated server name, if any
         //
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -711,10 +711,8 @@
                     cachedSenderInetAddress = isa.getAddress();
                     cachedSenderPort = isa.getPort();
 
-                    // Socket was not bound before connecting,
-                    if (localAddress == null) {
-                        localAddress = Net.localAddress(fd);
-                    }
+                    // set or refresh local address
+                    localAddress = Net.localAddress(fd);
                 }
             }
         }
@@ -735,6 +733,9 @@
                     disconnect0(fd);
                     remoteAddress = null;
                     state = ST_UNCONNECTED;
+
+                    // refresh local address
+                    localAddress = Net.localAddress(fd);
                 }
             }
         }
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -699,15 +699,19 @@
         static volatile long totalSize;
         static volatile long totalCapacity;
 
-        private long address;
-        private long size;
-        private int cap;
+        private volatile long address;
+        private final long size;
+        private final int cap;
+        private final FileDescriptor fd;
 
-        private Unmapper(long address, long size, int cap) {
+        private Unmapper(long address, long size, int cap,
+                         FileDescriptor fd)
+        {
             assert (address != 0);
             this.address = address;
             this.size = size;
             this.cap = cap;
+            this.fd = fd;
 
             synchronized (Unmapper.class) {
                 count++;
@@ -722,6 +726,15 @@
             unmap0(address, size);
             address = 0;
 
+            // if this mapping has a valid file descriptor then we close it
+            if (fd.valid()) {
+                try {
+                    nd.close(fd);
+                } catch (IOException ignore) {
+                    // nothing we can do
+                }
+            }
+
             synchronized (Unmapper.class) {
                 count--;
                 totalSize -= size;
@@ -784,10 +797,12 @@
             }
             if (size == 0) {
                 addr = 0;
+                // a valid file descriptor is not required
+                FileDescriptor dummy = new FileDescriptor();
                 if ((!writable) || (imode == MAP_RO))
-                    return Util.newMappedByteBufferR(0, 0, null);
+                    return Util.newMappedByteBufferR(0, 0, dummy, null);
                 else
-                    return Util.newMappedByteBuffer(0, 0, null);
+                    return Util.newMappedByteBuffer(0, 0, dummy, null);
             }
 
             int pagePosition = (int)(position % allocationGranularity);
@@ -813,14 +828,31 @@
                 }
             }
 
+            // On Windows, and potentially other platforms, we need an open
+            // file descriptor for some mapping operations.
+            FileDescriptor mfd;
+            try {
+                mfd = nd.duplicateForMapping(fd);
+            } catch (IOException ioe) {
+                unmap0(addr, mapSize);
+                throw ioe;
+            }
+
             assert (IOStatus.checkAll(addr));
             assert (addr % allocationGranularity == 0);
             int isize = (int)size;
-            Unmapper um = new Unmapper(addr, size + pagePosition, isize);
-            if ((!writable) || (imode == MAP_RO))
-                return Util.newMappedByteBufferR(isize, addr + pagePosition, um);
-            else
-                return Util.newMappedByteBuffer(isize, addr + pagePosition, um);
+            Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+            if ((!writable) || (imode == MAP_RO)) {
+                return Util.newMappedByteBufferR(isize,
+                                                 addr + pagePosition,
+                                                 mfd,
+                                                 um);
+            } else {
+                return Util.newMappedByteBuffer(isize,
+                                                addr + pagePosition,
+                                                mfd,
+                                                um);
+            }
         } finally {
             threads.remove(ti);
             end(IOStatus.checkAll(addr));
--- a/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -45,4 +45,12 @@
 
     abstract void release(FileDescriptor fd, long pos, long size)
         throws IOException;
+
+    /**
+     * Returns a dup of fd if a file descriptor is required for
+     * memory-mapping operations, otherwise returns an invalid
+     * FileDescriptor (meaning a newly allocated FileDescriptor)
+     */
+    abstract FileDescriptor duplicateForMapping(FileDescriptor fd)
+        throws IOException;
 }
--- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,667 +0,0 @@
-/*
- * Copyright (c) 2008, 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.nio.ch;
-
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.net.*;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.*;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-
-/**
- * A prototype implementation of AsynchronousDatagramChannel, used to aid
- * test and spec development.
- */
-
-class SimpleAsynchronousDatagramChannelImpl
-    extends AsynchronousDatagramChannel implements Groupable, Cancellable
-{
-    private final DatagramChannel dc;
-    private final AsynchronousChannelGroupImpl group;
-    private final Object attachKey;
-    private boolean closed;
-
-    // used to coordinate timed and blocking reads
-    private final Object readLock = new Object();
-
-    // channel blocking mode (requires readLock)
-    private boolean isBlocking = true;
-
-    // number of blocking readers (requires readLock)
-    private int blockingReaderCount;
-
-    // true if timed read attempted while blocking read in progress (requires readLock)
-    private boolean transitionToNonBlocking;
-
-    // true if a blocking read is cancelled (requires readLock)
-    private boolean blockingReadKilledByCancel;
-
-    // temporary Selectors used by timed reads (requires readLock)
-    private Selector firstReader;
-    private Set<Selector> otherReaders;
-
-    SimpleAsynchronousDatagramChannelImpl(ProtocolFamily family,
-                                          AsynchronousChannelGroupImpl group)
-        throws IOException
-    {
-        super(group.provider());
-        this.dc = (family == null) ?
-            DatagramChannel.open() : DatagramChannel.open(family);
-        this.group = group;
-
-        // attach this channel to the group as foreign channel
-        boolean registered = false;
-        try {
-            if (!(dc instanceof DatagramChannelImpl))
-                throw new UnsupportedOperationException();
-            attachKey = group
-                .attachForeignChannel(this, ((DatagramChannelImpl)dc).getFD());
-            registered = true;
-        } finally {
-            if (!registered)
-                dc.close();
-        }
-    }
-
-    // throws RuntimeException if blocking read has been cancelled
-    private void ensureBlockingReadNotKilled() {
-        assert Thread.holdsLock(readLock);
-        if (blockingReadKilledByCancel)
-            throw new RuntimeException("Reading not allowed due to cancellation");
-    }
-
-    // invoke prior to non-timed read/receive
-    private void beginNoTimeoutRead() {
-        synchronized (readLock) {
-            ensureBlockingReadNotKilled();
-            if (isBlocking)
-                blockingReaderCount++;
-        }
-    }
-
-    // invoke after non-timed read/receive has completed
-    private void endNoTimeoutRead() {
-        synchronized (readLock) {
-            if (isBlocking) {
-                if (--blockingReaderCount == 0 && transitionToNonBlocking) {
-                    // notify any threads waiting to make channel non-blocking
-                    readLock.notifyAll();
-                }
-            }
-        }
-    }
-
-    // invoke prior to timed read
-    // returns the timeout remaining
-    private long prepareForTimedRead(PendingFuture<?,?> result, long timeout)
-        throws IOException
-    {
-        synchronized (readLock) {
-            ensureBlockingReadNotKilled();
-            if (isBlocking) {
-                transitionToNonBlocking = true;
-                while (blockingReaderCount > 0 &&
-                       timeout > 0L &&
-                       !result.isCancelled())
-                {
-                    long st = System.currentTimeMillis();
-                    try {
-                        readLock.wait(timeout);
-                    } catch (InterruptedException e) { }
-                    timeout -= System.currentTimeMillis() - st;
-                }
-                if (blockingReaderCount == 0) {
-                    // re-check that blocked read wasn't cancelled
-                    ensureBlockingReadNotKilled();
-                    // no blocking reads so change channel to non-blocking
-                    dc.configureBlocking(false);
-                    isBlocking = false;
-                }
-            }
-            return timeout;
-        }
-    }
-
-    // returns a temporary Selector
-    private Selector getSelector() throws IOException {
-        Selector sel = Util.getTemporarySelector(dc);
-        synchronized (readLock) {
-            if (firstReader == null) {
-                firstReader = sel;
-            } else {
-                if (otherReaders == null)
-                    otherReaders = new HashSet<Selector>();
-                otherReaders.add(sel);
-            }
-        }
-        return sel;
-    }
-
-    // releases a temporary Selector
-    private void releaseSelector(Selector sel) throws IOException {
-        synchronized (readLock) {
-            if (firstReader == sel) {
-                firstReader = null;
-            } else {
-                otherReaders.remove(sel);
-            }
-        }
-        Util.releaseTemporarySelector(sel);
-    }
-
-    // wakeup all Selectors currently in use
-    private void wakeupSelectors() {
-        synchronized (readLock) {
-            if (firstReader != null)
-                firstReader.wakeup();
-            if (otherReaders != null) {
-                for (Selector sel: otherReaders) {
-                    sel.wakeup();
-                }
-            }
-        }
-    }
-
-    @Override
-    public AsynchronousChannelGroupImpl group() {
-        return group;
-    }
-
-    @Override
-    public boolean isOpen() {
-        return dc.isOpen();
-    }
-
-    @Override
-    public void onCancel(PendingFuture<?,?> task) {
-        synchronized (readLock) {
-            if (blockingReaderCount > 0) {
-                blockingReadKilledByCancel = true;
-                readLock.notifyAll();
-                return;
-            }
-        }
-        wakeupSelectors();
-    }
-
-    @Override
-    public void close() throws IOException {
-        synchronized (dc) {
-            if (closed)
-                return;
-            closed = true;
-        }
-        // detach from group and close underlying channel
-        group.detachForeignChannel(attachKey);
-        dc.close();
-
-        // wakeup any threads blocked in timed read/receives
-        wakeupSelectors();
-    }
-
-    @Override
-    public AsynchronousDatagramChannel connect(SocketAddress remote)
-        throws IOException
-    {
-        dc.connect(remote);
-        return this;
-    }
-
-    @Override
-    public AsynchronousDatagramChannel disconnect() throws IOException {
-        dc.disconnect();
-        return this;
-    }
-
-    private static class WrappedMembershipKey extends MembershipKey {
-        private final MulticastChannel channel;
-        private final MembershipKey key;
-
-        WrappedMembershipKey(MulticastChannel channel, MembershipKey key) {
-            this.channel = channel;
-            this.key = key;
-        }
-
-        @Override
-        public boolean isValid() {
-            return key.isValid();
-        }
-
-        @Override
-        public void drop() {
-            key.drop();
-        }
-
-        @Override
-        public MulticastChannel channel() {
-            return channel;
-        }
-
-        @Override
-        public InetAddress group() {
-            return key.group();
-        }
-
-        @Override
-        public NetworkInterface networkInterface() {
-            return key.networkInterface();
-        }
-
-        @Override
-        public InetAddress sourceAddress() {
-            return key.sourceAddress();
-        }
-
-        @Override
-        public MembershipKey block(InetAddress toBlock) throws IOException {
-            key.block(toBlock);
-            return this;
-        }
-
-        @Override
-        public MembershipKey unblock(InetAddress toUnblock) {
-            key.unblock(toUnblock);
-            return this;
-        }
-
-        @Override
-        public String toString() {
-            return key.toString();
-        }
-    }
-
-    @Override
-    public MembershipKey join(InetAddress group,
-                              NetworkInterface interf)
-        throws IOException
-    {
-        MembershipKey key = ((MulticastChannel)dc).join(group, interf);
-        return new WrappedMembershipKey(this, key);
-    }
-
-    @Override
-    public MembershipKey join(InetAddress group,
-                              NetworkInterface interf,
-                              InetAddress source)
-        throws IOException
-    {
-        MembershipKey key = ((MulticastChannel)dc).join(group, interf, source);
-        return new WrappedMembershipKey(this, key);
-    }
-
-    private <A> Future<Integer> implSend(ByteBuffer src,
-                                         SocketAddress target,
-                                         A attachment,
-                                         CompletionHandler<Integer,? super A> handler)
-    {
-        int n = 0;
-        Throwable exc = null;
-        try {
-            n = dc.send(src, target);
-        } catch (IOException ioe) {
-            exc = ioe;
-        }
-        if (handler == null)
-            return CompletedFuture.withResult(n, exc);
-        Invoker.invoke(this, handler, attachment, n, exc);
-        return null;
-    }
-
-    @Override
-    public Future<Integer> send(ByteBuffer src, SocketAddress target) {
-        return implSend(src, target, null, null);
-    }
-
-    @Override
-    public <A> void send(ByteBuffer src,
-                         SocketAddress target,
-                         A attachment,
-                         CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implSend(src, target, attachment, handler);
-    }
-
-    private <A> Future<Integer> implWrite(ByteBuffer src,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
-    {
-        int n = 0;
-        Throwable exc = null;
-        try {
-            n = dc.write(src);
-        } catch (IOException ioe) {
-            exc = ioe;
-        }
-        if (handler == null)
-            return CompletedFuture.withResult(n, exc);
-        Invoker.invoke(this, handler, attachment, n, exc);
-        return null;
-
-    }
-
-    @Override
-    public Future<Integer> write(ByteBuffer src) {
-        return implWrite(src, null, null);
-    }
-
-    @Override
-    public <A> void write(ByteBuffer src,
-                          A attachment,
-                          CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implWrite(src, attachment, handler);
-    }
-
-    /**
-     * Receive into the given buffer with privileges enabled and restricted by
-     * the given AccessControlContext (can be null).
-     */
-    private SocketAddress doRestrictedReceive(final ByteBuffer dst,
-                                              AccessControlContext acc)
-        throws IOException
-    {
-        if (acc == null) {
-            return dc.receive(dst);
-        } else {
-            try {
-                return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<SocketAddress>() {
-                        public SocketAddress run() throws IOException {
-                            return dc.receive(dst);
-                        }}, acc);
-            } catch (PrivilegedActionException pae) {
-                Exception cause = pae.getException();
-                if (cause instanceof SecurityException)
-                    throw (SecurityException)cause;
-                throw (IOException)cause;
-            }
-        }
-    }
-
-    private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
-                                                  final long timeout,
-                                                  final TimeUnit unit,
-                                                  A attachment,
-                                                  final CompletionHandler<SocketAddress,? super A> handler)
-    {
-        if (dst.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
-
-        // complete immediately if channel closed
-        if (!isOpen()) {
-            Throwable exc = new ClosedChannelException();
-            if (handler == null)
-                return CompletedFuture.withFailure(exc);
-            Invoker.invoke(this, handler, attachment, null, exc);
-            return null;
-        }
-
-        final AccessControlContext acc = (System.getSecurityManager() == null) ?
-            null : AccessController.getContext();
-        final PendingFuture<SocketAddress,A> result =
-            new PendingFuture<SocketAddress,A>(this, handler, attachment);
-        Runnable task = new Runnable() {
-            public void run() {
-                try {
-                    SocketAddress remote = null;
-                    long to;
-                    if (timeout == 0L) {
-                        beginNoTimeoutRead();
-                        try {
-                            remote = doRestrictedReceive(dst, acc);
-                        } finally {
-                            endNoTimeoutRead();
-                        }
-                        to = 0L;
-                    } else {
-                        to = prepareForTimedRead(result, unit.toMillis(timeout));
-                        if (to <= 0L)
-                            throw new InterruptedByTimeoutException();
-                        remote = doRestrictedReceive(dst, acc);
-                    }
-                    if (remote == null) {
-                        Selector sel = getSelector();
-                        SelectionKey sk = null;
-                        try {
-                            sk = dc.register(sel, SelectionKey.OP_READ);
-                            for (;;) {
-                                if (!dc.isOpen())
-                                    throw new AsynchronousCloseException();
-                                if (result.isCancelled())
-                                    break;
-                                long st = System.currentTimeMillis();
-                                int ns = sel.select(to);
-                                if (ns > 0) {
-                                    remote = doRestrictedReceive(dst, acc);
-                                    if (remote != null)
-                                        break;
-                                }
-                                sel.selectedKeys().remove(sk);
-                                if (timeout != 0L) {
-                                    to -= System.currentTimeMillis() - st;
-                                    if (to <= 0)
-                                        throw new InterruptedByTimeoutException();
-                                }
-                            }
-                        } finally {
-                            if (sk != null)
-                                sk.cancel();
-                            releaseSelector(sel);
-                        }
-                    }
-                    result.setResult(remote);
-                } catch (Throwable x) {
-                    if (x instanceof ClosedChannelException)
-                        x = new AsynchronousCloseException();
-                    result.setFailure(x);
-                }
-                Invoker.invokeUnchecked(result);
-            }
-        };
-        try {
-            group.executeOnPooledThread(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
-        return result;
-    }
-
-    @Override
-    public Future<SocketAddress> receive(ByteBuffer dst) {
-        return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
-
-    @Override
-    public <A> void receive(ByteBuffer dst,
-                            long timeout,
-                            TimeUnit unit,
-                            A attachment,
-                            CompletionHandler<SocketAddress,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implReceive(dst, timeout, unit, attachment, handler);
-    }
-
-    private <A> Future<Integer> implRead(final ByteBuffer dst,
-                                         final long timeout,
-                                         final TimeUnit unit,
-                                         A attachment,
-                                         final CompletionHandler<Integer,? super A> handler)
-    {
-        if (dst.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
-
-        // complete immediately if channel closed
-        if (!isOpen()) {
-            Throwable exc = new ClosedChannelException();
-            if (handler == null)
-                return CompletedFuture.withFailure(exc);
-            Invoker.invoke(this, handler, attachment, null, exc);
-            return null;
-        }
-
-        // another thread may disconnect before read is initiated
-        if (!dc.isConnected())
-            throw new NotYetConnectedException();
-
-        final PendingFuture<Integer,A> result =
-            new PendingFuture<Integer,A>(this, handler, attachment);
-        Runnable task = new Runnable() {
-            public void run() {
-                try {
-                    int n = 0;
-                    long to;
-                    if (timeout == 0L) {
-                        beginNoTimeoutRead();
-                        try {
-                            n = dc.read(dst);
-                        } finally {
-                            endNoTimeoutRead();
-                        }
-                        to = 0L;
-                    } else {
-                        to = prepareForTimedRead(result, unit.toMillis(timeout));
-                        if (to <= 0L)
-                            throw new InterruptedByTimeoutException();
-                        n = dc.read(dst);
-                    }
-                    if (n == 0) {
-                        Selector sel = getSelector();
-                        SelectionKey sk = null;
-                        try {
-                            sk = dc.register(sel, SelectionKey.OP_READ);
-                            for (;;) {
-                                if (!dc.isOpen())
-                                    throw new AsynchronousCloseException();
-                                if (result.isCancelled())
-                                    break;
-                                long st = System.currentTimeMillis();
-                                int ns = sel.select(to);
-                                if (ns > 0) {
-                                    if ((n = dc.read(dst)) != 0)
-                                        break;
-                                }
-                                sel.selectedKeys().remove(sk);
-                                if (timeout != 0L) {
-                                    to -= System.currentTimeMillis() - st;
-                                    if (to <= 0)
-                                        throw new InterruptedByTimeoutException();
-                                }
-                            }
-                        } finally {
-                            if (sk != null)
-                                sk.cancel();
-                            releaseSelector(sel);
-                        }
-                    }
-                    result.setResult(n);
-                } catch (Throwable x) {
-                    if (x instanceof ClosedChannelException)
-                        x = new AsynchronousCloseException();
-                    result.setFailure(x);
-                }
-                Invoker.invokeUnchecked(result);
-            }
-        };
-        try {
-            group.executeOnPooledThread(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
-        return result;
-    }
-
-    @Override
-    public Future<Integer> read(ByteBuffer dst) {
-        return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
-
-    @Override
-    public <A> void read(ByteBuffer dst,
-                            long timeout,
-                            TimeUnit unit,
-                            A attachment,
-                            CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implRead(dst, timeout, unit, attachment, handler);
-    }
-
-    @Override
-    public  AsynchronousDatagramChannel bind(SocketAddress local)
-        throws IOException
-    {
-        dc.bind(local);
-        return this;
-    }
-
-    @Override
-    public SocketAddress getLocalAddress() throws IOException {
-        return dc.getLocalAddress();
-    }
-
-    @Override
-    public <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
-        throws IOException
-    {
-        dc.setOption(name, value);
-        return this;
-    }
-
-    @Override
-    public  <T> T getOption(SocketOption<T> name) throws IOException {
-        return dc.getOption(name);
-    }
-
-    @Override
-    public Set<SocketOption<?>> supportedOptions() {
-        return dc.supportedOptions();
-    }
-
-    @Override
-    public SocketAddress getRemoteAddress() throws IOException {
-        return dc.getRemoteAddress();
-    }
-}
--- a/jdk/src/share/classes/sun/nio/ch/Util.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java	Tue Nov 09 22:53:18 2010 -0800
@@ -28,6 +28,7 @@
 import java.lang.ref.SoftReference;
 import java.lang.reflect.*;
 import java.io.IOException;
+import java.io.FileDescriptor;
 import java.nio.ByteBuffer;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.*;
@@ -364,6 +365,7 @@
                         Constructor ctor = cl.getDeclaredConstructor(
                             new Class[] { int.class,
                                           long.class,
+                                          FileDescriptor.class,
                                           Runnable.class });
                         ctor.setAccessible(true);
                         directByteBufferConstructor = ctor;
@@ -381,6 +383,7 @@
     }
 
     static MappedByteBuffer newMappedByteBuffer(int size, long addr,
+                                                FileDescriptor fd,
                                                 Runnable unmapper)
     {
         MappedByteBuffer dbb;
@@ -390,6 +393,7 @@
             dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance(
               new Object[] { new Integer(size),
                              new Long(addr),
+                             fd,
                              unmapper });
         } catch (InstantiationException e) {
             throw new InternalError();
@@ -411,6 +415,7 @@
                         Constructor ctor = cl.getDeclaredConstructor(
                             new Class[] { int.class,
                                           long.class,
+                                          FileDescriptor.class,
                                           Runnable.class });
                         ctor.setAccessible(true);
                         directByteBufferRConstructor = ctor;
@@ -428,6 +433,7 @@
     }
 
     static MappedByteBuffer newMappedByteBufferR(int size, long addr,
+                                                 FileDescriptor fd,
                                                  Runnable unmapper)
     {
         MappedByteBuffer dbb;
@@ -437,6 +443,7 @@
             dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance(
               new Object[] { new Integer(size),
                              new Long(addr),
+                             fd,
                              unmapper });
         } catch (InstantiationException e) {
             throw new InternalError();
--- a/jdk/src/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -38,7 +38,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public interface TlsMasterSecret extends SecretKey {
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -39,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
@@ -50,6 +51,9 @@
     private final String cipherAlgorithm;
     private final int cipherKeyLength, ivLength, macKeyLength;
     private final int expandedCipherKeyLength; // == 0 for domestic ciphersuites
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsKeyMaterialParameterSpec.
@@ -71,6 +75,12 @@
      * @param ivLength the length in bytes of the initialization vector
      *    to be generated, or 0 if no initialization vector is required
      * @param macKeyLength the length in bytes of the MAC key to be generated
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if masterSecret, clientRandom,
      *   serverRandom, or cipherAlgorithm are null
@@ -82,7 +92,8 @@
     public TlsKeyMaterialParameterSpec(SecretKey masterSecret,
             int majorVersion, int minorVersion, byte[] clientRandom,
             byte[] serverRandom, String cipherAlgorithm, int cipherKeyLength,
-            int expandedCipherKeyLength, int ivLength, int macKeyLength) {
+            int expandedCipherKeyLength, int ivLength, int macKeyLength,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if (masterSecret.getAlgorithm().equals("TlsMasterSecret") == false) {
             throw new IllegalArgumentException("Not a TLS master secret");
         }
@@ -90,8 +101,10 @@
             throw new NullPointerException();
         }
         this.masterSecret = masterSecret;
-        this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
-        this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
+        this.majorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(majorVersion);
+        this.minorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(minorVersion);
         this.clientRandom = clientRandom.clone();
         this.serverRandom = serverRandom.clone();
         this.cipherAlgorithm = cipherAlgorithm;
@@ -99,6 +112,9 @@
         this.expandedCipherKeyLength = checkSign(expandedCipherKeyLength);
         this.ivLength = checkSign(ivLength);
         this.macKeyLength = checkSign(macKeyLength);
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     private static int checkSign(int k) {
@@ -172,20 +188,36 @@
     }
 
     /**
-     * Returns the length in bytes of the expanded encryption key to be generated.
+     * Returns the length in bytes of the expanded encryption key to be
+     * generated. Returns zero if the expanded encryption key is not
+     * supposed to be generated.
      *
-     * @return the length in bytes of the expanded encryption key to be generated.
+     * @return the length in bytes of the expanded encryption key to be
+     *     generated.
      */
     public int getExpandedCipherKeyLength() {
+        // TLS v1.1 disables the exportable weak cipher suites.
+        if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+            return 0;
+        }
         return expandedCipherKeyLength;
     }
 
     /**
-     * Returns the length in bytes of the initialization vector to be generated.
+     * Returns the length in bytes of the initialization vector to be
+     * generated. Returns zero if the initialization vector is not
+     * supposed to be generated.
      *
-     * @return the length in bytes of the initialization vector to be generated.
+     * @return the length in bytes of the initialization vector to be
+     *     generated.
      */
     public int getIvLength() {
+        // TLS v1.1 or later uses an explicit IV to protect against
+        // the CBC attacks.
+        if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+            return 0;
+        }
+
         return ivLength;
     }
 
@@ -198,4 +230,30 @@
         return macKeyLength;
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of the PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the block size of the PRF hash algorithm.
+     *
+     * @return the hash algorithm block size
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -39,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
@@ -80,7 +81,8 @@
      */
     public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
             SecretKey clientCipherKey, SecretKey serverCipherKey) {
-        this(clientMacKey, serverMacKey, clientCipherKey, null, serverCipherKey, null);
+        this(clientMacKey, serverMacKey, clientCipherKey, null,
+            serverCipherKey, null);
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -39,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
@@ -47,6 +48,9 @@
     private final SecretKey premasterSecret;
     private final int majorVersion, minorVersion;
     private final byte[] clientRandom, serverRandom;
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsMasterSecretParameterSpec.
@@ -60,6 +64,12 @@
      * @param minorVersion the minor number of the protocol version
      * @param clientRandom the client's random value
      * @param serverRandom the server's random value
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if premasterSecret, clientRandom,
      *   or serverRandom are null
@@ -67,7 +77,9 @@
      *   negative or larger than 255
      */
     public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
-            int majorVersion, int minorVersion, byte[] clientRandom, byte[] serverRandom) {
+            int majorVersion, int minorVersion,
+            byte[] clientRandom, byte[] serverRandom,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if (premasterSecret == null) {
             throw new NullPointerException("premasterSecret must not be null");
         }
@@ -76,11 +88,15 @@
         this.minorVersion = checkVersion(minorVersion);
         this.clientRandom = clientRandom.clone();
         this.serverRandom = serverRandom.clone();
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     static int checkVersion(int version) {
         if ((version < 0) || (version > 255)) {
-            throw new IllegalArgumentException("Version must be between 0 and 255");
+            throw new IllegalArgumentException(
+                        "Version must be between 0 and 255");
         }
         return version;
     }
@@ -130,4 +146,30 @@
         return serverRandom.clone();
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of the PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the block size of the PRF hash algorithm.
+     *
+     * @return the hash algorithm block size.
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsPrfParameterSpec.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsPrfParameterSpec.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -38,7 +38,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
@@ -47,6 +48,9 @@
     private final String label;
     private final byte[] seed;
     private final int outputLength;
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsPrfParameterSpec.
@@ -55,11 +59,19 @@
      * @param label the label to use in the calculation
      * @param seed the random seed to use in the calculation
      * @param outputLength the length in bytes of the output key to be produced
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if label or seed is null
      * @throws IllegalArgumentException if outputLength is negative
      */
-    public TlsPrfParameterSpec(SecretKey secret, String label, byte[] seed, int outputLength) {
+    public TlsPrfParameterSpec(SecretKey secret, String label,
+            byte[] seed, int outputLength,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if ((label == null) || (seed == null)) {
             throw new NullPointerException("label and seed must not be null");
         }
@@ -70,6 +82,9 @@
         this.label = label;
         this.seed = seed.clone();
         this.outputLength = outputLength;
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     /**
@@ -110,4 +125,33 @@
         return outputLength;
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm, or null if no algorithm was specified.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of PRF hash algorithm.
+     *
+     * It would have been preferred to use MessageDigest.getDigestLength(),
+     * but the API does not require implementations to support the method.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the length of PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -36,10 +36,12 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
-public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpec {
+public class TlsRsaPremasterSecretParameterSpec
+        implements AlgorithmParameterSpec {
 
     private final int majorVersion;
     private final int minorVersion;
@@ -58,10 +60,12 @@
      * @throws IllegalArgumentException if minorVersion or majorVersion are
      *   negative or larger than 255
      */
-    public TlsRsaPremasterSecretParameterSpec(int majorVersion, int minorVersion) {
-        this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
-        this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
-    }
+    public TlsRsaPremasterSecretParameterSpec(int majorVersion,
+            int minorVersion) {
+        this.majorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(majorVersion);
+        this.minorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(minorVersion); }
 
     /**
      * Returns the major version.
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Tue Nov 09 22:53:18 2010 -0800
@@ -34,7 +34,6 @@
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
-import java.util.Vector;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.io.IOException;
@@ -42,7 +41,10 @@
 import java.io.FileOutputStream;
 import java.io.File;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.Vector;
 
 /**
  * This class represents key table. The key table functions deal with storing
@@ -239,23 +241,22 @@
         EncryptionKey key;
         int size = entries.size();
         ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey> (size);
-        if (entries != null) {
-            for (int i = size-1; i >= 0; i--) {
-                entry = entries.elementAt(i);
-                if (entry.service.match(service)) {
-                    if (EType.isSupported(entry.keyType)) {
-                        key = new EncryptionKey(entry.keyblock,
-                                            entry.keyType,
-                                            new Integer(entry.keyVersion));
-                        keys.add(key);
-                        if (DEBUG) {
-                            System.out.println("Added key: " + entry.keyType +
-                                "version: " + entry.keyVersion);
-                        }
-                    } else if (DEBUG) {
-                        System.out.println("Found unsupported keytype (" +
-                            entry.keyType + ") for " + service);
+
+        for (int i = size-1; i >= 0; i--) {
+            entry = entries.elementAt(i);
+            if (entry.service.match(service)) {
+                if (EType.isSupported(entry.keyType)) {
+                    key = new EncryptionKey(entry.keyblock,
+                                        entry.keyType,
+                                        new Integer(entry.keyVersion));
+                    keys.add(key);
+                    if (DEBUG) {
+                        System.out.println("Added key: " + entry.keyType +
+                            "version: " + entry.keyVersion);
                     }
+                } else if (DEBUG) {
+                    System.out.println("Found unsupported keytype (" +
+                        entry.keyType + ") for " + service);
                 }
             }
         }
@@ -313,16 +314,14 @@
      */
     public boolean findServiceEntry(PrincipalName service) {
         KeyTabEntry entry;
-        if (entries != null) {
-            for (int i = 0; i < entries.size(); i++) {
-                entry = entries.elementAt(i);
-                if (entry.service.match(service)) {
-                    if (EType.isSupported(entry.keyType)) {
-                        return true;
-                    } else if (DEBUG) {
-                        System.out.println("Found unsupported keytype (" +
-                            entry.keyType + ") for " + service);
-                    }
+        for (int i = 0; i < entries.size(); i++) {
+            entry = entries.elementAt(i);
+            if (entry.service.match(service)) {
+                if (EType.isSupported(entry.keyType)) {
+                    return true;
+                } else if (DEBUG) {
+                    System.out.println("Found unsupported keytype (" +
+                        entry.keyType + ") for " + service);
                 }
             }
         }
@@ -337,94 +336,57 @@
      * Adds a new entry in the key table.
      * @param service the service which will have a new entry in the key table.
      * @param psswd the password which generates the key.
+     * @param kvno the kvno to use, -1 means automatic increasing
+     * @param append false if entries with old kvno would be removed.
+     * Note: if kvno is not -1, entries with the same kvno are always removed
      */
-    public void addEntry(PrincipalName service, char[] psswd)
-         throws KrbException {
+    public void addEntry(PrincipalName service, char[] psswd,
+            int kvno, boolean append) throws KrbException {
 
         EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
             psswd, service.getSalt());
 
+        // There should be only one maximum KVNO value for all etypes, so that
+        // all added keys can have the same KVNO.
+
+        int maxKvno = 0;    // only useful when kvno == -1
+        for (int i = entries.size()-1; i >= 0; i--) {
+            KeyTabEntry e = entries.get(i);
+            if (e.service.match(service)) {
+                if (e.keyVersion > maxKvno) {
+                    maxKvno = e.keyVersion;
+                }
+                if (!append || e.keyVersion == kvno) {
+                    entries.removeElementAt(i);
+                }
+            }
+        }
+        if (kvno == -1) {
+            kvno = maxKvno + 1;
+        }
+
         for (int i = 0; encKeys != null && i < encKeys.length; i++) {
             int keyType = encKeys[i].getEType();
             byte[] keyValue = encKeys[i].getBytes();
-            int result = retrieveEntry(service, keyType);
-            int kvno = 1;
-            if (result != -1) {
-                KeyTabEntry oldEntry = entries.elementAt(result);
-                kvno = oldEntry.keyVersion;
-                entries.removeElementAt(result);
-                kvno += 1;
-            } else
-                kvno = 1;
 
             KeyTabEntry newEntry = new KeyTabEntry(service,
                             service.getRealm(),
                             new KerberosTime(System.currentTimeMillis()),
                                                kvno, keyType, keyValue);
-            if (entries == null)
-                entries = new Vector<KeyTabEntry> ();
             entries.addElement(newEntry);
         }
     }
 
     /**
-     * Only used by KDC test. This method can specify kvno and does not
-     * remove any old keys.
-     */
-    public void addEntry(PrincipalName service, char[] psswd, int kvno)
-         throws KrbException {
-
-        EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
-            psswd, service.getSalt());
-
-        for (int i = 0; encKeys != null && i < encKeys.length; i++) {
-            int keyType = encKeys[i].getEType();
-            byte[] keyValue = encKeys[i].getBytes();
-            KeyTabEntry newEntry = new KeyTabEntry(service,
-                            service.getRealm(),
-                            new KerberosTime(System.currentTimeMillis()),
-                                               kvno, keyType, keyValue);
-            if (entries == null)
-                entries = new Vector<KeyTabEntry> ();
-            entries.addElement(newEntry);
-        }
-    }
-
-    /**
-     * Retrieves the key table entry with the specified service name.
-     * @param service the service which may have an entry in the key table.
-     * @param keyType the etype to match, returns the 1st one if -1 provided
-     * @return -1 if the entry is not found, else return the entry index
-     * in the list.
-     */
-    private int retrieveEntry(PrincipalName service, int keyType) {
-        KeyTabEntry e;
-        if (entries != null) {
-            for (int i = 0; i < entries.size(); i++) {
-                e = entries.elementAt(i);
-                if (service.match(e.getService()) &&
-                    (keyType == -1 || e.keyType == keyType)) {
-                    return i;
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
      * Gets the list of service entries in key table.
      * @return array of <code>KeyTabEntry</code>.
      */
     public KeyTabEntry[] getEntries() {
-        if (entries != null) {
-            KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
-            for (int i = 0; i < kentries.length; i++) {
-                kentries[i] = entries.elementAt(i);
-            }
-            return kentries;
-        } else {
-            return null;
+        KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
+        for (int i = 0; i < kentries.length; i++) {
+            kentries[i] = entries.elementAt(i);
         }
+        return kentries;
     }
 
     /**
@@ -464,29 +426,55 @@
     }
 
     /**
-     * Removes an entry from the key table.
+     * Removes entries from the key table.
      * @param service the service <code>PrincipalName</code>.
-     * @param etype the etype to match, first one if -1 provided
-     * @return 1 if removed successfully, 0 otherwise
+     * @param etype the etype to match, remove all if -1
+     * @param kvno what kvno to remove, -1 for all, -2 for old
+     * @return the number of entries deleted
      */
-    public int deleteEntry(PrincipalName service, int etype) {
-        int result = retrieveEntry(service, etype);
-        if (result != -1) {
-            entries.removeElementAt(result);
-            return 1;
+    public int deleteEntries(PrincipalName service, int etype, int kvno) {
+        int count = 0;
+
+        // Remember the highest KVNO for each etype. Used for kvno == -2
+        Map<Integer,Integer> highest = new HashMap<>();
+
+        for (int i = entries.size()-1; i >= 0; i--) {
+            KeyTabEntry e = entries.get(i);
+            if (service.match(e.getService())) {
+                if (etype == -1 || e.keyType == etype) {
+                    if (kvno == -2) {
+                        // Two rounds for kvno == -2. In the first round (here),
+                        // only find out highest KVNO for each etype
+                        if (highest.containsKey(e.keyType)) {
+                            int n = highest.get(e.keyType);
+                            if (e.keyVersion > n) {
+                                highest.put(e.keyType, e.keyVersion);
+                            }
+                        } else {
+                            highest.put(e.keyType, e.keyVersion);
+                        }
+                    } else if (kvno == -1 || e.keyVersion == kvno) {
+                        entries.removeElementAt(i);
+                        count++;
+                    }
+                }
+            }
         }
-        return 0;
-    }
 
-    /**
-     * Removes an entry from the key table.
-     * @param service the service <code>PrincipalName</code>.
-     * @return number of entries removed
-     */
-    public int deleteEntry(PrincipalName service) {
-        int count = 0;
-        while (deleteEntry(service, -1) > 0) {
-            count++;
+        // Second round for kvno == -2, remove old entries
+        if (kvno == -2) {
+            for (int i = entries.size()-1; i >= 0; i--) {
+                KeyTabEntry e = entries.get(i);
+                if (service.match(e.getService())) {
+                    if (etype == -1 || e.keyType == etype) {
+                        int n = highest.get(e.keyType);
+                        if (e.keyVersion != n) {
+                            entries.removeElementAt(i);
+                            count++;
+                        }
+                    }
+                }
+            }
         }
         return count;
     }
--- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -655,6 +655,25 @@
         d(SIG, "SHA512withRSA", P11Signature,
                 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
 
+        /*
+         * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
+         * PRF calculations.  As of 2010, there is no PKCS11-level
+         * support for TLS 1.2 PRF calculations, and no known OS's have
+         * an internal variant we could use.  Therefore for TLS 1.2, we
+         * are updating JSSE to request different provider algorithms
+         * (e.g. "SunTls12Prf"), and currently only SunJCE has these
+         * TLS 1.2 algorithms.
+         *
+         * If we reused the names such as "SunTlsPrf", the PKCS11
+         * providers would need be updated to fail correctly when
+         * presented with the wrong version number (via
+         * Provider.Service.supportsParameters()), and we would also
+         * need to add the appropriate supportsParamters() checks into
+         * KeyGenerators (not currently there).
+         *
+         * In the future, if PKCS11 support is added, we will restructure
+         * this.
+         */
         d(KG, "SunTlsRsaPremasterSecret",
                     "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
                 m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
@@ -887,7 +906,8 @@
             return (aliases == null) ? null : Arrays.asList(aliases);
         }
 
-        public Object newInstance(Object param) throws NoSuchAlgorithmException {
+        public Object newInstance(Object param)
+                throws NoSuchAlgorithmException {
             if (token.isValid() == false) {
                 throw new NoSuchAlgorithmException("Token has been removed");
             }
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,95 +25,336 @@
 
 package sun.security.provider.certpath;
 
-import java.util.Set;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
 import java.util.Collection;
-import java.util.Locale;
+import java.util.Collections;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.KeyFactory;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
+import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
-import java.security.cert.X509CRL;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
-import java.security.cert.PKIXCertPathChecker;
+import java.io.IOException;
+import java.security.interfaces.*;
+import java.security.spec.*;
 
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CRLImpl;
 import sun.security.x509.AlgorithmId;
 
 /**
- * AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
- * the signature algorithm of the specified certificate is not disabled.
+ * A <code>PKIXCertPathChecker</code> implementation to check whether a
+ * specified certificate contains the required algorithm constraints.
+ * <p>
+ * Certificate fields such as the subject public key, the signature
+ * algorithm, key usage, extended key usage, etc. need to conform to
+ * the specified algorithm constraints.
  *
- * @author      Xuelei Fan
+ * @see PKIXCertPathChecker
+ * @see PKIXParameters
  */
 final public class AlgorithmChecker extends PKIXCertPathChecker {
 
-    // the disabled algorithms
-    private static final String[] disabledAlgorithms = new String[] {"md2"};
+    private final AlgorithmConstraints constraints;
+    private final PublicKey trustedPubKey;
+    private PublicKey prevPubKey;
 
-    // singleton instance
-    static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
+    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
+                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+
+    private final static DisabledAlgorithmConstraints
+        certPathDefaultConstraints = new DisabledAlgorithmConstraints(
+            DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 
     /**
-     * Default Constructor
+     * Create a new <code>AlgorithmChecker</code> with the algorithm
+     * constraints specified in security property
+     * "jdk.certpath.disabledAlgorithms".
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
      */
-    private AlgorithmChecker() {
-        // do nothing
+    public AlgorithmChecker(TrustAnchor anchor) {
+        this(anchor, certPathDefaultConstraints);
+    }
+
+    /**
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given {@code AlgorithmConstraints}.
+     * <p>
+     * Note that this constructor will be used to check a certification
+     * path where the trust anchor is unknown, or a certificate list which may
+     * contain the trust anchor. This constructor is used by SunJSSE.
+     *
+     * @param constraints the algorithm constraints (or null)
+     */
+    public AlgorithmChecker(AlgorithmConstraints constraints) {
+        this.prevPubKey = null;
+        this.trustedPubKey = null;
+        this.constraints = constraints;
     }
 
     /**
-     * Return a AlgorithmChecker instance.
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @throws IllegalArgumentException if the <code>anchor</code> is null
      */
-    static AlgorithmChecker getInstance() {
-        return INSTANCE;
+    public AlgorithmChecker(TrustAnchor anchor,
+            AlgorithmConstraints constraints) {
+
+        if (anchor == null) {
+            throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+        }
+
+        if (anchor.getTrustedCert() != null) {
+            this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+        } else {
+            this.trustedPubKey = anchor.getCAPublicKey();
+        }
+
+        this.prevPubKey = trustedPubKey;
+        this.constraints = constraints;
     }
 
-    /**
-     * Initializes the internal state of the checker from parameters
-     * specified in the constructor.
-     */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
-        // do nothing
+        //  Note that this class does not support forward mode.
+        if (!forward) {
+            if (trustedPubKey != null) {
+                prevPubKey = trustedPubKey;
+            } else {
+                prevPubKey = null;
+            }
+        } else {
+            throw new
+                CertPathValidatorException("forward checking not supported");
+        }
     }
 
+    @Override
     public boolean isForwardCheckingSupported() {
+        //  Note that as this class does not support forward mode, the method
+        //  will always returns false.
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         return null;
     }
 
-    /**
-     * Checks the signature algorithm of the specified certificate.
-     */
-    public void check(Certificate cert, Collection<String> unresolvedCritExts)
+    @Override
+    public void check(Certificate cert,
+            Collection<String> unresolvedCritExts)
             throws CertPathValidatorException {
-        check(cert);
-    }
+
+        if (!(cert instanceof X509Certificate) || constraints == null) {
+            // ignore the check for non-x.509 certificate or null constraints
+            return;
+        }
+
+        X509CertImpl x509Cert = null;
+        try {
+            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        PublicKey currPubKey = x509Cert.getPublicKey();
+        String currSigAlg = x509Cert.getSigAlgName();
+
+        AlgorithmId algorithmId = null;
+        try {
+            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+
+        // Check the current signature algorithm
+        if (!constraints.permits(
+                SIGNATURE_PRIMITIVE_SET,
+                currSigAlg, currSigAlgParams)) {
+            throw new CertPathValidatorException(
+                "Algorithm constraints check failed: " + currSigAlg);
+        }
+
+        // check the key usage and key size
+        boolean[] keyUsage = x509Cert.getKeyUsage();
+        if (keyUsage != null && keyUsage.length < 9) {
+            throw new CertPathValidatorException(
+                        "incorrect KeyUsage extension");
+        }
+
+        if (keyUsage != null) {
+            Set<CryptoPrimitive> primitives =
+                        EnumSet.noneOf(CryptoPrimitive.class);
+
+            if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
+                // keyUsage[0]: KeyUsage.digitalSignature
+                // keyUsage[1]: KeyUsage.nonRepudiation
+                // keyUsage[5]: KeyUsage.keyCertSign
+                // keyUsage[6]: KeyUsage.cRLSign
+                primitives.add(CryptoPrimitive.SIGNATURE);
+            }
+
+            if (keyUsage[2]) {      // KeyUsage.keyEncipherment
+                primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
+            }
+
+            if (keyUsage[3]) {      // KeyUsage.dataEncipherment
+                primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
+            }
 
-    public static void check(Certificate cert)
-            throws CertPathValidatorException {
-        X509Certificate xcert = (X509Certificate)cert;
-        check(xcert.getSigAlgName());
+            if (keyUsage[4]) {      // KeyUsage.keyAgreement
+                primitives.add(CryptoPrimitive.KEY_AGREEMENT);
+            }
+
+            // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
+            // undefined in the absence of the keyAgreement bit.
+
+            if (!primitives.isEmpty()) {
+                if (!constraints.permits(primitives, currPubKey)) {
+                    throw new CertPathValidatorException(
+                        "algorithm constraints check failed");
+                }
+            }
+        }
+
+        // Check with previous cert for signature algorithm and public key
+        if (prevPubKey != null) {
+            if (currSigAlg != null) {
+                if (!constraints.permits(
+                        SIGNATURE_PRIMITIVE_SET,
+                        currSigAlg, prevPubKey, currSigAlgParams)) {
+                    throw new CertPathValidatorException(
+                        "Algorithm constraints check failed: " + currSigAlg);
+                }
+            }
+
+            // Inherit key parameters from previous key
+            if (currPubKey instanceof DSAPublicKey &&
+                ((DSAPublicKey)currPubKey).getParams() == null) {
+                // Inherit DSA parameters from previous key
+                if (!(prevPubKey instanceof DSAPublicKey)) {
+                    throw new CertPathValidatorException("Input key is not " +
+                         "of a appropriate type for inheriting parameters");
+                }
+
+                DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
+                if (params == null) {
+                    throw new CertPathValidatorException(
+                                    "Key parameters missing");
+                }
+
+                try {
+                    BigInteger y = ((DSAPublicKey)currPubKey).getY();
+                    KeyFactory kf = KeyFactory.getInstance("DSA");
+                    DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
+                                                       params.getP(),
+                                                       params.getQ(),
+                                                       params.getG());
+                    currPubKey = kf.generatePublic(ks);
+                } catch (GeneralSecurityException e) {
+                    throw new CertPathValidatorException("Unable to generate " +
+                        "key with inherited parameters: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        // reset the previous public key
+        prevPubKey = currPubKey;
+
+        // check the extended key usage, ignore the check now
+        // List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
+
+        // DO NOT remove any unresolved critical extensions
     }
 
-    static void check(AlgorithmId aid) throws CertPathValidatorException {
-        check(aid.getName());
-    }
-
-    static void check(X509CRL crl) throws CertPathValidatorException {
-        check(crl.getSigAlgName());
-    }
+    /**
+     * Try to set the trust anchor of the checker.
+     * <p>
+     * If there is no trust anchor specified and the checker has not started,
+     * set the trust anchor.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     */
+    void trySetTrustAnchor(TrustAnchor anchor) {
+        // Don't bother if the check has started or trust anchor has already
+        // specified.
+        if (prevPubKey == null) {
+            if (anchor == null) {
+                throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+            }
 
-    private static void check(String algName)
-            throws CertPathValidatorException {
-
-        String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
-
-        for (String disabled : disabledAlgorithms) {
-            // checking the signature algorithm name
-            if (lowerCaseAlgName.indexOf(disabled) != -1) {
-                throw new CertPathValidatorException(
-                    "algorithm check failed: " + algName + " is disabled");
+            // Don't bother to change the trustedPubKey.
+            if (anchor.getTrustedCert() != null) {
+                prevPubKey = anchor.getTrustedCert().getPublicKey();
+            } else {
+                prevPubKey = anchor.getCAPublicKey();
             }
         }
     }
 
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, X509CRL crl)
+                        throws CertPathValidatorException {
+
+        X509CRLImpl x509CRLImpl = null;
+        try {
+            x509CRLImpl = X509CRLImpl.toImpl(crl);
+        } catch (CRLException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
+        check(key, algorithmId);
+    }
+
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, AlgorithmId algorithmId)
+                        throws CertPathValidatorException {
+        String sigAlgName = algorithmId.getName();
+        AlgorithmParameters sigAlgParams = algorithmId.getParameters();
+
+        if (!certPathDefaultConstraints.permits(
+                SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
+            throw new CertPathValidatorException(
+                "algorithm check failed: " + sigAlgName + " is disabled");
+        }
+    }
+
 }
+
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -289,16 +289,6 @@
         X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
         X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
 
-        // check the crl signature algorithm
-        try {
-            AlgorithmChecker.check(crl);
-        } catch (CertPathValidatorException cpve) {
-            if (debug != null) {
-                debug.println("CRL signature algorithm check failed: " + cpve);
-            }
-            return false;
-        }
-
         // if crlIssuer is set, verify that it matches the issuer of the
         // CRL and the CRL contains an IDP extension with the indirectCRL
         // boolean asserted. Otherwise, verify that the CRL issuer matches the
@@ -637,6 +627,16 @@
             }
         }
 
+        // check the crl signature algorithm
+        try {
+            AlgorithmChecker.check(prevKey, crl);
+        } catch (CertPathValidatorException cpve) {
+            if (debug != null) {
+                debug.println("CRL signature algorithm check failed: " + cpve);
+            }
+            return false;
+        }
+
         // validate the signature on the CRL
         try {
             crl.verify(prevKey, provider);
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -719,11 +719,6 @@
         /* we don't perform any validation of the trusted cert */
         if (!isTrustedCert) {
             /*
-             * check that the signature algorithm is not disabled.
-             */
-            AlgorithmChecker.check(cert);
-
-            /*
              * Check CRITICAL private extensions for user checkers that
              * support forward checking (forwardCheckers) and remove
              * ones we know how to check.
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -327,6 +327,10 @@
                 "(set using the OCSP security properties).");
         }
 
+        // The algorithm constraints of the OCSP trusted responder certificate
+        // does not need to be checked in this code. The constraints will be
+        // checked when the responder's certificate is validated.
+
         CertId certId = null;
         OCSPResponse response = null;
         try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -32,6 +32,7 @@
 import java.security.cert.CertificateParsingException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CRLReason;
+import java.security.cert.TrustAnchor;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
 import java.util.Date;
@@ -371,6 +372,13 @@
                         "OCSP responses", cpe);
                 }
 
+                // Check algorithm constraints specified in security property
+                // "jdk.certpath.disabledAlgorithms".
+                AlgorithmChecker algChecker = new AlgorithmChecker(
+                                    new TrustAnchor(responderCert, null));
+                algChecker.init(false);
+                algChecker.check(cert, Collections.<String>emptySet());
+
                 // check the validity
                 try {
                     if (dateCheckedAgainst == null) {
@@ -422,6 +430,10 @@
         // Confirm that the signed response was generated using the public
         // key from the trusted responder cert
         if (responderCert != null) {
+            // Check algorithm constraints specified in security property
+            // "jdk.certpath.disabledAlgorithms".
+            AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
+
             if (!verifyResponse(responseDataDer, responderCert,
                 sigAlgId, signature)) {
                 throw new CertPathValidatorException(
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -275,7 +275,7 @@
         int certPathLen = certList.size();
 
         basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
-        AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
+        AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
         KeyChecker keyChecker = new KeyChecker(certPathLen,
             pkixParam.getTargetCertConstraints());
         ConstraintsChecker constraintsChecker =
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -347,9 +347,6 @@
             return;
         }
 
-        /* check that the signature algorithm is not disabled. */
-        AlgorithmChecker.check(cert);
-
         /*
          * check for looping - abort a loop if
          * ((we encounter the same certificate twice) AND
@@ -470,9 +467,16 @@
         if (unresolvedCritExts == null) {
             unresolvedCritExts = Collections.<String>emptySet();
         }
+
+        /*
+         * Check that the signature algorithm is not disabled.
+         */
+        currentState.algorithmChecker.check(cert, unresolvedCritExts);
+
         for (PKIXCertPathChecker checker : currentState.userCheckers) {
             checker.check(cert, unresolvedCritExts);
         }
+
         /*
          * Look at the remaining extensions and remove any ones we have
          * already checked. If there are any left, throw an exception!
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -96,6 +96,9 @@
     /* the checker used for revocation status */
     public CrlRevocationChecker crlChecker;
 
+    /* the algorithm checker */
+    AlgorithmChecker algorithmChecker;
+
     /* the trust anchor used to validate the path */
     TrustAnchor trustAnchor;
 
@@ -241,6 +244,14 @@
             updateState(anchor.getCAPublicKey(), caName);
         }
 
+        // The user specified AlgorithmChecker may not be
+        // able to set the trust anchor until now.
+        for (PKIXCertPathChecker checker : userCheckers) {
+            if (checker instanceof AlgorithmChecker) {
+                ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
+            }
+        }
+
         init = false;
     }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -302,6 +302,7 @@
             // init the crl checker
             currentState.crlChecker =
                 new CrlRevocationChecker(null, buildParams, null, onlyEECert);
+            currentState.algorithmChecker = new AlgorithmChecker(anchor);
             try {
                 depthFirstSearchReverse(null, currentState,
                 new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -475,29 +476,41 @@
                 userCheckers.add(mustCheck, policyChecker);
                 mustCheck++;
 
+                // add the algorithm checker
+                userCheckers.add(mustCheck,
+                        new AlgorithmChecker(builder.trustAnchor));
+                mustCheck++;
+
                 if (nextState.keyParamsNeeded()) {
                     PublicKey rootKey = cert.getPublicKey();
                     if (builder.trustAnchor.getTrustedCert() == null) {
                         rootKey = builder.trustAnchor.getCAPublicKey();
                         if (debug != null)
-                            debug.println("SunCertPathBuilder.depthFirstSearchForward" +
-                                          " using buildParams public key: " +
-                                          rootKey.toString());
+                            debug.println(
+                                "SunCertPathBuilder.depthFirstSearchForward " +
+                                "using buildParams public key: " +
+                                rootKey.toString());
                     }
                     TrustAnchor anchor = new TrustAnchor
                         (cert.getSubjectX500Principal(), rootKey, null);
+
+                    // add the basic checker
                     basicChecker = new BasicChecker(anchor,
                                            builder.date,
                                            buildParams.getSigProvider(),
                                            true);
                     userCheckers.add(mustCheck, basicChecker);
                     mustCheck++;
+
+                    // add the crl revocation checker
                     if (buildParams.isRevocationEnabled()) {
                         userCheckers.add(mustCheck, new CrlRevocationChecker
                             (anchor, buildParams, null, onlyEECert));
                         mustCheck++;
                     }
                 }
+                // Why we don't need BasicChecker and CrlRevocationChecker
+                // if nextState.keyParamsNeeded() is false?
 
                 for (int i=0; i<appendedCerts.size(); i++) {
                     X509Certificate currCert = appendedCerts.get(i);
@@ -513,10 +526,18 @@
                     for (int j=0; j<userCheckers.size(); j++) {
                         PKIXCertPathChecker currChecker = userCheckers.get(j);
                         if (j < mustCheck ||
-                            !currChecker.isForwardCheckingSupported())
-                        {
+                            !currChecker.isForwardCheckingSupported()) {
                             if (i == 0) {
                                 currChecker.init(false);
+
+                                // The user specified
+                                // AlgorithmChecker may not be
+                                // able to set the trust anchor until now.
+                                if (j >= mustCheck &&
+                                    currChecker instanceof AlgorithmChecker) {
+                                    ((AlgorithmChecker)currChecker).
+                                        trySetTrustAnchor(builder.trustAnchor);
+                                }
                             }
 
                             try {
--- a/jdk/src/share/classes/sun/security/rsa/RSASignature.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/rsa/RSASignature.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -49,7 +49,7 @@
 public abstract class RSASignature extends SignatureSpi {
 
     // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
-    // it has the form 30:xx:30:0c:[digestOID]:05:00:04:xx:[digest]
+    // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
     // this means the encoded length is (8 + digestOID.length + digest.length)
     private static final int baseLength = 8;
 
@@ -104,7 +104,8 @@
     // initialize for signing. See JCA doc
     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
             throws InvalidKeyException {
-        RSAPrivateKey rsaKey = (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
+        RSAPrivateKey rsaKey =
+            (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
         this.privateKey = rsaKey;
         this.publicKey = null;
         initCommon(rsaKey, random);
@@ -212,7 +213,8 @@
         DerOutputStream out = new DerOutputStream();
         new AlgorithmId(oid).encode(out);
         out.putOctetString(digest);
-        DerValue result = new DerValue(DerValue.tag_Sequence, out.toByteArray());
+        DerValue result =
+            new DerValue(DerValue.tag_Sequence, out.toByteArray());
         return result.toByteArray();
     }
 
@@ -229,7 +231,8 @@
         }
         AlgorithmId algId = AlgorithmId.parse(values[0]);
         if (algId.getOID().equals(oid) == false) {
-            throw new IOException("ObjectIdentifier mismatch: " + algId.getOID());
+            throw new IOException("ObjectIdentifier mismatch: "
+                + algId.getOID());
         }
         if (algId.getEncodedParams() != null) {
             throw new IOException("Unexpected AlgorithmId parameters");
--- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -28,6 +28,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.Hashtable;
 
 import java.security.*;
 import javax.crypto.*;
@@ -50,6 +51,37 @@
  * 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.
  *
@@ -76,6 +108,21 @@
     private int blockSize;
 
     /**
+     * secure random
+     */
+    private SecureRandom random;
+
+    /**
+     * 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() {
@@ -90,14 +137,37 @@
      * implementation could be found.
      */
     private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
-            SecretKey key,  IvParameterSpec iv, boolean encrypt)
-            throws NoSuchAlgorithmException {
+            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;
-            cipher.init(mode, key, iv);
-            // do not call getBlockSize until after init()
+
+            if (random == null) {
+                random = JsseJce.getSecureRandom();
+            }
+            this.random = random;
+
+            /*
+             * 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
@@ -119,19 +189,37 @@
      * Factory method to obtain a new CipherBox object.
      */
     static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
-            SecretKey key, IvParameterSpec iv, boolean encrypt)
-            throws NoSuchAlgorithmException {
+            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, encrypt);
+            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.
      */
@@ -139,8 +227,26 @@
         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")) {
@@ -189,6 +295,34 @@
             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()) {
+                        buf = bb.array();
+                        System.arraycopy(buf, pos,
+                                buf, 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);
@@ -236,11 +370,25 @@
     /*
      * 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) throws BadPaddingException {
         if (cipher == null) {
             return len;
         }
+
         try {
             int newLen = cipher.update(buf, offset, len, buf, offset);
             if (newLen != len) {
@@ -263,6 +411,18 @@
             if (blockSize != 0) {
                 newLen = removePadding(buf, offset, newLen,
                              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) {
@@ -277,6 +437,8 @@
      * 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) throws BadPaddingException {
 
@@ -292,7 +454,6 @@
              * Decrypt "in-place".
              */
             int pos = bb.position();
-
             ByteBuffer dup = bb.duplicate();
             int newLen = cipher.update(dup, bb);
             if (newLen != len) {
@@ -320,6 +481,33 @@
             if (blockSize != 0) {
                 bb.position(pos);
                 newLen = removePadding(bb, 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()) {
+                        buf = bb.array();
+                        System.arraycopy(buf, pos + blockSize,
+                                         buf, 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) {
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java	Tue Nov 09 22:53:18 2010 -0800
@@ -30,6 +30,7 @@
 
 import java.security.NoSuchAlgorithmException;
 import java.security.InvalidKeyException;
+import java.security.SecureRandom;
 
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
@@ -37,6 +38,7 @@
 
 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.*;
 
 /**
@@ -101,19 +103,32 @@
     // by default
     final int priority;
 
-    // key exchange, bulk cipher, and mac algorithms. See those classes below.
+    // 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) {
+            KeyExchange keyExchange, BulkCipher cipher,
+            boolean allowed, int obsoleted, int supported, PRF prfAlg) {
         this.name = name;
         this.id = id;
         this.priority = priority;
@@ -124,6 +139,10 @@
             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")) {
@@ -136,8 +155,14 @@
         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;
@@ -148,6 +173,9 @@
         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;
     }
 
     /**
@@ -197,10 +225,12 @@
         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;
     }
 
@@ -227,10 +257,17 @@
         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) {
+            KeyExchange keyExchange, BulkCipher cipher,
+            boolean allowed, int obsoleted, int supported, PRF prf) {
+
         CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
-                                        cipher, allowed);
+            cipher, allowed, obsoleted, supported, prf);
         if (idMap.put(id, c) != null) {
             throw new RuntimeException("Duplicate ciphersuite definition: "
                                         + id + ", " + name);
@@ -243,6 +280,41 @@
         }
     }
 
+    /*
+     * 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) {
@@ -380,10 +452,11 @@
          *
          * @exception NoSuchAlgorithmException if anything goes wrong
          */
-        CipherBox newCipher(ProtocolVersion version,
-                SecretKey key, IvParameterSpec iv,
+        CipherBox newCipher(ProtocolVersion version, SecretKey key,
+                IvParameterSpec iv, SecureRandom random,
                 boolean encrypt) throws NoSuchAlgorithmException {
-            return CipherBox.newCipherBox(version, this, key, iv, encrypt);
+            return CipherBox.newCipherBox(version, this,
+                                            key, iv, random, encrypt);
         }
 
         /**
@@ -402,6 +475,7 @@
             if (this == B_AES_256) {
                 return isAvailable(this);
             }
+
             // always available
             return true;
         }
@@ -421,7 +495,8 @@
                         (new byte[cipher.expandedKeySize], cipher.algorithm);
                     IvParameterSpec iv =
                         new IvParameterSpec(new byte[cipher.ivSize]);
-                    cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
+                    cipher.newCipher(ProtocolVersion.DEFAULT,
+                                                key, iv, null, true);
                     b = Boolean.TRUE;
                 } catch (NoSuchAlgorithmException e) {
                     b = Boolean.FALSE;
@@ -439,7 +514,7 @@
     /**
      * An SSL/TLS key MAC algorithm.
      *
-     * Also contains a factory method to obtain in initialized MAC
+     * Also contains a factory method to obtain an initialized MAC
      * for this algorithm.
      */
     final static class MacAlg {
@@ -499,6 +574,48 @@
     final static MacAlg M_NULL = new MacAlg("NULL", 0);
     final static MacAlg M_MD5  = new MacAlg("MD5", 16);
     final static MacAlg M_SHA  = new MacAlg("SHA", 20);
+    final static MacAlg M_SHA256  = new MacAlg("SHA256", 32);
+    final static MacAlg M_SHA384  = new MacAlg("SHA384", 48);
+
+    // 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>();
@@ -509,6 +626,239 @@
         // 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);
 
@@ -516,191 +866,377 @@
         // They are listed in preference order, most preferred first.
         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_RSA_WITH_AES_128_CBC_SHA256",
+            0x003c, --p, K_RSA,         B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_RSA_WITH_AES_256_CBC_SHA256",
+            0x003d, --p, K_RSA,         B_AES_256, 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_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_256_CBC_SHA256",
+            0x006a, --p, K_DHE_DSS,     B_AES_256, T, max, tls12, P_SHA256);
+        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+            0x006b, --p, K_DHE_RSA,     B_AES_256, T, max, tls12, P_SHA256);
+
+        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_ECDSA_WITH_AES_256_CBC_SHA384",
+            0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
+        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_ECDSA_WITH_AES_256_CBC_SHA384",
+            0xc026, --p, K_ECDH_ECDSA,  B_AES_256, T, max, tls12, P_SHA384);
+        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+            0xc027, --p, K_ECDHE_RSA,   B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+            0xc028, --p, K_ECDHE_RSA,   B_AES_256, T, max, tls12, P_SHA384);
+        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+            0xc029, --p, K_ECDH_RSA,    B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+            0xc02a, --p, K_ECDH_RSA,    B_AES_256, T, max, tls12, P_SHA384);
+
         add("SSL_RSA_WITH_RC4_128_MD5",
-                              0x0004, --p, K_RSA,        B_RC4_128, N);
+            0x0004, --p, K_RSA,         B_RC4_128, N);
         add("SSL_RSA_WITH_RC4_128_SHA",
-                              0x0005, --p, K_RSA,        B_RC4_128, N);
+            0x0005, --p, K_RSA,         B_RC4_128, N);
         add("TLS_RSA_WITH_AES_128_CBC_SHA",
-                              0x002f, --p, K_RSA,        B_AES_128, T);
+            0x002f, --p, K_RSA,         B_AES_128, T);
         add("TLS_RSA_WITH_AES_256_CBC_SHA",
-                              0x0035, --p, K_RSA,        B_AES_256, T);
+            0x0035, --p, K_RSA,         B_AES_256, T);
 
         add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
-                              0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
+            0xC002, --p, K_ECDH_ECDSA,  B_RC4_128, N);
         add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
-                              0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
+            0xC004, --p, K_ECDH_ECDSA,  B_AES_128, T);
         add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
-                              0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
+            0xC005, --p, K_ECDH_ECDSA,  B_AES_256, T);
         add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
-                              0xC00C, --p, K_ECDH_RSA,   B_RC4_128, N);
+            0xC00C, --p, K_ECDH_RSA,    B_RC4_128, N);
         add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
-                              0xC00E, --p, K_ECDH_RSA,   B_AES_128, T);
+            0xC00E, --p, K_ECDH_RSA,    B_AES_128, T);
         add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
-                              0xC00F, --p, K_ECDH_RSA,   B_AES_256, T);
+            0xC00F, --p, K_ECDH_RSA,    B_AES_256, T);
 
         add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
-                              0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
+            0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
         add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-                              0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
+            0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
         add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-                              0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
+            0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
         add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
-                              0xC011, --p, K_ECDHE_RSA,  B_RC4_128, N);
+            0xC011, --p, K_ECDHE_RSA,   B_RC4_128, N);
         add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-                              0xC013, --p, K_ECDHE_RSA,  B_AES_128, T);
+            0xC013, --p, K_ECDHE_RSA,   B_AES_128, T);
         add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-                              0xC014, --p, K_ECDHE_RSA,  B_AES_256, T);
+            0xC014, --p, K_ECDHE_RSA,   B_AES_256, T);
 
         add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-                              0x0033, --p, K_DHE_RSA,    B_AES_128, T);
+            0x0033, --p, K_DHE_RSA,     B_AES_128, T);
         add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-                              0x0039, --p, K_DHE_RSA,    B_AES_256, T);
+            0x0039, --p, K_DHE_RSA,     B_AES_256, T);
         add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
-                              0x0032, --p, K_DHE_DSS,    B_AES_128, T);
+            0x0032, --p, K_DHE_DSS,     B_AES_128, T);
         add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
-                              0x0038, --p, K_DHE_DSS,    B_AES_256, T);
+            0x0038, --p, K_DHE_DSS,     B_AES_256, T);
 
         add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0x000a, --p, K_RSA,        B_3DES,    T);
+            0x000a, --p, K_RSA,         B_3DES,    T);
         add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC003, --p, K_ECDH_ECDSA, B_3DES,    T);
+            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);
+            0xC00D, --p, K_ECDH_RSA,    B_3DES,    T);
         add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC008, --p, K_ECDHE_ECDSA,B_3DES,    T);
+            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);
+            0xC012, --p, K_ECDHE_RSA,   B_3DES,    T);
         add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0x0016, --p, K_DHE_RSA,    B_3DES,    T);
+            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_DES_CBC_SHA",
-                              0x0009, --p, K_RSA,        B_DES,     N);
-        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
-                              0x0015, --p, K_DHE_RSA,    B_DES,     N);
-        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
-                              0x0012, --p, K_DHE_DSS,    B_DES,     N);
-        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
-                              0x0003, --p, K_RSA_EXPORT, B_RC4_40,  N);
-        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0008, --p, K_RSA_EXPORT, B_DES_40,  N);
-        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0014, --p, K_DHE_RSA,    B_DES_40,  N);
-        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0011, --p, K_DHE_DSS,    B_DES_40,  N);
+            0x0013, --p, K_DHE_DSS,     B_3DES,    N);
 
         // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
         add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
-                              0x00ff, --p, K_SCSV,       B_NULL,    T);
+            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.
         p = DEFAULT_SUITES_PRIORITY;
 
+        // weak single-DES cipher suites
+        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);
+
         // Anonymous key exchange and the NULL ciphers
         add("SSL_RSA_WITH_NULL_MD5",
-                              0x0001, --p, K_RSA,        B_NULL,    N);
+            0x0001, --p, K_RSA,         B_NULL,    N);
         add("SSL_RSA_WITH_NULL_SHA",
-                              0x0002, --p, K_RSA,        B_NULL,    N);
+            0x0002, --p, K_RSA,         B_NULL,    N);
+        add("TLS_RSA_WITH_NULL_SHA256",
+            0x003b, --p, K_RSA,         B_NULL,    N, max, tls12, P_SHA256);
+
         add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
-                              0xC001, --p, K_ECDH_ECDSA, B_NULL,    N);
+            0xC001, --p, K_ECDH_ECDSA,  B_NULL,    N);
         add("TLS_ECDH_RSA_WITH_NULL_SHA",
-                              0xC00B, --p, K_ECDH_RSA,   B_NULL,    N);
+            0xC00B, --p, K_ECDH_RSA,    B_NULL,    N);
         add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
-                              0xC006, --p, K_ECDHE_ECDSA,B_NULL,    N);
+            0xC006, --p, K_ECDHE_ECDSA, B_NULL,    N);
         add("TLS_ECDHE_RSA_WITH_NULL_SHA",
-                              0xC010, --p, K_ECDHE_RSA,  B_NULL,    N);
+            0xC010, --p, K_ECDHE_RSA,   B_NULL,    N);
 
         add("SSL_DH_anon_WITH_RC4_128_MD5",
-                              0x0018, --p, K_DH_ANON,    B_RC4_128, N);
+            0x0018, --p, K_DH_ANON,     B_RC4_128, N);
         add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
-                              0x0034, --p, K_DH_ANON,    B_AES_128, N);
+            0x0034, --p, K_DH_ANON,     B_AES_128, N);
         add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
-                              0x003a, --p, K_DH_ANON,    B_AES_256, N);
+            0x003a, --p, K_DH_ANON,     B_AES_256, N);
         add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
-                              0x001b, --p, K_DH_ANON,    B_3DES,    N);
+            0x001b, --p, K_DH_ANON,     B_3DES,    N);
         add("SSL_DH_anon_WITH_DES_CBC_SHA",
-                              0x001a, --p, K_DH_ANON,    B_DES,     N);
+            0x001a, --p, K_DH_ANON,     B_DES,     N, tls12);
+
+        add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+            0x006c, --p, K_DH_ANON,     B_AES_128, N, max, tls12, P_SHA256);
+        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_RC4_128_SHA",
-                              0xC016, --p, K_ECDH_ANON,  B_RC4_128, N);
+            0xC016, --p, K_ECDH_ANON,   B_RC4_128, N);
         add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
-                              0xC018, --p, K_ECDH_ANON,  B_AES_128, T);
+            0xC018, --p, K_ECDH_ANON,   B_AES_128, T);
         add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
-                              0xC019, --p, K_ECDH_ANON,  B_AES_256, T);
+            0xC019, --p, K_ECDH_ANON,   B_AES_256, T);
         add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
-                              0xC017, --p, K_ECDH_ANON,  B_3DES,    T);
+            0xC017, --p, K_ECDH_ANON,   B_3DES,    T);
 
         add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-                              0x0017, --p, K_DH_ANON,    B_RC4_40,  N);
+            0x0017, --p, K_DH_ANON,     B_RC4_40,  N, tls11);
         add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0019, --p, K_DH_ANON,    B_DES_40,  N);
+            0x0019, --p, K_DH_ANON,     B_DES_40,  N, tls11);
 
         add("TLS_ECDH_anon_WITH_NULL_SHA",
-                              0xC015, --p, K_ECDH_ANON,  B_NULL,    N);
+            0xC015, --p, K_ECDH_ANON,   B_NULL,    N);
+
+        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+            0x0003, --p, K_RSA_EXPORT,  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);
 
         // Supported Kerberos ciphersuites from RFC2712
         add("TLS_KRB5_WITH_RC4_128_SHA",
-                              0x0020, --p, K_KRB5,        B_RC4_128, N);
+            0x0020, --p, K_KRB5,        B_RC4_128, N);
         add("TLS_KRB5_WITH_RC4_128_MD5",
-                              0x0024, --p, K_KRB5,        B_RC4_128, N);
+            0x0024, --p, K_KRB5,        B_RC4_128, N);
         add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
-                              0x001f, --p, K_KRB5,        B_3DES,    N);
+            0x001f, --p, K_KRB5,        B_3DES,    N);
         add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
-                              0x0023, --p, K_KRB5,        B_3DES,    N);
+            0x0023, --p, K_KRB5,        B_3DES,    N);
         add("TLS_KRB5_WITH_DES_CBC_SHA",
-                              0x001e, --p, K_KRB5,        B_DES,     N);
+            0x001e, --p, K_KRB5,        B_DES,     N, tls12);
         add("TLS_KRB5_WITH_DES_CBC_MD5",
-                              0x0022, --p, K_KRB5,        B_DES,     N);
+            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);
+            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);
+            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);
+            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);
+            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);
+        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);
+        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);
+        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);
+        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);
+        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
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,6 @@
  * questions.
  */
 
-
 package sun.security.ssl;
 
 import java.io.*;
@@ -45,12 +44,12 @@
 
 import javax.security.auth.Subject;
 
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 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
@@ -89,6 +88,10 @@
      */
     private ProtocolVersion maxProtocolVersion;
 
+    // To switch off the SNI extension.
+    private final static boolean enableSNIExtension =
+            Debug.getBooleanProperty("jsse.enableSNIExtension", true);
+
     /*
      * Constructors
      */
@@ -190,7 +193,8 @@
                 }
                 break;
             case K_DH_ANON:
-                this.serverKeyExchange(new DH_ServerKeyExchange(input));
+                this.serverKeyExchange(new DH_ServerKeyExchange(
+                                                input, protocolVersion));
                 break;
             case K_DHE_DSS:
             case K_DHE_RSA:
@@ -198,7 +202,8 @@
                     this.serverKeyExchange(new DH_ServerKeyExchange(
                         input, serverKey,
                         clnt_random.random_bytes, svr_random.random_bytes,
-                        messageLen));
+                        messageLen,
+                        localSupportedSignAlgs, protocolVersion));
                 } catch (GeneralSecurityException e) {
                     throwSSLException("Server key", e);
                 }
@@ -209,7 +214,8 @@
                 try {
                     this.serverKeyExchange(new ECDH_ServerKeyExchange
                         (input, serverKey, clnt_random.random_bytes,
-                        svr_random.random_bytes));
+                        svr_random.random_bytes,
+                        localSupportedSignAlgs, protocolVersion));
                 } catch (GeneralSecurityException e) {
                     throwSSLException("Server key", e);
                 }
@@ -219,8 +225,9 @@
             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);
+                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(
@@ -243,10 +250,32 @@
                     "Client certificate requested for "+
                     "kerberos cipher suite.");
             }
-            certRequest = new CertificateRequest(input);
+            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:
@@ -254,7 +283,8 @@
             break;
 
         case HandshakeMessage.ht_finished:
-            this.serverFinished(new Finished(protocolVersion, input));
+            this.serverFinished(
+                new Finished(protocolVersion, input, cipherSuite));
             break;
 
         default:
@@ -345,11 +375,15 @@
 
         // check if the server selected protocol version is OK for us
         ProtocolVersion mesgVersion = mesg.protocolVersion;
-        if (enabledProtocols.contains(mesgVersion) == false) {
-            throw new SSLHandshakeException
-            ("Server chose unsupported or disabled protocol: " + mesgVersion);
+        if (!isNegotiable(mesgVersion)) {
+            throw new SSLHandshakeException(
+                    "Server chose unsupported or disabled protocol: " +
+                    mesgVersion);
         }
 
+        handshakeHash.protocolDetermined(
+            mesgVersion.v >= ProtocolVersion.TLS12.v);
+
         // Set protocolVersion and propagate to SSLSocket and the
         // Handshake streams
         setVersion(mesgVersion);
@@ -425,10 +459,13 @@
 
         if (isNegotiable(mesg.cipherSuite) == false) {
             fatalSE(Alerts.alert_illegal_parameter,
-                "Server selected improper ciphersuite " + cipherSuite);
+                "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,
@@ -507,7 +544,6 @@
                 if (debug != null && Debug.isOn("session")) {
                     System.out.println("%% Server resumed " + session);
                 }
-                return;
             } else {
                 // we wanted to resume, but the server refused
                 session = null;
@@ -518,11 +554,21 @@
             }
         }
 
+        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);
@@ -531,7 +577,9 @@
 
         // 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);
         }
@@ -567,11 +615,13 @@
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
-        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(), sslContext.getSecureRandom());
+        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
+                                            sslContext.getSecureRandom());
         serverDH = mesg.getServerPublicKey();
     }
 
-    private void serverKeyExchange(ECDH_ServerKeyExchange mesg) throws IOException {
+    private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
+            throws IOException {
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
@@ -665,9 +715,13 @@
                     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)) {
+                        ECParameterSpec params =
+                            ((ECPublicKey)publicKey).getParams();
+                        int index =
+                            SupportedEllipticCurvesExtension.getCurveIndex(
+                                params);
+                        if (!SupportedEllipticCurvesExtension.isSupported(
+                                index)) {
                             publicKey = null;
                         }
                     }
@@ -813,8 +867,9 @@
                 throw new IOException("Hostname is required" +
                                 " to use Kerberos cipher suites");
             }
-            KerberosClientKeyExchange kerberosMsg = new KerberosClientKeyExchange
-                (hostname, isLoopbackSE(), getAccSE(), protocolVersion,
+            KerberosClientKeyExchange kerberosMsg =
+                new KerberosClientKeyExchange(
+                    hostname, isLoopbackSE(), getAccSE(), protocolVersion,
                 sslContext.getSecureRandom());
             // Record the principals involved in exchange
             session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
@@ -861,7 +916,8 @@
         case K_KRB5_EXPORT:
             byte[] secretBytes =
                 ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
-            preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret");
+            preMasterSecret = new SecretKeySpec(secretBytes,
+                "TlsPremasterSecret");
             break;
         case K_DHE_RSA:
         case K_DHE_DSS:
@@ -878,7 +934,8 @@
             preMasterSecret = ecdh.getAgreedSecret(serverKey);
             break;
         default:
-            throw new IOException("Internal error: unknown key exchange " + keyExchange);
+            throw new IOException("Internal error: unknown key exchange "
+                + keyExchange);
         }
 
         calculateKeys(preMasterSecret, null);
@@ -896,9 +953,32 @@
         if (signingKey != null) {
             CertificateVerify m3;
             try {
+                SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    preferableSignatureAlgorithm =
+                        SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                            peerSupportedSignAlgs, signingKey.getAlgorithm());
+
+                    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());
+                    sslContext.getSecureRandom(),
+                    preferableSignatureAlgorithm);
             } catch (GeneralSecurityException e) {
                 fatalSE(Alerts.alert_handshake_failure,
                     "Error signing certificate verify", e);
@@ -910,6 +990,10 @@
             }
             m3.write(output);
             output.doHashes();
+        } else {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                handshakeHash.setCertificateVerifyAlg(null);
+            }
         }
 
         /*
@@ -930,8 +1014,8 @@
             mesg.print(System.out);
         }
 
-        boolean verified = mesg.verify(protocolVersion, handshakeHash,
-                                Finished.SERVER, session.getMasterSecret());
+        boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
+            session.getMasterSecret());
 
         if (!verified) {
             fatalSE(Alerts.alert_illegal_parameter,
@@ -988,7 +1072,7 @@
     private void sendChangeCipherAndFinish(boolean finishedTag)
             throws IOException {
         Finished mesg = new Finished(protocolVersion, handshakeHash,
-                                Finished.CLIENT, session.getMasterSecret());
+            Finished.CLIENT, session.getMasterSecret(), cipherSuite);
 
         /*
          * Send the change_cipher_spec message, then the Finished message
@@ -1022,7 +1106,7 @@
         SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
 
         // a list of cipher suites sent by the client
-        CipherSuiteList cipherSuites = enabledCipherSuites;
+        CipherSuiteList cipherSuites = getActiveCipherSuites();
 
         // set the max protocol version this client is supporting.
         maxProtocolVersion = protocolVersion;
@@ -1057,8 +1141,7 @@
                 session = null;
             }
 
-            if ((session != null) &&
-                        (enabledProtocols.contains(sessionVersion) == false)) {
+            if ((session != null) && !isNegotiable(sessionVersion)) {
                 if (debug != null && Debug.isOn("session")) {
                     System.out.println("%% can't resume, protocol disabled");
                 }
@@ -1088,7 +1171,7 @@
              */
             if (!enableNewSession) {
                 if (session == null) {
-                    throw new SSLException(
+                    throw new SSLHandshakeException(
                         "Can't reuse existing SSL client session");
                 }
 
@@ -1105,7 +1188,7 @@
         }
 
         if (session == null && !enableNewSession) {
-            throw new SSLException("No existing session to resume");
+            throw new SSLHandshakeException("No existing session to resume");
         }
 
         // exclude SCSV for secure renegotiation
@@ -1131,14 +1214,52 @@
         }
 
         if (!negotiable) {
-            throw new SSLException("No negotiable cipher suite");
+            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(false);
+        // }
+
         // 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;
 
@@ -1194,26 +1315,23 @@
                 keyExchangeString = keyExchange.name;
             }
 
-            String identificator = getHostnameVerificationSE();
             if (tm instanceof X509ExtendedTrustManager) {
-                ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        (peerCerts != null ?
-                            peerCerts.clone() :
-                            null),
+                if (conn != null) {
+                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
+                        peerCerts.clone(),
                         keyExchangeString,
-                        getHostSE(),
-                        identificator);
+                        conn);
+                } else {
+                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
+                        peerCerts.clone(),
+                        keyExchangeString,
+                        engine);
+                }
             } else {
-                if (identificator != null) {
-                    throw new RuntimeException(
-                        "trust manager does not support peer identification");
-                }
-
-                tm.checkServerTrusted(
-                    (peerCerts != null ?
-                        peerCerts.clone() :
-                        peerCerts),
-                    keyExchangeString);
+                // 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.
--- a/jdk/src/share/classes/sun/security/ssl/Debug.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/Debug.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,6 +27,7 @@
 
 import java.io.PrintStream;
 import java.security.AccessController;
+import java.util.Locale;
 
 import sun.security.action.GetPropertyAction;
 
@@ -44,7 +45,7 @@
     static {
         args = java.security.AccessController.doPrivileged(
             new GetPropertyAction("javax.net.debug", ""));
-        args = args.toLowerCase();
+        args = args.toLowerCase(Locale.ENGLISH);
         if (args.equals("help")) {
             Help();
         }
@@ -114,7 +115,7 @@
             return false;
         } else {
             int n = 0;
-            option = option.toLowerCase();
+            option = option.toLowerCase(Locale.ENGLISH);
 
             if (args.indexOf("all") != -1) {
                 return true;
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeHash.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeHash.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,7 +26,13 @@
 
 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
@@ -36,51 +42,161 @@
  *
  * 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(boolean isTLS12) 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(false) is called, getFinishedHash() and
+ * getCertificateVerifyHash() cannot be called. After protocolDetermined(true)
+ * is called, getMD5Clone() and getSHAClone() cannot be called.
+ *
+ * 5. getMD5Clone() and getSHAClone() can only be called after
+ * protocolDetermined(false) is called.
+ *
+ * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
+ * all protocolDetermined(true), setCertificateVerifyAlg() and setFinishedAlg()
+ * have been called. 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.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 {
 
-    private final MessageDigest md5, sha;
+    // 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.
+     * 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 needCertificateVerify) {
-        int n = needCertificateVerify ? 3 : 2;
-        try {
-            md5 = CloneableDigest.getDigest("MD5", n);
-            sha = CloneableDigest.getDigest("SHA", n);
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException
-                        ("Algorithm MD5 or SHA not available", e);
+    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;
         }
     }
 
-    void update(byte b) {
-        md5.update(b);
-        sha.update(b);
-    }
-
-    void update(byte[] b, int offset, int len) {
-        md5.update(b, offset, len);
-        sha.update(b, offset, len);
-    }
-
     /**
-     * Reset the remaining digests. Note this does *not* reset the numbe of
+     * 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() {
-        md5.reset();
-        sha.reset();
+        if (version != -1) {
+            throw new RuntimeException(
+                    "reset() can be only be called before protocolDetermined");
+        }
+        data.reset();
     }
 
+
+    void protocolDetermined(boolean isTLS12) {
+
+        // Do not set again, will ignore
+        if (version != -1) return;
+
+        version = isTLS12 ? 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);
     }
 
@@ -88,6 +204,10 @@
      * 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);
     }
 
@@ -100,6 +220,181 @@
         }
     }
 
+    /////////////////////////////////////////////////////////////
+    // 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");
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+    // TEST
+    ////////////////////////////////////////////////////////////////
+
+    public static void main(String[] args) throws Exception {
+        Test t = new Test();
+        t.test(null, "SHA-256");
+        t.test("", "SHA-256");
+        t.test("SHA-1", "SHA-256");
+        t.test("SHA-256", "SHA-256");
+        t.test("SHA-384", "SHA-256");
+        t.test("SHA-512", "SHA-256");
+        t.testSame("sha", "SHA-1");
+        t.testSame("SHA", "SHA-1");
+        t.testSame("SHA1", "SHA-1");
+        t.testSame("SHA-1", "SHA-1");
+        t.testSame("SHA256", "SHA-256");
+        t.testSame("SHA-256", "SHA-256");
+    }
+
+    static class Test {
+        void update(HandshakeHash hh, String s) {
+            hh.update(s.getBytes(), 0, s.length());
+        }
+        static byte[] digest(String alg, String data) throws Exception {
+            return MessageDigest.getInstance(alg).digest(data.getBytes());
+        }
+        static void equals(byte[] b1, byte[] b2) {
+            if (!Arrays.equals(b1, b2)) {
+                throw new RuntimeException("Bad");
+            }
+        }
+        void testSame(String a, String a2) {
+            System.out.println("testSame: " + a + " " + a2);
+            if (!HandshakeHash.normalizeAlgName(a).equals(a2)) {
+                throw new RuntimeException("Bad");
+            }
+        }
+        /**
+         * Special convention: when it's certain that CV will not be used at the
+         * very beginning, use null as cvAlg. If known at a late stage, use "".
+         */
+        void test(String cvAlg, String finAlg) throws Exception {
+            System.out.println("test: " + cvAlg + " " + finAlg);
+            byte[] cv = null, f1, f2;
+            HandshakeHash hh = new HandshakeHash(true, true, null);
+            if (cvAlg == null) {
+                hh.setCertificateVerifyAlg(cvAlg);
+            }
+
+            update(hh, "ClientHello,");
+            hh.reset();
+            update(hh, "ClientHellov2,");
+            hh.setFinishedAlg(finAlg);
+
+            // Useless calls
+            hh.setFinishedAlg("SHA-1");
+            hh.setFinishedAlg("SHA-512");
+
+            update(hh, "More,");
+            if (cvAlg != null) {
+                if (cvAlg.isEmpty()) cvAlg = null;
+                hh.setCertificateVerifyAlg(cvAlg);
+            }
+
+            // Useless calls
+            hh.setCertificateVerifyAlg("SHA-1");
+            hh.setCertificateVerifyAlg(null);
+
+            hh.protocolDetermined(true);
+
+            if (cvAlg != null) {
+                cv = hh.getAllHandshakeMessages();
+                equals(cv, "ClientHellov2,More,".getBytes());
+            }
+
+            update(hh, "FIN1,");
+            f1 = hh.getFinishedHash();
+            equals(f1, digest(finAlg, "ClientHellov2,More,FIN1,"));
+            update(hh, "FIN2,");
+            f2 = hh.getFinishedHash();
+            equals(f2, digest(finAlg, "ClientHellov2,More,FIN1,FIN2,"));
+        }
+    }
 }
 
 /**
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * copyright (c) 1996, 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
@@ -41,15 +41,12 @@
 
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
 
 import javax.net.ssl.*;
 
-import sun.security.action.GetPropertyAction;
-
 import sun.security.internal.spec.TlsPrfParameterSpec;
-
 import sun.security.ssl.CipherSuite.*;
+import static sun.security.ssl.CipherSuite.PRF.*;
 
 /**
  * Many data structures are involved in the handshake messages.  These
@@ -258,6 +255,27 @@
         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<String>(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; }
 
@@ -290,7 +308,8 @@
         s.println("*** ClientHello, " + protocolVersion);
 
         if (debug != null && Debug.isOn("verbose")) {
-            s.print   ("RandomCookie:  "); clnt_random.print(s);
+            s.print("RandomCookie:  ");
+            clnt_random.print(s);
 
             s.print("Session ID:  ");
             s.println(sessionId);
@@ -327,7 +346,8 @@
         // empty
     }
 
-    ServerHello(HandshakeInStream input, int messageLength) throws IOException {
+    ServerHello(HandshakeInStream input, int messageLength)
+            throws IOException {
         protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
                                                   input.getInt8());
         svr_random = new RandomCookie(input);
@@ -367,7 +387,8 @@
         s.println("*** ServerHello, " + protocolVersion);
 
         if (debug != null && Debug.isOn("verbose")) {
-            s.print   ("RandomCookie:  "); svr_random.print(s);
+            s.print("RandomCookie:  ");
+            svr_random.print(s);
 
             int i;
 
@@ -425,8 +446,8 @@
                 }
                 v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
             } catch (CertificateException e) {
-                throw (SSLProtocolException)new SSLProtocolException
-                        (e.getMessage()).initCause(e);
+                throw (SSLProtocolException)new SSLProtocolException(
+                    e.getMessage()).initCause(e);
             }
         }
 
@@ -469,7 +490,7 @@
     }
 
     X509Certificate[] getCertificateChain() {
-        return chain;
+        return chain.clone();
     }
 }
 
@@ -597,9 +618,9 @@
         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));
+            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);
@@ -667,6 +688,12 @@
 
     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;
+
     /* Return the Diffie-Hellman modulus */
     BigInteger getModulus() {
         return new BigInteger(1, dh_p);
@@ -712,8 +739,11 @@
      * Construct from initialized DH key object, for DH_anon
      * key exchange.
      */
-    DH_ServerKeyExchange(DHCrypt obj) {
-        getValues(obj);
+    DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
+        this.protocolVersion = protocolVersion;
+        this.preferableSignatureAlgorithm = null;
+
+        setValues(obj);
         signature = null;
     }
 
@@ -723,22 +753,33 @@
      * key exchange.  (Constructor called by server.)
      */
     DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
-            byte svrNonce[], SecureRandom sr) throws GeneralSecurityException {
+            byte svrNonce[], SecureRandom sr,
+            SignatureAndHashAlgorithm signAlgorithm,
+            ProtocolVersion protocolVersion) throws GeneralSecurityException {
 
-        getValues(obj);
+        this.protocolVersion = protocolVersion;
+
+        setValues(obj);
 
         Signature sig;
-        if (key.getAlgorithm().equals("DSA")) {
-            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            this.preferableSignatureAlgorithm = signAlgorithm;
+            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
         } else {
-            sig = RSASignature.getInstance();
+            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();
     }
 
-    private void getValues(DHCrypt obj) {
+    private void setValues(DHCrypt obj) {
         dh_p = toByteArray(obj.getModulus());
         dh_g = toByteArray(obj.getBase());
         dh_Ys = toByteArray(obj.getPublicKey());
@@ -749,7 +790,12 @@
      * stream, as if sent from server to client for use with
      * DH_anon key exchange
      */
-    DH_ServerKeyExchange(HandshakeInStream input) throws IOException {
+    DH_ServerKeyExchange(HandshakeInStream input,
+            ProtocolVersion protocolVersion) throws IOException {
+
+        this.protocolVersion = protocolVersion;
+        this.preferableSignatureAlgorithm = null;
+
         dh_p = input.getBytes16();
         dh_g = input.getBytes16();
         dh_Ys = input.getBytes16();
@@ -762,13 +808,38 @@
      * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
      */
     DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
-            byte clntNonce[], byte svrNonce[], int messageSize)
+            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();
 
+        // 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();
@@ -783,12 +854,17 @@
 
         Signature sig;
         String algorithm = publicKey.getAlgorithm();
-        if (algorithm.equals("DSA")) {
-            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-        } else if (algorithm.equals("RSA")) {
-            sig = RSASignature.getInstance();
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sig = JsseJce.getSignature(
+                        preferableSignatureAlgorithm.getAlgorithmName());
         } else {
-            throw new SSLKeyException("neither an RSA or a DSA key");
+            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);
@@ -805,12 +881,18 @@
         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;
     }
 
@@ -818,7 +900,13 @@
         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 {
@@ -838,6 +926,11 @@
             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");
             }
         }
@@ -871,9 +964,19 @@
     // 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)
-            throws GeneralSecurityException {
+            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();
@@ -885,8 +988,14 @@
             return;
         }
 
-        Signature sig = getSignature(privateKey.getAlgorithm());
-        sig.initSign(privateKey);
+        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();
@@ -896,49 +1005,87 @@
      * Parse an ECDH server key exchange message.
      */
     ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
-            byte[] clntNonce, byte[] svrNonce)
+            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);
+            if (SupportedEllipticCurvesExtension.isSupported(curveId)
+                    == false) {
+                throw new SSLHandshakeException(
+                    "Unsupported curveId: " + curveId);
             }
-            String curveOid = SupportedEllipticCurvesExtension.getCurveOid(curveId);
+            String curveOid =
+                SupportedEllipticCurvesExtension.getCurveOid(curveId);
             if (curveOid == null) {
-                throw new SSLHandshakeException("Unknown named curve: " + curveId);
+                throw new SSLHandshakeException(
+                    "Unknown named curve: " + curveId);
             }
             parameters = JsseJce.getECParameterSpec(curveOid);
             if (parameters == null) {
-                throw new SSLHandshakeException("Unsupported curve: " + curveOid);
+                throw new SSLHandshakeException(
+                    "Unsupported curve: " + curveOid);
             }
         } else {
-            throw new SSLHandshakeException("Unsupported ECCurveType: " + curveType);
+            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));
+        publicKey = (ECPublicKey)factory.generatePublic(
+            new ECPublicKeySpec(point, parameters));
 
         if (signingKey == null) {
             // ECDH_anon
             return;
         }
 
-        // verify the signature
+        // 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();
-        Signature sig = getSignature(signingKey.getAlgorithm());
+
+        // 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");
+            throw new SSLKeyException(
+                "Invalid signature on ECDH server key exchange message");
         }
     }
 
@@ -949,7 +1096,8 @@
         return publicKey;
     }
 
-    private static Signature getSignature(String keyAlgorithm) throws NoSuchAlgorithmException {
+    private static Signature getSignature(String keyAlgorithm)
+            throws NoSuchAlgorithmException {
         if (keyAlgorithm.equals("EC")) {
             return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
         } else if (keyAlgorithm.equals("RSA")) {
@@ -973,6 +1121,11 @@
 
     int messageLength() {
         int sigLen = (signatureBytes == null) ? 0 : 2 + signatureBytes.length;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sigLen += SignatureAndHashAlgorithm.sizeInRecord();
+        }
+
         return 4 + pointBytes.length + sigLen;
     }
 
@@ -980,6 +1133,11 @@
         s.putInt8(CURVE_NAMED_CURVE);
         s.putInt16(curveId);
         s.putBytes8(pointBytes);
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            s.putInt8(preferableSignatureAlgorithm.getHashValue());
+            s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
+        }
+
         if (signatureBytes != null) {
             s.putBytes16(signatureBytes);
         }
@@ -989,6 +1147,11 @@
         s.println("*** ECDH ServerKeyExchange");
 
         if (debug != null && Debug.isOn("verbose")) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                s.println("Signature Algorithm " +
+                        preferableSignatureAlgorithm.getAlgorithmName());
+            }
+
             s.println("Server key: " + publicKey);
         }
     }
@@ -1014,8 +1177,8 @@
         try {
             return new X500Principal(name);
         } catch (IllegalArgumentException e) {
-            throw (SSLProtocolException)new SSLProtocolException
-                    (e.getMessage()).initCause(e);
+            throw (SSLProtocolException)new SSLProtocolException(
+                e.getMessage()).initCause(e);
         }
     }
 
@@ -1038,12 +1201,25 @@
  *
  * 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
 {
-    int messageType() { return ht_certificate_request; }
-
     // enum ClientCertificateType
     static final int   cct_rsa_sign = 1;
     static final int   cct_dss_sign = 2;
@@ -1068,8 +1244,21 @@
     DistinguishedName   authorities [];         // 3 to 2^16 - 1
         // ... "3" because that's the smallest DER-encoded X500 DN
 
-    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange)
-            throws IOException {
+    // 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++) {
@@ -1081,10 +1270,63 @@
         // 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) throws IOException {
+    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<DistinguishedName>();
         while (len >= 3) {
@@ -1108,31 +1350,58 @@
         return ret;
     }
 
-    int messageLength()
-    {
-        int len;
+    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
+        return algorithms;
+    }
+
+    @Override
+    int messageType() {
+        return ht_certificate_request;
+    }
 
-        len = 1 + types.length + 2;
-        for (int i = 0; i < authorities.length; i++)
+    @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;
     }
 
-    void send(HandshakeOutStream output) throws IOException
-    {
-        int     len = 0;
+    @Override
+    void send(HandshakeOutStream output) throws IOException {
+        // put certificate_types
+        output.putBytes8(types);
 
-        for (int i = 0; i < authorities.length; i++)
+        // 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.putBytes8(types);
         output.putInt16(len);
-        for (int i = 0; i < authorities.length; i++)
+        for (int i = 0; i < authorities.length; i++) {
             authorities[i].send(output);
+        }
     }
 
-    void print(PrintStream s) throws IOException
-    {
+    @Override
+    void print(PrintStream s) throws IOException {
         s.println("*** CertificateRequest");
 
         if (debug != null && Debug.isOn("verbose")) {
@@ -1166,9 +1435,28 @@
             }
             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:");
-            for (int i = 0; i < authorities.length; i++)
-                authorities[i].print(s);
+            if (authorities.length == 0) {
+                s.println("<Empty>");
+            } else {
+                for (int i = 0; i < authorities.length; i++) {
+                    authorities[i].print(s);
+                }
+            }
         }
     }
 }
@@ -1219,18 +1507,34 @@
  */
 static final class CertificateVerify extends HandshakeMessage {
 
-    int messageType() { return ht_certificate_verify; }
+    // the signature bytes
+    private byte[] signature;
 
-    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) throws GeneralSecurityException {
+    CertificateVerify(ProtocolVersion protocolVersion,
+            HandshakeHash handshakeHash, PrivateKey privateKey,
+            SecretKey masterSecret, SecureRandom sr,
+            SignatureAndHashAlgorithm signAlgorithm)
+            throws GeneralSecurityException {
+
+        this.protocolVersion = protocolVersion;
+
         String algorithm = privateKey.getAlgorithm();
-        Signature sig = getSignature(protocolVersion, algorithm);
+        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);
@@ -1240,11 +1544,41 @@
     //
     // Unmarshal the signed data from the input stream.
     //
-    CertificateVerify(HandshakeInStream input) throws IOException  {
+    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.
      */
@@ -1252,7 +1586,13 @@
             HandshakeHash handshakeHash, PublicKey publicKey,
             SecretKey masterSecret) throws GeneralSecurityException {
         String algorithm = publicKey.getAlgorithm();
-        Signature sig = getSignature(protocolVersion, algorithm);
+        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);
@@ -1286,25 +1626,35 @@
             ProtocolVersion protocolVersion,
             HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
             throws SignatureException {
-        MessageDigest md5Clone = handshakeHash.getMD5Clone();
-        MessageDigest shaClone = handshakeHash.getSHAClone();
-        boolean tls = protocolVersion.v >= ProtocolVersion.TLS10.v;
+
         if (algorithm.equals("RSA")) {
-            if (tls) {
-                // nothing to do
-            } else { // SSLv3
-                updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
-                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+            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());
             }
-            // need to use these hashes directly
-            RSASignature.setHashes(sig, md5Clone, shaClone);
         } else { // DSA, ECDSA
-            if (tls) {
-                // nothing to do
-            } else { // SSLv3
-                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+            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());
             }
-            sig.update(shaClone.digest());
         }
     }
 
@@ -1314,7 +1664,8 @@
      * all preceding handshake messages.
      * Used by the Finished class as well.
      */
-    static void updateDigest(MessageDigest md, byte[] pad1, byte[] pad2,
+    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.
@@ -1390,26 +1741,54 @@
                 methodCache.put(clazz, r);
             }
             if (r == NULL_OBJECT) {
-                throw new Exception("Digest does not support implUpdate(SecretKey)");
+                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);
+            throw new RuntimeException(
+                "Could not obtain encoded key and "
+                + "MessageDigest cannot digest key", e);
         }
     }
 
-    int messageLength() {
-        return 2 + signature.length;
+    @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());
+            }
+        }
     }
 }
 
@@ -1448,19 +1827,29 @@
     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) {
-        verifyData = getFinished(protocolVersion, handshakeHash, sender,
-                                 master);
+            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)
-            throws IOException {
+    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);
@@ -1472,18 +1861,16 @@
      * both client and server are fully in sync, and that the handshake
      * computations have been successful.
      */
-    boolean verify(ProtocolVersion protocolVersion,
-             HandshakeHash handshakeHash, int sender, SecretKey master) {
-        byte[] myFinished = getFinished(protocolVersion, handshakeHash,
-                                        sender, master);
+    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 static byte[] getFinished(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, int sender, SecretKey masterKey) {
+    private byte[] getFinished(HandshakeHash handshakeHash,
+            int sender, SecretKey masterKey) {
         byte[] sslLabel;
         String tlsLabel;
         if (sender == CLIENT) {
@@ -1495,23 +1882,53 @@
         } else {
             throw new RuntimeException("Invalid sender: " + sender);
         }
-        MessageDigest md5Clone = handshakeHash.getMD5Clone();
-        MessageDigest shaClone = handshakeHash.getSHAClone();
+
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            // TLS
+            // TLS 1.0+
             try {
-                byte[] seed = new byte[36];
-                md5Clone.digest(seed, 0, 16);
-                shaClone.digest(seed, 16, 20);
+                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);
 
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec
-                                                (masterKey, tlsLabel, seed, 12);
-                KeyGenerator prf = JsseJce.getKeyGenerator("SunTlsPrf");
-                prf.init(spec);
-                SecretKey prfKey = prf.generateKey();
+                    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");
+                    throw new ProviderException(
+                        "Invalid PRF output, format must be RAW");
                 }
                 byte[] finished = prfKey.getEncoded();
                 return finished;
@@ -1520,6 +1937,8 @@
             }
         } 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];
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,13 +29,12 @@
 import java.io.*;
 import java.util.*;
 import java.security.*;
-import java.security.MessageDigest;
 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 java.security.cert.X509Certificate;
 
 import javax.crypto.*;
 import javax.crypto.spec.*;
@@ -49,6 +48,8 @@
 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.
@@ -71,13 +72,48 @@
     byte[]              clientVerifyData;
     byte[]              serverVerifyData;
 
-    // is it an initial negotiation  or a renegotiation?
+    // Is it an initial negotiation  or a renegotiation?
     boolean                     isInitialHandshake;
 
-    // list of enabled protocols
-    ProtocolList enabledProtocols;
+    // 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;
@@ -90,13 +126,6 @@
     RandomCookie                clnt_random, svr_random;
     SSLSessionImpl              session;
 
-    // Temporary MD5 and SHA message digests. Must always be left
-    // in reset state after use.
-    private MessageDigest md5Tmp, shaTmp;
-
-    // list of enabled CipherSuites
-    CipherSuiteList     enabledCipherSuites;
-
     // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
     CipherSuite         cipherSuite;
 
@@ -191,6 +220,7 @@
 
         this.sslContext = context;
         this.isClient = isClient;
+        this.needCertVerify = needCertVerify;
         this.activeProtocolVersion = activeProtocolVersion;
         this.isInitialHandshake = isInitialHandshake;
         this.secureRenegotiation = secureRenegotiation;
@@ -200,23 +230,12 @@
         invalidated = false;
 
         setCipherSuite(CipherSuite.C_NULL);
-
-        md5Tmp = JsseJce.getMD5();
-        shaTmp = JsseJce.getSHA();
-
-        //
-        // We accumulate digests of the handshake messages so that
-        // we can read/write CertificateVerify and Finished messages,
-        // getting assurance against some particular active attacks.
-        //
-        handshakeHash = new HandshakeHash(needCertVerify);
-
         setEnabledProtocols(enabledProtocols);
 
         if (conn != null) {
-            conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
+            algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
         } else {        // engine != null
-            engine.inputRecord.setHandshakeHash(handshakeHash);
+            algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
         }
 
 
@@ -233,7 +252,7 @@
         // client's cert verify, those constants are in a convenient
         // order to drastically simplify state machine checking.
         //
-        state = -1;
+        state = -2;  // initialized but not activated
     }
 
     /*
@@ -268,6 +287,14 @@
         }
     }
 
+    String getRawHostnameSE() {
+        if (conn != null) {
+            return conn.getRawHostname();
+        } else {
+            return engine.getPeerHost();
+        }
+    }
+
     String getHostSE() {
         if (conn != null) {
             return conn.getHost();
@@ -313,14 +340,6 @@
         }
     }
 
-    String getHostnameVerificationSE() {
-        if (conn != null) {
-            return conn.getHostnameVerification();
-        } else {
-            return engine.getHostnameVerification();
-        }
-    }
-
     AccessControlContext getAccSE() {
         if (conn != null) {
             return conn.getAcc();
@@ -345,39 +364,139 @@
     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 enabled protocols. Called from the constructor or
-     * SSLSocketImpl.setEnabledProtocols() (if the handshake is not yet
-     * in progress).
+     * 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 setEnabledProtocols(ProtocolList enabledProtocols) {
-        this.enabledProtocols = enabledProtocols;
+    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. Using max() as the record
-        // version is not really correct but some implementations fail to
-        // correctly negotiate TLS otherwise.
-        protocolVersion = enabledProtocols.max;
+        // 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;
+        }
 
-        ProtocolVersion helloVersion = enabledProtocols.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;
     }
 
     /**
@@ -392,20 +511,150 @@
 
     /**
      * Check if the given ciphersuite is enabled and available.
-     * (Enabled ciphersuites are always available unless the status has
-     * changed due to change in JCE providers since it was enabled).
      * Does not check if the required server certificates are available.
      */
     boolean isNegotiable(CipherSuite s) {
-        return enabledCipherSuites.contains(s) && s.isNegotiable();
+        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);
     }
 
     /**
-     * As long as handshaking has not started, we can
+     * 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<CipherSuite>();
+            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<ProtocolVersion>(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 started.
+     * has activated.
      */
     void setEnableSessionCreation(boolean newSessions) {
         enableNewSession = newSessions;
@@ -419,12 +668,12 @@
         CipherBox box;
         if (isClient) {
             box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   false);
+                                   sslContext.getSecureRandom(), false);
             svrWriteKey = null;
             svrWriteIV = null;
         } else {
             box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   false);
+                                   sslContext.getSecureRandom(), false);
             clntWriteKey = null;
             clntWriteIV = null;
         }
@@ -439,12 +688,12 @@
         CipherBox box;
         if (isClient) {
             box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   true);
+                                   sslContext.getSecureRandom(), true);
             clntWriteKey = null;
             clntWriteIV = null;
         } else {
             box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   true);
+                                   sslContext.getSecureRandom(), true);
             svrWriteKey = null;
             svrWriteIV = null;
         }
@@ -502,6 +751,17 @@
     }
 
     /*
+     * 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() {
@@ -614,13 +874,20 @@
 
 
     /**
+     * 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.
-     * Server kickstarting is not as neat as it should be; we
-     * need to create a new handshaker, this method lets us
-     * know if we should.
      */
     boolean started() {
-        return state >= 0;
+        return state >= 0;  // 0: HandshakeMessage.ht_hello_request
+                            // 1: HandshakeMessage.ht_client_hello
     }
 
 
@@ -633,6 +900,7 @@
         if (state >= 0) {
             return;
         }
+
         HandshakeMessage m = getKickstartMessage();
 
         if (debug != null && Debug.isOn("handshake")) {
@@ -746,9 +1014,6 @@
      */
     private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
             ProtocolVersion requestedVersion) {
-        TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                (preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                clnt_random.random_bytes, svr_random.random_bytes);
 
         if (debug != null && Debug.isOn("keygen")) {
             HexDumpEncoder      dump = new HexDumpEncoder();
@@ -762,33 +1027,70 @@
             // 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("SunTlsMasterSecret");
+            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")) {
+            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);
                 System.out.println("Generating new random premaster secret");
             }
-            preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+
+            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),
+        // 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)) {
+        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();
@@ -800,13 +1102,21 @@
         // 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
-        // NOTE that we may be comparing two unsupported version numbers in
-        // the second case, which is why we cannot use object reference
-        // equality in this special case
-        ProtocolVersion premasterVersion = ProtocolVersion.valueOf(major, minor);
-        boolean versionMismatch = (premasterVersion != protocolVersion) &&
-                                  (premasterVersion.v != requestedVersion.v);
+        // 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
@@ -823,7 +1133,9 @@
                 + premasterVersion);
             System.out.println("Generating new random premaster secret");
         }
-        preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+        preMasterSecret =
+            RSAClientKeyExchange.generateDummySecret(requestedVersion);
+
         // recursive call with new premaster secret
         return calculateMasterSecret(preMasterSecret, null);
     }
@@ -849,24 +1161,41 @@
         int hashSize = cipherSuite.macAlg.size;
         boolean is_exportable = cipherSuite.exportable;
         BulkCipher cipher = cipherSuite.cipher;
-        int keySize = cipher.keySize;
-        int ivSize = cipher.ivSize;
         int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
 
-        TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-            (masterKey, protocolVersion.major, protocolVersion.minor,
+        // 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);
+            cipher.ivSize, hashSize,
+            prfHashAlg, prfHashLength, prfBlockSize);
 
         try {
-            KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsKeyMaterial");
+            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();
 
@@ -914,7 +1243,12 @@
                     System.out.println("Server write IV:");
                     printHex(dump, svrWriteIV.getIV());
                 } else {
-                    System.out.println("... no IV used for this cipher");
+                    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();
             }
--- a/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java	Tue Nov 09 22:53:18 2010 -0800
@@ -50,7 +50,8 @@
  *
  *  . UnknownExtension: used to represent all parsed extensions that we do not
  *      explicitly support.
- *  . ServerNameExtension: partially implemented server_name extension.
+ *  . 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.
@@ -78,6 +79,8 @@
             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) {
@@ -266,31 +269,102 @@
     }
 
     public String toString() {
-        return "Unsupported extension " + type + ", data: " + Debug.toString(data);
+        return "Unsupported extension " + type + ", data: " +
+            Debug.toString(data);
     }
 }
 
 /*
- * Support for the server_name extension is incomplete. Parsing is implemented
- * so that we get nicer debug output, but we neither send it nor do we do
- * act on it if we receive it.
+ * [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);
-        names = new ArrayList<ServerName>();
-        while (len > 0) {
-            ServerName name = new ServerName(s);
-            names.add(name);
-            len -= name.length + 2;
+
+        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 (len != 0) {
+
+        if (remains != 0) {
             throw new SSLProtocolException("Invalid server_name extension");
         }
     }
@@ -301,10 +375,19 @@
         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 {
-            length = s.getInt16();      // ServerNameList length
             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 {
@@ -322,15 +405,29 @@
     }
 
     int length() {
-        throw new RuntimeException("not yet supported");
+        return listLength == 0 ? 4 : 6 + listLength;
     }
 
     void send(HandshakeOutStream s) throws IOException {
-        throw new RuntimeException("not yet supported");
+        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() {
-        return "Unsupported extension " + type + ", " + names.toString();
+        StringBuffer buffer = new StringBuffer();
+        for (ServerName name : names) {
+            buffer.append("[" + name + "]");
+        }
+
+        return "Extension " + type + ", server_name: " + buffer;
     }
 }
 
@@ -523,7 +620,8 @@
     final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
 
     static final HelloExtension DEFAULT =
-        new SupportedEllipticPointFormatsExtension(new byte[] {FMT_UNCOMPRESSED});
+        new SupportedEllipticPointFormatsExtension(
+            new byte[] {FMT_UNCOMPRESSED});
 
     private final byte[] formats;
 
@@ -665,3 +763,105 @@
     }
 
 }
+
+/*
+ * [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;
+    }
+}
--- a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -69,6 +69,7 @@
     }
 
     public KerberosClientKeyExchange() {
+        // empty
     }
 
     public KerberosClientKeyExchange(String serverName, boolean isLoopback,
@@ -93,14 +94,17 @@
         }
     }
 
+    @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);
     }
--- a/jdk/src/share/classes/sun/security/ssl/MAC.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/MAC.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -105,6 +105,10 @@
             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);
         }
@@ -155,6 +159,42 @@
         return compute(type, bb, null, 0, bb.remaining());
     }
 
+    /**
+     * 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] == 0xFF && block[1] == 0xFF &&
+                block[2] == 0xFF && block[3] == 0xFF &&
+                block[4] == 0xFF && block[5] == 0xFF &&
+                block[6] == 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] == 0xFF && block[1] == 0xFF);
+    }
+
     // increment the sequence number in the block array
     // it is a 64-bit number stored in big-endian format
     private void incrementSequenceNumber() {
@@ -168,7 +208,8 @@
      * 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) {
+    private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
+            int offset, int len) {
 
         if (macSize == 0) {
             return nullMAC;
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -38,8 +38,12 @@
 final class ProtocolList {
 
     private static final ProtocolList SUPPORTED;
+    private static final ProtocolList CLIENT_DEFAULT;
+    private static final ProtocolList SERVER_DEFAULT;
 
-    private final Collection<ProtocolVersion> protocols;
+    // the sorted protocol version list
+    private final ArrayList<ProtocolVersion> protocols;
+
     private String[] protocolNames;
 
     // the minimum and maximum ProtocolVersions in this list
@@ -49,30 +53,45 @@
     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");
         }
-        protocols = new ArrayList<ProtocolVersion>(3);
+
+        ArrayList<ProtocolVersion> versions = new ArrayList<ProtocolVersion>(3);
         for (int i = 0; i < names.length; i++ ) {
             ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
-            if (protocols.contains(version) == false) {
-                protocols.add(version);
+            if (versions.contains(version) == false) {
+                versions.add(version);
             }
         }
-        if ((protocols.size() == 1)
-                && protocols.contains(ProtocolVersion.SSL20Hello)) {
-            throw new IllegalArgumentException("SSLv2Hello" +
-                  "cannot be enabled unless TLSv1 or SSLv3 is also enabled");
-        }
-        min = contains(ProtocolVersion.SSL30) ? ProtocolVersion.SSL30
-                                              : ProtocolVersion.TLS10;
-        max = contains(ProtocolVersion.TLS10) ? ProtocolVersion.TLS10
-                                              : ProtocolVersion.SSL30;
-        if (protocols.contains(ProtocolVersion.SSL20Hello)) {
-            helloVersion = ProtocolVersion.SSL20Hello;
-        } else {
-            helloVersion = min;
-        }
+
+        return versions;
     }
 
     /**
@@ -88,6 +107,37 @@
     }
 
     /**
+     * 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() {
@@ -106,11 +156,18 @@
     }
 
     /**
-     * Return the list of default enabled protocols. Currently, this
-     * is identical to the supported protocols.
+     * Return the list of default enabled protocols.
      */
-    static ProtocolList getDefault() {
-        return SUPPORTED;
+    static ProtocolList getDefault(boolean isServer) {
+        return isServer ? SERVER_DEFAULT : CLIENT_DEFAULT;
+    }
+
+    /**
+     * Return whether a protocol list is the original default enabled
+     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
+     */
+    static boolean isDefaultProtocolList(ProtocolList protocols) {
+        return protocols == CLIENT_DEFAULT || protocols == SERVER_DEFAULT;
     }
 
     /**
@@ -123,6 +180,13 @@
     static {
         if (SunJSSE.isFIPS()) {
             SUPPORTED = new ProtocolList(new String[] {
+                ProtocolVersion.TLS10.name,
+                ProtocolVersion.TLS11.name,
+                ProtocolVersion.TLS12.name
+            });
+
+            SERVER_DEFAULT = SUPPORTED;
+            CLIENT_DEFAULT = new ProtocolList(new String[] {
                 ProtocolVersion.TLS10.name
             });
         } else {
@@ -130,6 +194,24 @@
                 ProtocolVersion.SSL20Hello.name,
                 ProtocolVersion.SSL30.name,
                 ProtocolVersion.TLS10.name,
+                ProtocolVersion.TLS11.name,
+                ProtocolVersion.TLS12.name
+            });
+
+            SERVER_DEFAULT = SUPPORTED;
+
+            /*
+             * RFC 5246 says that sending SSLv2 backward-compatible
+             * hello SHOULD NOT be done any longer.
+             *
+             * We are not enabling TLS 1.1/1.2 by default yet on clients
+             * out of concern for interop with existing
+             * SSLv3/TLS1.0-only servers.  When these versions of TLS
+             * gain more traction, we'll enable them.
+             */
+            CLIENT_DEFAULT = new ProtocolList(new String[] {
+                ProtocolVersion.SSL30.name,
+                ProtocolVersion.TLS10.name
             });
         }
     }
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -45,9 +45,15 @@
  * @author  Andreas Sterbenz
  * @since   1.4.1
  */
-public final class ProtocolVersion {
+public final class ProtocolVersion implements Comparable<ProtocolVersion> {
+
+    // The limit of maximum protocol version
+    final static int LIMIT_MAX_VALUE = 0xFFFF;
 
-    // dummy protocol version value for invalid SSLSession
+    // 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
@@ -61,22 +67,24 @@
     final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
 
     // TLS 1.1
-    // not supported yet, but added for better readability of the debug trace
     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.0)
-    final static ProtocolVersion MAX = TLS10;
+    // 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 : SSL20Hello;
+    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
@@ -104,6 +112,8 @@
             return TLS10;
         } else if (v == TLS11.v) {
             return TLS11;
+        } else if (v == TLS12.v) {
+            return TLS12;
         } else if (v == SSL20Hello.v) {
             return SSL20Hello;
         } else {
@@ -134,18 +144,20 @@
         if (name == null) {
             throw new IllegalArgumentException("Protocol cannot be null");
         }
-        if (FIPS) {
-            if (name.equals(TLS10.name)) {
-                return TLS10;
-            } else {
-                throw new IllegalArgumentException
-                    ("Only TLS 1.0 allowed in FIPS mode");
-            }
+
+        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 {
@@ -157,4 +169,10 @@
         return name;
     }
 
+    /**
+     * Compares this object with the specified object for order.
+     */
+    public int compareTo(ProtocolVersion protocolVersion) {
+        return this.v - protocolVersion.v;
+    }
 }
--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -55,20 +55,17 @@
      * 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.
-     *
-     * Default is "false" (old behavior) for compatibility reasons. This
-     * will be changed in the future.
      */
     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);
 
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
     /*
      * The following field values were encrypted with the server's public
      * key (or temp key from server key exchange msg) and are presented
@@ -78,14 +75,14 @@
     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,
+    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");
@@ -94,7 +91,7 @@
 
         int major, minor;
 
-        if (rsaPreMasterSecretFix) {
+        if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
             major = maxVersion.major;
             minor = maxVersion.minor;
         } else {
@@ -103,7 +100,9 @@
         }
 
         try {
-            KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+            String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
+                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
+            KeyGenerator kg = JsseJce.getKeyGenerator(s);
             kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
             preMaster = kg.generateKey();
 
@@ -120,14 +119,15 @@
      * Server gets the PKCS #1 (block format 02) data, decrypts
      * it with its private key.
      */
-    RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
+    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");
         }
 
-        this.protocolVersion = currentVersion;
         if (currentVersion.v >= ProtocolVersion.TLS10.v) {
             encrypted = input.getBytes16();
         } else {
@@ -143,31 +143,109 @@
             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) {
-            /*
-             * Bogus decrypted ClientKeyExchange? If so, conjure a
-             * a random preMaster secret that will fail later during
-             * Finished message processing. This is a countermeasure against
-             * the "interactive RSA PKCS#1 encryption envelop attack" reported
-             * in June 1998. Preserving the executation path will
-             * mitigate timing attacks and force consistent error handling
-             * that will prevent an attacking client from differentiating
-             * different kinds of decrypted ClientKeyExchange bogosities.
-             */
-            if (debug != null && Debug.isOn("handshake")) {
+            // 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");
+                }
+
+                // We are not always able to get the encoded key of the
+                // premaster secret. Pass the cheking 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) {
+                    /*
+                     * we never checked the client_version in server side
+                     * for TLS v1.0 and SSL v3.0. For compatibility, we
+                     * maintain this behavior.
+                     */
+                    if (currentVersion.major == encoded[0] &&
+                        currentVersion.minor == encoded[1]) {
+                        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]));
+                }
+            } else {
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "incorrect length of premaster secret: " +
+                        encoded.length);
+                }
+            }
+        }
+
+        if (debug != null && Debug.isOn("handshake")) {
+            if (failoverException != null) {
                 System.out.println("Error decrypting premaster secret:");
-                e.printStackTrace(System.out);
-                System.out.println("Generating random secret");
+                failoverException.printStackTrace(System.out);
             }
-            preMaster = generateDummySecret(currentVersion);
+
+            System.out.println("Generating random secret");
         }
+
+        return generateDummySecret(clientHelloVersion);
     }
 
     // generate a premaster secret with the specified version number
     static SecretKey generateDummySecret(ProtocolVersion version) {
         try {
-            KeyGenerator kg =
-                    JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+            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();
@@ -176,6 +254,12 @@
         }
     }
 
+    @Override
+    int messageType() {
+        return ht_client_key_exchange;
+    }
+
+    @Override
     int messageLength() {
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
             return encrypted.length + 2;
@@ -184,6 +268,7 @@
         }
     }
 
+    @Override
     void send(HandshakeOutStream s) throws IOException {
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
             s.putBytes16(encrypted);
@@ -192,7 +277,9 @@
         }
     }
 
+    @Override
     void print(PrintStream s) throws IOException {
-        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + protocolVersion);
+        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
+                                                        protocolVersion);
     }
 }
--- a/jdk/src/share/classes/sun/security/ssl/Record.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/Record.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -47,11 +47,12 @@
     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    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,
@@ -59,8 +60,9 @@
      * 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 =
+    static final int    maxRecordSize =
                                       headerSize        // header
+                                    + maxIVLength       // iv
                                     + maxDataSize       // data
                                     + maxPadding        // padding
                                     + trailerSize;      // MAC
@@ -74,7 +76,7 @@
      * The maximum large record size is defined as maxRecordSize plus 2^14,
      * this is the amount OpenSSL is using.
      */
-    static final int            maxLargeRecordSize =
+    static final int    maxLargeRecordSize =
                 maxRecordSize   // Max size with a conforming implemenation
               + maxDataSize;    // extra 2^14 bytes for large data packets.
 
@@ -84,7 +86,11 @@
      * They only contain 2 and 1 bytes of data, respectively.
      * Allocate a smaller array.
      */
-    static final int maxAlertRecordSize =
-                        headerSize + 2 + maxPadding + trailerSize;
+    static final int    maxAlertRecordSize =
+                                      headerSize        // header
+                                    + maxIVLength       // iv
+                                    + 2                 // alert
+                                    + maxPadding        // padding
+                                    + trailerSize;      // MAC
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 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.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<String>();
+            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<String>();
+
+            if (bulkCipher.transformation != null) {
+                components.addAll(super.decomposes(bulkCipher.transformation));
+            }
+
+            return components;
+        }
+
+        protected Set<String> decomposes(MacAlg macAlg) {
+            Set<String> components = new HashSet<String>();
+
+            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<String>();
+
+                    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<String>();
+
+                    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);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,11 +27,15 @@
 
 import java.net.Socket;
 
+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 class SSLContextImpl extends SSLContextSpi {
 
     private static final Debug debug = Debug.getInstance("ssl");
@@ -82,7 +86,8 @@
         if (sr == null) {
             secureRandom = JsseJce.getSecureRandom();
         } else {
-            if (SunJSSE.isFIPS() && (sr.getProvider() != SunJSSE.cryptoProvider)) {
+            if (SunJSSE.isFIPS() &&
+                        (sr.getProvider() != SunJSSE.cryptoProvider)) {
                 throw new KeyManagementException
                     ("FIPS mode: SecureRandom must be from provider "
                     + SunJSSE.cryptoProvider.getName());
@@ -111,11 +116,18 @@
         // 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)) {
+                if (SunJSSE.isFIPS() &&
+                        !(tm[i] instanceof X509TrustManagerImpl)) {
                     throw new KeyManagementException
                         ("FIPS mode: only SunJSSE TrustManagers may be used");
                 }
-                return (X509TrustManager)tm[i];
+
+                if (tm[i] instanceof X509ExtendedTrustManager) {
+                    return (X509TrustManager)tm[i];
+                } else {
+                    return new AbstractTrustManagerWrapper(
+                                        (X509TrustManager)tm[i]);
+                }
             }
         }
 
@@ -153,7 +165,7 @@
                     "SSLContext.init():  need an " +
                     "X509ExtendedKeyManager for SSLEngine use");
             }
-            return new AbstractWrapper((X509KeyManager)km);
+            return new AbstractKeyManagerWrapper((X509KeyManager)km);
         }
 
         // nothing found, return a dummy X509ExtendedKeyManager
@@ -217,9 +229,179 @@
 
 }
 
+
+final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
+            implements X509TrustManager {
+
+    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);
+            }
+
+            AlgorithmChecker checker = new AlgorithmChecker(constraints);
+            try {
+                checker.init(false);
+
+                // a forward checker, need to check from trust to target
+                for (int i = chain.length - 1; 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");
+            }
+        }
+    }
+
+    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);
+            }
+
+            AlgorithmChecker checker = new AlgorithmChecker(constraints);
+            try {
+                checker.init(false);
+
+                // A forward checker, need to check from trust to target
+                for (int i = chain.length - 1; 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 implements X509TrustManager {
+final class DummyX509TrustManager extends X509ExtendedTrustManager
+            implements X509TrustManager {
 
     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
 
@@ -234,6 +416,7 @@
      * 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(
@@ -247,6 +430,7 @@
      * 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(
@@ -257,19 +441,48 @@
      * 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 AbstractWrapper extends X509ExtendedKeyManager {
+final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
 
     private final X509KeyManager km;
 
-    AbstractWrapper(X509KeyManager km) {
+    AbstractKeyManagerWrapper(X509KeyManager km) {
         this.km = km;
     }
 
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -200,8 +200,10 @@
      * is associated with a session at the same time.  (TLS/IETF may
      * change that to add client authentication w/o new key exchg.)
      */
-    private SSLSessionImpl      sess;
-    private Handshaker          handshaker;
+    private Handshaker                  handshaker;
+    private SSLSessionImpl              sess;
+    private volatile SSLSessionImpl     handshakeSession;
+
 
     /*
      * Client authentication be off, requested, or required.
@@ -240,26 +242,30 @@
      * session is changed.
      */
     private byte                        doClientAuth;
-    private CipherSuiteList             enabledCipherSuites;
     private boolean                     enableSessionCreation = true;
     EngineInputRecord                   inputRecord;
     EngineOutputRecord                  outputRecord;
     private AccessControlContext        acc;
 
-    // hostname identification algorithm, the hostname identification is
-    // disabled by default.
-    private String                      identificationAlg = null;
+    // 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 protocols we support are SSL Version 3.0) and
-     * TLS (version 3.1).
-     * In addition we support a pseudo protocol called
-     * SSLv2Hello which when set will result in an SSL v2 Hello
-     * being sent with SSLv3 or TLSv1 version info.
+     * 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;
 
@@ -342,6 +348,7 @@
 
         sslContext = ctx;
         sess = SSLSessionImpl.nullSession;
+        handshakeSession = null;
 
         /*
          * State is cs_START until we initialize the handshaker.
@@ -368,7 +375,7 @@
         serverVerifyData = new byte[0];
 
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(roleIsServer);
 
         wrapLock = new Object();
         unwrapLock = new Object();
@@ -405,8 +412,8 @@
      *  . if the engine is already closed, throw an Exception (internal error)
      *
      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, initialize it, and advance the connection state (to
-     *    cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+     *    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
@@ -454,12 +461,8 @@
                     protocolVersion, connectionState == cs_HANDSHAKE,
                     secureRenegotiation, clientVerifyData, serverVerifyData);
         }
-        handshaker.enabledCipherSuites = enabledCipherSuites;
+        handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
-        if (connectionState == cs_RENEGOTIATE) {
-            // don't use SSLv2Hello when renegotiating
-            handshaker.output.r.setHelloVersion(protocolVersion);
-        }
     }
 
     /*
@@ -686,7 +689,15 @@
         // to its HandshakeOutStream, which calls back into
         // SSLSocketImpl.writeRecord() to send it.
         //
-        if (!handshaker.started()) {
+        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();
@@ -696,6 +707,7 @@
                 } else {
                     // we want to renegotiate, send hello request
                     handshaker.kickstart();
+
                     // hello request is not included in the handshake
                     // hashes, reset them
                     handshaker.handshakeHash.reset();
@@ -982,6 +994,15 @@
                      * 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
@@ -1007,6 +1028,7 @@
                         serverVerifyData = handshaker.getServerVerifyData();
 
                         sess = handshaker.getSession();
+                        handshakeSession = null;
                         if (!writer.hasOutboundData()) {
                             hsStatus = HandshakeStatus.FINISHED;
                         }
@@ -1081,6 +1103,26 @@
                     }
                     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)
         }
 
@@ -1229,7 +1271,29 @@
             EngineArgs ea) throws IOException {
 
         // eventually compress as well.
-        return writer.writeRecord(eor, ea, writeMAC, writeCipher);
+        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);
+            }
+        }
+
+        return hsStatus;
     }
 
     /*
@@ -1238,6 +1302,21 @@
     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());
+        }
     }
 
     //
@@ -1245,6 +1324,67 @@
     //
 
     /**
+     * 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>.
      */
@@ -1394,6 +1534,15 @@
         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>.
@@ -1495,6 +1644,9 @@
         inboundDone = true;
 
         sess.invalidate();
+        if (handshakeSession != null) {
+            handshakeSession.invalidate();
+        }
 
         /*
          * If we haven't even started handshaking yet, no need
@@ -1594,10 +1746,18 @@
      * 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);
 
@@ -1647,7 +1807,7 @@
     synchronized public void setEnableSessionCreation(boolean flag) {
         enableSessionCreation = flag;
 
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnableSessionCreation(enableSessionCreation);
         }
     }
@@ -1675,7 +1835,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -1698,7 +1858,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -1717,6 +1877,16 @@
         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) &&
+                    ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                enabledProtocols = ProtocolList.getDefault(!flag);
+            }
+
             roleIsServer = !flag;
             serverModeSet = true;
             break;
@@ -1730,7 +1900,17 @@
              * have the streams.
              */
             assert(handshaker != null);
-            if (!handshaker.started()) {
+            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) &&
+                        ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                    enabledProtocols = ProtocolList.getDefault(!flag);
+                }
+
                 roleIsServer = !flag;
                 connectionState = cs_START;
                 initHandshaker();
@@ -1786,8 +1966,8 @@
      */
     synchronized public void setEnabledCipherSuites(String[] suites) {
         enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.enabledCipherSuites = enabledCipherSuites;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setEnabledCipherSuites(enabledCipherSuites);
         }
     }
 
@@ -1809,7 +1989,7 @@
     /**
      * Returns the protocols that are supported by this implementation.
      * A subset of the supported protocols may be enabled for this connection
-     * @ returns an array of protocol names.
+     * @return an array of protocol names.
      */
     public String[] getSupportedProtocols() {
         return ProtocolList.getSupported().toStringArray();
@@ -1826,7 +2006,7 @@
      */
     synchronized public void setEnabledProtocols(String[] protocols) {
         enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnabledProtocols(enabledProtocols);
         }
     }
@@ -1836,28 +2016,31 @@
     }
 
     /**
-     * Try to configure the endpoint identification algorithm of the engine.
-     *
-     * @param identificationAlgorithm the algorithm used to check the
-     *          endpoint identity.
-     * @return true if the identification algorithm configuration success.
+     * Returns the SSLParameters in effect for this SSLEngine.
      */
-    synchronized public boolean trySetHostnameVerification(
-        String identificationAlgorithm) {
-        if (sslContext.getX509TrustManager() instanceof
-                X509ExtendedTrustManager) {
-            this.identificationAlg = identificationAlgorithm;
-            return true;
-        } else {
-            return false;
-        }
+    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;
     }
 
     /**
-     * Returns the endpoint identification algorithm of the engine.
+     * Applies SSLParameters to this engine.
      */
-    synchronized public String getHostnameVerification() {
-        return identificationAlg;
+    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);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -31,11 +31,14 @@
 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;
 
 
 /**
@@ -83,6 +86,12 @@
     /* 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.
@@ -145,7 +154,7 @@
         }
         sslContext = context;
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(true);
     }
 
     /**
@@ -238,6 +247,16 @@
      * 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) &&
+                ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+            enabledProtocols = ProtocolList.getDefault(!flag);
+        }
+
         useServerMode = !flag;
     }
 
@@ -262,6 +281,29 @@
         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
@@ -269,67 +311,15 @@
      * presented during construction.
      */
     public Socket accept() throws IOException {
-        checkEnabledSuites();
-
         SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
             enabledCipherSuites, doClientAuth, enableSessionCreation,
-            enabledProtocols);
+            enabledProtocols, identificationProtocol, algorithmConstraints);
 
         implAccept(s);
         s.doneConnect();
         return s;
     }
 
-
-    /*
-     * This is a sometimes helpful diagnostic check that is performed
-     * once for each ServerSocket to verify that the initial set of
-     * enabled suites are capable of supporting a successful handshake.
-     */
-    private void checkEnabledSuites() throws IOException {
-        //
-        // We want to report an error if no cipher suites were actually
-        // enabled, since this is an error users are known to make.  Then
-        // they get vastly confused by having clients report an error!
-        //
-        synchronized (this) {
-            if (checkedEnabled) {
-                return;
-            }
-            if (useServerMode == false) {
-                return;
-            }
-
-            SSLSocketImpl tmp = new SSLSocketImpl(sslContext, useServerMode,
-                         enabledCipherSuites, doClientAuth,
-                         enableSessionCreation, enabledProtocols);
-
-            try {
-                ServerHandshaker handshaker = tmp.getServerHandshaker();
-
-                for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
-                        t.hasNext();) {
-                    CipherSuite suite = t.next();
-                    if (handshaker.trySetCipherSuite(suite)) {
-                        checkedEnabled = true;
-                        return;
-                    }
-                }
-            } finally {
-                tmp.closeSocket();
-            }
-
-            //
-            // diagnostic text here is currently appropriate
-            // since it's only certificate unavailability that can
-            // cause such problems ... but that might change someday.
-            //
-            throw new SSLException("No available certificate or key corresponds"
-                + " to the SSL cipher suites which are enabled.");
-        }
-    }
-
-
     /**
      * Provides a brief description of this SSL socket.
      */
--- a/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -31,6 +31,8 @@
 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;
@@ -47,6 +49,8 @@
 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;
 
@@ -71,7 +75,7 @@
  *
  * @author David Brownell
  */
-final class SSLSessionImpl implements SSLSession {
+final class SSLSessionImpl extends ExtendedSSLSession {
 
     /*
      * we only really need a single null session
@@ -89,7 +93,7 @@
     private final SessionId             sessionId;
     private X509Certificate[]   peerCerts;
     private byte                compressionMethod;
-    private final CipherSuite   cipherSuite;
+    private CipherSuite         cipherSuite;
     private SecretKey           masterSecret;
 
     /*
@@ -105,6 +109,8 @@
     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;
@@ -132,8 +138,8 @@
      * first opened and before handshaking begins.
      */
     private SSLSessionImpl() {
-        this(ProtocolVersion.NONE, CipherSuite.C_NULL,
-             new SessionId(false, null), null, -1);
+        this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
+            new SessionId(false, null), null, -1);
     }
 
     /*
@@ -142,8 +148,9 @@
      * is intended mostly for use by serves.
      */
     SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
+            Collection<SignatureAndHashAlgorithm> algorithms,
             SecureRandom generator, String host, int port) {
-        this(protocolVersion, cipherSuite,
+        this(protocolVersion, cipherSuite, algorithms,
              new SessionId(defaultRejoinable, generator), host, port);
     }
 
@@ -151,6 +158,7 @@
      * 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;
@@ -161,9 +169,11 @@
         this.host = host;
         this.port = port;
         sessionCount = ++counter;
+        localSupportedSignAlgs =
+            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
 
         if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Created:  " + this);
+            System.out.println("%% Initialized:  " + this);
         }
     }
 
@@ -196,6 +206,12 @@
         localPrivateKey = privateKey;
     }
 
+    void setPeerSupportedSignatureAlgorithms(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        peerSupportedSignAlgs =
+            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
+    }
+
     /**
      * Set the peer principal.
      */
@@ -293,6 +309,17 @@
     }
 
     /**
+     * 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() {
@@ -718,6 +745,30 @@
         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
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -32,6 +32,7 @@
 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;
@@ -194,15 +195,27 @@
      */
     private byte                doClientAuth;
     private boolean             roleIsServer;
-    private CipherSuiteList     enabledCipherSuites;
     private boolean             enableSessionCreation = true;
     private String              host;
     private boolean             autoClose = true;
     private AccessControlContext acc;
 
-    // hostname identification algorithm, the hostname identification is
-    // disabled by default.
-    private String              identificationAlg = null;
+    /*
+     * 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 *
@@ -312,8 +325,9 @@
      * is associated with a session at the same time.  (TLS/IETF may
      * change that to add client authentication w/o new key exchg.)
      */
-    private SSLSessionImpl      sess;
-    private Handshaker          handshaker;
+    private Handshaker                  handshaker;
+    private SSLSessionImpl              sess;
+    private volatile SSLSessionImpl     handshakeSession;
 
 
     /*
@@ -341,11 +355,11 @@
     private AppOutputStream     output;
 
     /*
-     * The protocols we support are SSL Version 3.0) and
-     * TLS (version 3.1).
-     * In addition we support a pseudo protocol called
-     * SSLv2Hello which when set will result in an SSL v2 Hello
-     * being sent with SSLv3 or TLSv1 version info.
+     * 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;
 
@@ -374,6 +388,7 @@
             throws IOException, UnknownHostException {
         super();
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         SocketAddress socketAddress =
                host != null ? new InetSocketAddress(host, port) :
@@ -416,6 +431,7 @@
             throws IOException, UnknownHostException {
         super();
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         bind(new InetSocketAddress(localAddr, localPort));
         SocketAddress socketAddress =
@@ -455,11 +471,15 @@
      */
     SSLSocketImpl(SSLContextImpl context, boolean serverMode,
             CipherSuiteList suites, byte clientAuth,
-            boolean sessionCreation, ProtocolList protocols)
-            throws IOException {
+            boolean sessionCreation, ProtocolList protocols,
+            String identificationProtocol,
+            AlgorithmConstraints algorithmConstraints) throws IOException {
+
         super();
         doClientAuth = clientAuth;
         enableSessionCreation = sessionCreation;
+        this.identificationProtocol = identificationProtocol;
+        this.algorithmConstraints = algorithmConstraints;
         init(context, serverMode);
 
         /*
@@ -506,6 +526,7 @@
             throw new SocketException("Underlying socket is not connected");
         }
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         this.autoClose = autoClose;
         doneConnect();
@@ -517,6 +538,7 @@
     private void init(SSLContextImpl context, boolean isServer) {
         sslContext = context;
         sess = SSLSessionImpl.nullSession;
+        handshakeSession = null;
 
         /*
          * role is as specified, state is START until after
@@ -541,7 +563,7 @@
         serverVerifyData = new byte[0];
 
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(roleIsServer);
         inrec = null;
 
         // save the acc
@@ -764,6 +786,21 @@
         r.addMAC(writeMAC);
         r.encrypt(writeCipher);
         r.write(sockOutput);
+
+        /*
+         * 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());
+        }
     }
 
 
@@ -883,6 +920,7 @@
                 }
             }
 
+
             // if (!r.decompress(c))
             //     fatal(Alerts.alert_decompression_failure,
             //         "decompression failure");
@@ -905,6 +943,15 @@
                      * 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
@@ -930,6 +977,7 @@
                         serverVerifyData = handshaker.getServerVerifyData();
 
                         sess = handshaker.getSession();
+                        handshakeSession = null;
                         handshaker = null;
                         connectionState = cs_DATA;
 
@@ -949,9 +997,8 @@
 
                     if (needAppData || connectionState != cs_DATA) {
                         continue;
-                    } else {
-                        return;
                     }
+                    break;
 
                 case Record.ct_application_data:
                     // Pass this right back up to the application.
@@ -971,7 +1018,7 @@
                     }
 
                     r.setAppDataValid(true);
-                    return;
+                    break;
 
                 case Record.ct_alert:
                     recvAlert(r);
@@ -1010,6 +1057,23 @@
                     }
                     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)
         }
 
@@ -1021,6 +1085,61 @@
       }  // 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
     //
@@ -1033,28 +1152,10 @@
     }
 
     /**
-     * Initialize and get the server handshaker. Used by SSLServerSocketImpl
-     * for the ciphersuite availability test *only*.
+     * Return the AppOutputStream. For use by Handshaker only.
      */
-    ServerHandshaker getServerHandshaker() throws SSLException {
-        initHandshaker();
-
-         // The connection state would have been set to cs_HANDSHAKE during the
-         // handshaking initializing, however the caller may not have the
-         // the low level connection's established, which is not consistent with
-         // the HANDSHAKE state. As if it is unconnected, we need to reset the
-         // connection state to cs_START.
-         if (!isConnected()) {
-             connectionState = cs_START;
-         }
-
-         // Make sure that we get a ServerHandshaker.
-         // This should never happen.
-         if (!(handshaker instanceof ServerHandshaker)) {
-             throw new SSLProtocolException("unexpected handshaker instance");
-         }
-
-        return (ServerHandshaker)handshaker;
+    AppOutputStream getAppOutputStream() {
+        return output;
     }
 
     /**
@@ -1066,8 +1167,8 @@
      *  . if the socket is already closed, throw an Exception (internal error)
      *
      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, initialize it, and advance the connection state (to
-     *    cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+     *    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
@@ -1115,12 +1216,8 @@
                     protocolVersion, connectionState == cs_HANDSHAKE,
                     secureRenegotiation, clientVerifyData, serverVerifyData);
         }
-        handshaker.enabledCipherSuites = enabledCipherSuites;
+        handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
-        if (connectionState == cs_RENEGOTIATE) {
-            // don't use SSLv2Hello when renegotiating
-            handshaker.output.r.setHelloVersion(protocolVersion);
-        }
     }
 
     /**
@@ -1135,6 +1232,8 @@
         // 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.
@@ -1157,7 +1256,6 @@
                     inrec.enableFormatChecks();
                 }
 
-                kickstartHandshake();
                 readRecord(inrec, false);
                 inrec = null;
             }
@@ -1211,6 +1309,7 @@
      *    on servers when renegotiating).
      */
     private synchronized void kickstartHandshake() throws IOException {
+
         switch (connectionState) {
 
         case cs_HANDSHAKE:
@@ -1257,7 +1356,15 @@
         // to its HandshakeOutStream, which calls back into
         // SSLSocketImpl.writeRecord() to send it.
         //
-        if (!handshaker.started()) {
+        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();
@@ -1646,6 +1753,9 @@
             input.r.close();
         }
         sess.invalidate();
+        if (handshakeSession != null) {
+            handshakeSession.invalidate();
+        }
 
         int oldState = connectionState;
         connectionState = cs_ERROR;
@@ -1752,10 +1862,18 @@
      * 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);
 
@@ -1878,9 +1996,14 @@
         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;
     }
 
     /**
@@ -1951,6 +2074,15 @@
         }
     }
 
+    @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.
@@ -1962,7 +2094,7 @@
     synchronized public void setEnableSessionCreation(boolean flag) {
         enableSessionCreation = flag;
 
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnableSessionCreation(enableSessionCreation);
         }
     }
@@ -1990,7 +2122,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -2013,7 +2145,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -2032,6 +2164,15 @@
         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) &&
+                    ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                enabledProtocols = ProtocolList.getDefault(!flag);
+            }
             roleIsServer = !flag;
             break;
 
@@ -2044,7 +2185,16 @@
              * have the streams.
              */
             assert(handshaker != null);
-            if (!handshaker.started()) {
+            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) &&
+                        ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                    enabledProtocols = ProtocolList.getDefault(!flag);
+                }
                 roleIsServer = !flag;
                 connectionState = cs_START;
                 initHandshaker();
@@ -2095,8 +2245,8 @@
      */
     synchronized public void setEnabledCipherSuites(String[] suites) {
         enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.enabledCipherSuites = enabledCipherSuites;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setEnabledCipherSuites(enabledCipherSuites);
         }
     }
 
@@ -2118,7 +2268,7 @@
     /**
      * Returns the protocols that are supported by this implementation.
      * A subset of the supported protocols may be enabled for this connection
-     * @ returns an array of protocol names.
+     * @return an array of protocol names.
      */
     public String[] getSupportedProtocols() {
         return ProtocolList.getSupported().toStringArray();
@@ -2135,7 +2285,7 @@
      */
     synchronized public void setEnabledProtocols(String[] protocols) {
         enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnabledProtocols(enabledProtocols);
         }
     }
@@ -2194,28 +2344,31 @@
     }
 
     /**
-     * Try to configure the endpoint identification algorithm of the socket.
-     *
-     * @param identificationAlgorithm the algorithm used to check the
-     *        endpoint identity.
-     * @return true if the identification algorithm configuration success.
+     * Returns the SSLParameters in effect for this SSLSocket.
      */
-    synchronized public boolean trySetHostnameVerification(
-        String identificationAlgorithm) {
-        if (sslContext.getX509TrustManager() instanceof
-                X509ExtendedTrustManager) {
-            this.identificationAlg = identificationAlgorithm;
-            return true;
-        } else {
-            return false;
-        }
+    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;
     }
 
     /**
-     * Returns the endpoint identification algorithm of the socket.
+     * Applies SSLParameters to this socket.
      */
-    synchronized public String getHostnameVerification() {
-        return identificationAlg;
+    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);
+        }
     }
 
     //
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java	Tue Nov 09 22:53:18 2010 -0800
@@ -40,10 +40,9 @@
 
 import javax.security.auth.Subject;
 
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 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.*;
 
@@ -92,6 +91,9 @@
 
     private SupportedEllipticCurvesExtension supportedCurves;
 
+    // the preferable signature algorithm used by ServerKeyExchange message
+    SignatureAndHashAlgorithm preferableSignatureAlgorithm;
+
     /*
      * Constructor ... use the keys found in the auth context.
      */
@@ -185,8 +187,10 @@
                      * temporary one used for non-export or signing-only
                      * certificates/keys.
                      */
-                    RSAClientKeyExchange pms = new RSAClientKeyExchange
-                        (protocolVersion, input, message_len, privateKey);
+                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
+                            protocolVersion, clientRequestedVersion,
+                            sslContext.getSecureRandom(), input,
+                            message_len, privateKey);
                     preMasterSecret = this.clientKeyExchange(pms);
                     break;
                 case K_KRB5:
@@ -231,11 +235,13 @@
                 break;
 
             case HandshakeMessage.ht_certificate_verify:
-                this.clientCertificateVerify(new CertificateVerify(input));
+                this.clientCertificateVerify(new CertificateVerify(input,
+                            localSupportedSignAlgs, protocolVersion));
                 break;
 
             case HandshakeMessage.ht_finished:
-                this.clientFinished(new Finished(protocolVersion, input));
+                this.clientFinished(
+                    new Finished(protocolVersion, input, cipherSuite));
                 break;
 
             default:
@@ -408,21 +414,18 @@
 
         clientRequestedVersion = mesg.protocolVersion;
 
-        // check if clientVersion is recent enough for us
-        if (clientRequestedVersion.v < enabledProtocols.min.v) {
+        // 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");
+                " not enabled or not supported");
         }
 
-        // now we know we have an acceptable version
-        // use the lower of our max and the client requested version
-        ProtocolVersion selectedVersion;
-        if (clientRequestedVersion.v <= enabledProtocols.max.v) {
-            selectedVersion = clientRequestedVersion;
-        } else {
-            selectedVersion = enabledProtocols.max;
-        }
+        handshakeHash.protocolDetermined(
+            selectedVersion.v >= ProtocolVersion.TLS12.v);
         setVersion(selectedVersion);
 
         m1.protocolVersion = protocolVersion;
@@ -566,14 +569,71 @@
             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 = new SSLSessionImpl(protocolVersion, cipherSuite,
-                sslContext.getSecureRandom(),
-                getHostAddressSE(), getPortSE());
+
+            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;
@@ -693,14 +753,16 @@
                     privateKey,
                     clnt_random.random_bytes,
                     svr_random.random_bytes,
-                    sslContext.getSecureRandom());
+                    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);
+            m3 = new DH_ServerKeyExchange(dh, protocolVersion);
             break;
         case K_ECDHE_RSA:
         case K_ECDHE_ECDSA:
@@ -710,9 +772,12 @@
                     privateKey,
                     clnt_random.random_bytes,
                     svr_random.random_bytes,
-                    sslContext.getSecureRandom());
+                    sslContext.getSecureRandom(),
+                    preferableSignatureAlgorithm,
+                    protocolVersion);
             } catch (GeneralSecurityException e) {
-                throwSSLException("Error generating ECDH server key exchange", e);
+                throwSSLException(
+                    "Error generating ECDH server key exchange", e);
                 m3 = null; // make compiler happy
             }
             break;
@@ -741,21 +806,48 @@
         // Needed only if server requires client to authenticate self.
         // Illegal for anonymous flavors, so we need to check that.
         //
-        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-            // CertificateRequest is omitted for Kerberos ciphers
+        // 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) {
 
-        } else if (doClientAuth != SSLEngineImpl.clauth_none &&
-                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON) {
             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);
+            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);
+            }
         }
 
         /*
@@ -813,8 +905,7 @@
      * method should only be called if you really want to use the
      * CipherSuite.
      *
-     * This method is called from chooseCipherSuite() in this class
-     * and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
+     * This method is called from chooseCipherSuite() in this class.
      */
     boolean trySetCipherSuite(CipherSuite suite) {
         /*
@@ -831,6 +922,16 @@
             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
@@ -840,36 +941,136 @@
         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:
-        case K_DHE_RSA:
-        case K_ECDHE_RSA:
             // need RSA certs for authentication
             if (setupPrivateKeyAndChain("RSA") == false) {
                 return false;
             }
 
-            if (keyExchange == K_RSA_EXPORT) {
-                try {
-                   if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                        if (!setupEphemeralRSAKeys(suite.exportable)) {
-                            return false;
-                        }
-                   }
-                } catch (RuntimeException e) {
-                    // could not determine keylength, ignore key
+            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:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                                supportedSignAlgs, "RSA");
+                if (preferableSignatureAlgorithm == null) {
                     return false;
                 }
-            } else if (keyExchange == K_DHE_RSA) {
-                setupEphemeralDHKeys(suite.exportable);
-            } else if (keyExchange == K_ECDHE_RSA) {
-                if (setupEphemeralECDHKeys() == false) {
+            }
+
+            // need RSA certs for authentication
+            if (setupPrivateKeyAndChain("RSA") == false) {
+                return false;
+            }
+            setupEphemeralDHKeys(suite.exportable);
+            break;
+        case K_ECDHE_RSA:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                                supportedSignAlgs, "RSA");
+                if (preferableSignatureAlgorithm == null) {
                     return false;
                 }
-            } // else nothing more to do for K_RSA
+            }
+
+            // need RSA certs for authentication
+            if (setupPrivateKeyAndChain("RSA") == false) {
+                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;
@@ -877,6 +1078,16 @@
             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;
@@ -921,6 +1132,14 @@
             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;
     }
 
@@ -1170,6 +1389,24 @@
             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();
@@ -1225,8 +1462,8 @@
          * Verify the client's message with the "before" digest of messages,
          * and forget about continuing to use that digest.
          */
-        boolean verified = mesg.verify(protocolVersion, handshakeHash,
-                                Finished.CLIENT, session.getMasterSecret());
+        boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
+            session.getMasterSecret());
 
         if (!verified) {
             fatalSE(Alerts.alert_handshake_failure,
@@ -1281,7 +1518,7 @@
         output.flush();
 
         Finished mesg = new Finished(protocolVersion, handshakeHash,
-                                Finished.SERVER, session.getMasterSecret());
+            Finished.SERVER, session.getMasterSecret(), cipherSuite);
 
         /*
          * Send the change_cipher_spec record; then our Finished handshake
@@ -1351,7 +1588,8 @@
      * 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 {
+    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
+            throws IOException {
 
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
@@ -1379,6 +1617,11 @@
              * 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,
@@ -1405,26 +1648,23 @@
                 authType = "UNKNOWN";
             }
 
-            String identificator = getHostnameVerificationSE();
             if (tm instanceof X509ExtendedTrustManager) {
-                ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        (peerCerts != null ?
-                            peerCerts.clone() :
-                            null),
+                if (conn != null) {
+                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
+                        peerCerts.clone(),
                         authType,
-                        getHostSE(),
-                        identificator);
+                        conn);
+                } else {
+                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
+                        peerCerts.clone(),
+                        authType,
+                        engine);
+                }
             } else {
-                if (identificator != null) {
-                    throw new RuntimeException(
-                        "trust manager does not support peer identification");
-                }
-
-                tm.checkClientTrusted(
-                    (peerCerts != null ?
-                        peerCerts.clone() :
-                        peerCerts),
-                    authType);
+                // 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 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.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+
+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;
+
+/**
+ * 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<SignatureAndHashAlgorithm>();
+        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<SignatureAndHashAlgorithm>();
+        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<String>();
+        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<String>();
+        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) {
+
+        if (expected == null && !algorithms.isEmpty()) {
+            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
+                if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
+                    return sigAlg;
+                }
+            }
+
+            return null;  // no supported algorithm
+        }
+
+
+        for (SignatureAndHashAlgorithm algorithm : algorithms) {
+            int signValue = algorithm.id & 0xFF;
+            if ((expected.equalsIgnoreCase("dsa") &&
+                    signValue == SignatureAlgorithm.DSA.value) ||
+                (expected.equalsIgnoreCase("rsa") &&
+                    signValue == SignatureAlgorithm.RSA.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),
+        NONE(          "none",    "NONE",  0),
+        MD5(            "md5",     "MD5",  1),
+        SHA1(          "sha1",   "SHA-1",  2),
+        SHA224(      "sha224", "SHA-224",  3),
+        SHA256(      "sha256", "SHA-256",  4),
+        SHA384(      "sha384", "SHA-384",  5),
+        SHA512(      "sha512", "SHA-512",  6);
+
+        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;
+
+        private HashAlgorithm(String name, String standardName, int value) {
+            this.name = name;
+            this.standardName = standardName;
+            this.value = value;
+        }
+
+        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);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -38,7 +38,7 @@
  *
  * 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
+ *  . allow only TLS 1.0 or later
  *  . allow only FIPS approved ciphersuites
  *  . perform all crypto in the FIPS crypto provider
  *
@@ -129,7 +129,8 @@
         return t;
     }
 
-    private SunJSSE(java.security.Provider cryptoProvider, String providerName) {
+    private SunJSSE(java.security.Provider cryptoProvider,
+            String providerName) {
         super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
         subclassCheck();
         if (cryptoProvider == null) {
@@ -211,6 +212,10 @@
             "sun.security.ssl.SSLContextImpl");
         put("SSLContext.TLSv1",
             "sun.security.ssl.SSLContextImpl");
+        put("SSLContext.TLSv1.1",
+            "sun.security.ssl.SSLContextImpl");
+        put("SSLContext.TLSv1.2",
+            "sun.security.ssl.SSLContextImpl");
         put("SSLContext.Default",
             "sun.security.ssl.DefaultSSLContextImpl");
 
--- a/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -38,6 +38,8 @@
 
 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:
@@ -111,36 +113,98 @@
 
     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
             Socket socket) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT);
+        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);
+        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);
+        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);
+        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
+                        getAlgorithmConstraints(engine));
     }
 
     public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.CLIENT);
+        return getAliases(keyType, issuers, CheckType.CLIENT, null);
     }
 
     public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.SERVER);
+        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()
@@ -196,6 +260,13 @@
     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) {
@@ -218,7 +289,8 @@
             }
             if (chain.length > 1) {
                 // if possible, check the public key in the issuer cert
-                return sigKeyAlgorithm.equals(chain[1].getPublicKey().getAlgorithm());
+                return sigKeyAlgorithm.equals(
+                        chain[1].getPublicKey().getAlgorithm());
             } else {
                 // Check the signature algorithm of the certificate itself.
                 // Look for the "withRSA" in "SHA1withRSA", etc.
@@ -231,7 +303,8 @@
     }
 
     private static List<KeyType> getKeyTypes(String ... keyTypes) {
-        if ((keyTypes == null) || (keyTypes.length == 0) || (keyTypes[0] == null)) {
+        if ((keyTypes == null) ||
+                (keyTypes.length == 0) || (keyTypes[0] == null)) {
             return null;
         }
         List<KeyType> list = new ArrayList<KeyType>(keyTypes.length);
@@ -254,8 +327,8 @@
      *     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) {
+    private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
+            CheckType checkType, AlgorithmConstraints constraints) {
         if (keyTypeList == null || keyTypeList.size() == 0) {
             return null;
         }
@@ -264,8 +337,8 @@
         List<EntryStatus> allResults = null;
         for (int i = 0, n = builders.size(); i < n; i++) {
             try {
-                List<EntryStatus> results =
-                    getAliases(i, keyTypeList, issuerSet, false, checkType);
+                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
@@ -308,7 +381,7 @@
      * The perfect matches will be first in the array.
      */
     public String[] getAliases(String keyType, Principal[] issuers,
-            CheckType checkType) {
+            CheckType checkType, AlgorithmConstraints constraints) {
         if (keyType == null) {
             return null;
         }
@@ -318,8 +391,8 @@
         List<EntryStatus> allResults = null;
         for (int i = 0, n = builders.size(); i < n; i++) {
             try {
-                List<EntryStatus> results =
-                        getAliases(i, keyTypeList, issuerSet, true, checkType);
+                List<EntryStatus> results = getAliases(i, keyTypeList,
+                                    issuerSet, true, checkType, constraints);
                 if (results != null) {
                     if (allResults == null) {
                         allResults = new ArrayList<EntryStatus>();
@@ -438,7 +511,8 @@
             try {
                 // check extended key usage
                 List<String> certEku = cert.getExtendedKeyUsage();
-                if ((certEku != null) && Collections.disjoint(validEku, certEku)) {
+                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;
@@ -534,7 +608,8 @@
      */
     private List<EntryStatus> getAliases(int builderIndex,
             List<KeyType> keyTypes, Set<Principal> issuerSet,
-            boolean findAll, CheckType checkType) throws Exception {
+            boolean findAll, CheckType checkType,
+            AlgorithmConstraints constraints) throws Exception {
         Builder builder = builders.get(builderIndex);
         KeyStore ks = builder.getKeyStore();
         List<EntryStatus> results = null;
@@ -552,6 +627,19 @@
                 // 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;
@@ -573,10 +661,6 @@
             if (issuerSet != null) {
                 boolean found = false;
                 for (Certificate cert : chain) {
-                    if (cert instanceof X509Certificate == false) {
-                        // not an X509Certificate, ignore this entry
-                        break;
-                    }
                     X509Certificate xcert = (X509Certificate)cert;
                     if (issuerSet.contains(xcert.getIssuerX500Principal())) {
                         found = true;
@@ -591,6 +675,19 @@
                     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();
             }
@@ -616,4 +713,29 @@
         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;
+    }
+
 }
--- a/jdk/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,14 +26,15 @@
 
 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 com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 import sun.security.validator.*;
 
 import sun.security.util.HostnameChecker;
@@ -41,7 +42,7 @@
 /**
  * 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
@@ -50,19 +51,10 @@
  * classes.
  *
  * @author Andreas Sterbenz
- * @author Xuelei Fan
  */
 final class X509TrustManagerImpl extends X509ExtendedTrustManager
         implements X509TrustManager {
 
-    /**
-     * Flag indicating whether to enable revocation check for the PKIX trust
-     * manager. Typically, this will only work if the PKIX implementation
-     * supports CRL distribution points as we do not manually setup CertStores.
-     */
-    private final static boolean checkRevocation =
-        Debug.getBooleanProperty("com.sun.net.ssl.checkRevocation", false);
-
     private final String validatorType;
 
     /**
@@ -103,6 +95,199 @@
         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) {
@@ -127,13 +312,6 @@
         Validator v;
         if (pkixParams == null) {
             v = Validator.getInstance(validatorType, variant, trustedCerts);
-            // if the PKIX validator is created from a KeyStore,
-            // disable revocation checking
-            if (v instanceof PKIXValidator) {
-                PKIXValidator pkixValidator = (PKIXValidator)v;
-                pkixValidator.getParameters().setRevocationEnabled
-                                                            (checkRevocation);
-            }
         } else {
             v = Validator.getInstance(validatorType, variant, pkixParams);
         }
@@ -141,150 +319,35 @@
     }
 
     private static X509Certificate[] validate(Validator v,
-            X509Certificate[] chain, String authType) throws CertificateException {
+            X509Certificate[] chain, AlgorithmConstraints constraints,
+            String authType) throws CertificateException {
         Object o = JsseJce.beginFipsProvider();
         try {
-            return v.validate(chain, null, authType);
+            return v.validate(chain, null, constraints, authType);
         } finally {
             JsseJce.endFipsProvider(o);
         }
     }
 
-    /**
-     * Returns true if the client certificate can be trusted.
+    /*
+     * Identify the peer by its certificate and hostname.
      *
-     * @param chain certificates which establish an identity for the client.
-     *      Chains of arbitrary length are supported, and certificates
-     *      marked internally as trusted will short-circuit signature checks.
-     * @throws IllegalArgumentException if null or zero-length chain
-     *         is passed in for the chain parameter or if null or zero-length
-     *         string is passed in for the authType parameter.
-     * @throws CertificateException if the certificate chain is not trusted
-     *      by this TrustManager.
-     */
-    public void checkClientTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        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");
-        }
-
-        // assume double checked locking with a volatile flag works
-        // (guaranteed under the new Tiger memory model)
-        Validator v = clientValidator;
-        if (v == null) {
-            synchronized (this) {
-                v = clientValidator;
-                if (v == null) {
-                    v = getValidator(Validator.VAR_TLS_CLIENT);
-                    clientValidator = v;
-                }
-            }
-        }
-        X509Certificate[] trustedChain = validate(v, chain, null);
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    /**
-     * Returns true if the server certifcate can be trusted.
-     *
-     * @param chain certificates which establish an identity for the server.
-     *      Chains of arbitrary length are supported, and certificates
-     *      marked internally as trusted will short-circuit signature checks.
-     * @throws IllegalArgumentException if null or zero-length chain
-     *         is passed in for the chain parameter or if null or zero-length
-     *         string is passed in for the authType parameter.
-     * @throws CertificateException if the certificate chain is not trusted
-     *      by this TrustManager.
+     * Lifted from sun.net.www.protocol.https.HttpsClient.
      */
-    public void checkServerTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        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");
-        }
-
-        // assume double checked locking with a volatile flag works
-        // (guaranteed under the new Tiger memory model)
-        Validator v = serverValidator;
-        if (v == null) {
-            synchronized (this) {
-                v = serverValidator;
-                if (v == null) {
-                    v = getValidator(Validator.VAR_TLS_SERVER);
-                    serverValidator = v;
-                }
-            }
-        }
-        X509Certificate[] trustedChain = validate(v, chain, authType);
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    /**
-     * Returns a list of CAs accepted to authenticate entities for the
-     * specified purpose.
-     *
-     * @param purpose activity for which CAs should be trusted
-     * @return list of CAs accepted for authenticating such tasks
-     */
-    public X509Certificate[] getAcceptedIssuers() {
-        X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
-        trustedCerts.toArray(certsArray);
-        return certsArray;
-    }
-
-    /**
-     * Given the partial or complete certificate chain provided by the
-     * peer, check its identity and build a certificate path to a trusted
-     * root, return if it can be validated and is trusted for client SSL
-     * authentication based on the authentication type.
-     */
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-        String hostname, String algorithm) throws CertificateException {
-        checkClientTrusted(chain, authType);
-        checkIdentity(hostname, chain[0], algorithm);
-    }
-
-    /**
-     * Given the partial or complete certificate chain provided by the
-     * peer, check its identity and build a certificate path to a trusted
-     * root, return if it can be validated and is trusted for server SSL
-     * authentication based on the authentication type.
-     */
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-        String hostname, String algorithm) throws CertificateException {
-        checkServerTrusted(chain, authType);
-        checkIdentity(hostname, chain[0], algorithm);
-    }
-
-    // Identify the peer by its certificate and hostname.
-    private void checkIdentity(String hostname, X509Certificate cert,
-        String algorithm) throws CertificateException {
+    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 ((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")) {
+            } else if (algorithm.equalsIgnoreCase("LDAP") ||
+                    algorithm.equalsIgnoreCase("LDAPS")) {
                 HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP).match(
                         hostname, cert);
             } else {
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -244,7 +244,7 @@
                 clientVersion, rand, input, sessionKey);
         } else {
             // Generate bogus premaster secret
-            preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
+            preMaster = new KerberosPreMasterSecret(clientVersion, rand);
         }
     }
 
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Tue Nov 09 22:53:18 2010 -0800
@@ -176,13 +176,21 @@
         // 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
+        // old 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 in
         // the second case, which is why we cannot use object references
         // equality in this special case
-        boolean versionMismatch = (protocolVersion != currentVersion) &&
-                                  (protocolVersion.v != clientVersion.v);
+        boolean versionMismatch = (protocolVersion.v != clientVersion.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 && (clientVersion.v <= 0x0301)) {
+            versionMismatch = (protocolVersion.v != currentVersion.v);
+        }
 
         /*
          * Bogus decrypted ClientKeyExchange? If so, conjure a
@@ -203,8 +211,14 @@
                     Debug.println(System.out, "Invalid secret", preMaster);
                 }
             }
-            preMaster = generatePreMaster(generator, currentVersion);
-            protocolVersion = currentVersion;
+
+            /*
+             * Randomize the preMaster secret with the
+             * ClientHello.client_version, as will produce invalid master
+             * secret to prevent the attacks.
+             */
+            preMaster = generatePreMaster(generator, clientVersion);
+            protocolVersion = clientVersion;
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 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.util;
+
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AlgorithmParameters;
+
+import java.security.Key;
+import java.security.Security;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.DSAKey;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHKey;
+
+import java.util.Locale;
+import java.util.Set;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Algorithm constraints for disabled algorithms property
+ *
+ * See the "jdk.certpath.disabledAlgorithms" specification in java.security
+ * for the syntax of the disabled algorithm string.
+ */
+public class DisabledAlgorithmConstraints implements AlgorithmConstraints {
+
+    // the known security property, jdk.certpath.disabledAlgorithms
+    public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
+            "jdk.certpath.disabledAlgorithms";
+
+    // the known security property, jdk.tls.disabledAlgorithms
+    public final static String PROPERTY_TLS_DISABLED_ALGS =
+            "jdk.tls.disabledAlgorithms";
+
+    private static Map<String, String[]> disabledAlgorithmsMap =
+            Collections.synchronizedMap(new HashMap<String, String[]>());
+    private static Map<String, KeySizeConstraints> keySizeConstraintsMap =
+        Collections.synchronizedMap(new HashMap<String, KeySizeConstraints>());
+
+    private String[] disabledAlgorithms;
+    private KeySizeConstraints keySizeConstraints;
+
+    /**
+     * Initialize algorithm constraints with the specified security property.
+     *
+     * @param propertyName the security property name that define the disabled
+     *        algorithm constraints
+     */
+    public DisabledAlgorithmConstraints(String propertyName) {
+        synchronized (disabledAlgorithmsMap) {
+            if(!disabledAlgorithmsMap.containsKey(propertyName)) {
+                loadDisabledAlgorithmsMap(propertyName);
+            }
+
+            disabledAlgorithms = disabledAlgorithmsMap.get(propertyName);
+            keySizeConstraints = keySizeConstraintsMap.get(propertyName);
+        }
+    }
+
+    @Override
+    final 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");
+        }
+
+        Set<String> elements = null;
+        for (String disabled : disabledAlgorithms) {
+            if (disabled == null || disabled.isEmpty()) {
+                continue;
+            }
+
+            // check the full name
+            if (disabled.equalsIgnoreCase(algorithm)) {
+                return false;
+            }
+
+            // decompose the algorithm into sub-elements
+            if (elements == null) {
+                elements = decomposes(algorithm);
+            }
+
+            // check the items of the algorithm
+            for (String element : elements) {
+                if (disabled.equalsIgnoreCase(element)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
+        return checkConstraints(primitives, "", key, null);
+    }
+
+    @Override
+    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 checkConstraints(primitives, algorithm, key, parameters);
+    }
+
+    /**
+     * Decompose the standard algorithm name into sub-elements.
+     * <p>
+     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+     * so that we can check the "SHA1" and "RSA" algorithm constraints
+     * separately.
+     * <p>
+     * Please override the method if need to support more name pattern.
+     */
+    protected Set<String> decomposes(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<String>();
+        }
+
+        // algorithm/mode/padding
+        Pattern transPattern = Pattern.compile("/");
+        String[] transTockens = transPattern.split(algorithm);
+
+        Set<String> elements = new HashSet<String>();
+        for (String transTocken : transTockens) {
+            if (transTocken == null || transTocken.length() == 0) {
+                continue;
+            }
+
+            // PBEWith<digest>And<encryption>
+            // PBEWith<prf>And<encryption>
+            // OAEPWith<digest>And<mgf>Padding
+            // <digest>with<encryption>
+            // <digest>with<encryption>and<mgf>
+            Pattern pattern =
+                    Pattern.compile("with|and", Pattern.CASE_INSENSITIVE);
+            String[] tokens = pattern.split(transTocken);
+
+            for (String token : tokens) {
+                if (token == null || token.length() == 0) {
+                    continue;
+                }
+
+                elements.add(token);
+            }
+        }
+
+        // In Java standard algorithm name specification, for different
+        // purpose, the SHA-1 and SHA-2 algorithm names are different. For
+        // example, for MessageDigest, the standard name is "SHA-256", while
+        // for Signature, the digest algorithm component is "SHA256" for
+        // signature algorithm "SHA256withRSA". So we need to check both
+        // "SHA-256" and "SHA256" to make the right constraint checking.
+
+        // handle special name: SHA-1 and SHA1
+        if (elements.contains("SHA1") && !elements.contains("SHA-1")) {
+            elements.add("SHA-1");
+        }
+        if (elements.contains("SHA-1") && !elements.contains("SHA1")) {
+            elements.add("SHA1");
+        }
+
+        // handle special name: SHA-224 and SHA224
+        if (elements.contains("SHA224") && !elements.contains("SHA-224")) {
+            elements.add("SHA-224");
+        }
+        if (elements.contains("SHA-224") && !elements.contains("SHA224")) {
+            elements.add("SHA224");
+        }
+
+        // handle special name: SHA-256 and SHA256
+        if (elements.contains("SHA256") && !elements.contains("SHA-256")) {
+            elements.add("SHA-256");
+        }
+        if (elements.contains("SHA-256") && !elements.contains("SHA256")) {
+            elements.add("SHA256");
+        }
+
+        // handle special name: SHA-384 and SHA384
+        if (elements.contains("SHA384") && !elements.contains("SHA-384")) {
+            elements.add("SHA-384");
+        }
+        if (elements.contains("SHA-384") && !elements.contains("SHA384")) {
+            elements.add("SHA384");
+        }
+
+        // handle special name: SHA-512 and SHA512
+        if (elements.contains("SHA512") && !elements.contains("SHA-512")) {
+            elements.add("SHA-512");
+        }
+        if (elements.contains("SHA-512") && !elements.contains("SHA512")) {
+            elements.add("SHA512");
+        }
+
+        return elements;
+    }
+
+    // Check algorithm constraints
+    private boolean checkConstraints(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        // check the key parameter, it cannot be null.
+        if (key == null) {
+            throw new IllegalArgumentException("The key cannot be null");
+        }
+
+        // check the target algorithm
+        if (algorithm != null && algorithm.length() != 0) {
+            if (!permits(primitives, algorithm, parameters)) {
+                return false;
+            }
+        }
+
+        // check the key algorithm
+        if (!permits(primitives, key.getAlgorithm(), null)) {
+            return false;
+        }
+
+        // check the key constraints
+        if (keySizeConstraints.disables(key)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // Get disabled algorithm constraints from the specified security property.
+    private static void loadDisabledAlgorithmsMap(
+            final String propertyName) {
+
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(propertyName);
+                }
+            });
+
+        String[] algorithmsInProperty = null;
+
+        if (property != null && !property.isEmpty()) {
+
+            // remove double quote marks from beginning/end of the property
+            if (property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+
+            algorithmsInProperty = property.split(",");
+            for (int i = 0; i < algorithmsInProperty.length; i++) {
+                algorithmsInProperty[i] = algorithmsInProperty[i].trim();
+            }
+        }
+
+        // map the disabled algorithms
+        if (algorithmsInProperty == null) {
+            algorithmsInProperty = new String[0];
+        }
+        disabledAlgorithmsMap.put(propertyName, algorithmsInProperty);
+
+        // map the key constraints
+        KeySizeConstraints keySizeConstraints =
+            new KeySizeConstraints(algorithmsInProperty);
+        keySizeConstraintsMap.put(propertyName, keySizeConstraints);
+    }
+
+    /**
+     * key constraints
+     */
+    private static class KeySizeConstraints {
+        private static final Pattern pattern = Pattern.compile(
+                "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
+
+        private Map<String, Set<KeySizeConstraint>> constraintsMap =
+            Collections.synchronizedMap(
+                        new HashMap<String, Set<KeySizeConstraint>>());
+
+        public KeySizeConstraints(String[] restrictions) {
+            for (String restriction : restrictions) {
+                if (restriction == null || restriction.isEmpty()) {
+                    continue;
+                }
+
+                Matcher matcher = pattern.matcher(restriction);
+                if (matcher.matches()) {
+                    String algorithm = matcher.group(1);
+
+                    KeySizeConstraint.Operator operator =
+                             KeySizeConstraint.Operator.of(matcher.group(2));
+                    int length = Integer.parseInt(matcher.group(3));
+
+                    algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+
+                    synchronized (constraintsMap) {
+                        if (!constraintsMap.containsKey(algorithm)) {
+                            constraintsMap.put(algorithm,
+                                new HashSet<KeySizeConstraint>());
+                        }
+
+                        Set<KeySizeConstraint> constraintSet =
+                            constraintsMap.get(algorithm);
+                        KeySizeConstraint constraint =
+                            new KeySizeConstraint(operator, length);
+                        constraintSet.add(constraint);
+                    }
+                }
+            }
+        }
+
+        // Does this KeySizeConstraints disable the specified key?
+        public boolean disables(Key key) {
+            String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
+            synchronized (constraintsMap) {
+                if (constraintsMap.containsKey(algorithm)) {
+                    Set<KeySizeConstraint> constraintSet =
+                                        constraintsMap.get(algorithm);
+                    for (KeySizeConstraint constraint : constraintSet) {
+                        if (constraint.disables(key)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+
+    /**
+     * Key size constraint.
+     *
+     * e.g.  "keysize <= 1024"
+     */
+    private static class KeySizeConstraint {
+        // operator
+        static enum Operator {
+            EQ,         // "=="
+            NE,         // "!="
+            LT,         // "<"
+            LE,         // "<="
+            GT,         // ">"
+            GE;         // ">="
+
+            static Operator of(String s) {
+                switch (s) {
+                    case "==":
+                        return EQ;
+                    case "!=":
+                        return NE;
+                    case "<":
+                        return LT;
+                    case "<=":
+                        return LE;
+                    case ">":
+                        return GT;
+                    case ">=":
+                        return GE;
+                }
+
+                throw new IllegalArgumentException(
+                        s + " is not a legal Operator");
+            }
+        }
+
+        private int minSize;            // the minimal available key size
+        private int maxSize;            // the maximal available key size
+        private int prohibitedSize = -1;    // unavailable key sizes
+
+        public KeySizeConstraint(Operator operator, int length) {
+            switch (operator) {
+                case EQ:      // an unavailable key size
+                    this.minSize = 0;
+                    this.maxSize = Integer.MAX_VALUE;
+                    prohibitedSize = length;
+                    break;
+                case NE:
+                    this.minSize = length;
+                    this.maxSize = length;
+                    break;
+                case LT:
+                    this.minSize = length;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case LE:
+                    this.minSize = length + 1;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case GT:
+                    this.minSize = 0;
+                    this.maxSize = length;
+                    break;
+                case GE:
+                    this.minSize = 0;
+                    this.maxSize = length > 1 ? (length - 1) : 0;
+                    break;
+                default:
+                    // unlikely to happen
+                    this.minSize = Integer.MAX_VALUE;
+                    this.maxSize = -1;
+            }
+        }
+
+        // Does this key constraint disable the specified key?
+        public boolean disables(Key key) {
+            int size = -1;
+
+            // it is a SecretKey
+            if (key instanceof SecretKey) {
+                SecretKey sk = (SecretKey)key;
+                if (sk.getFormat().equals("RAW") && sk.getEncoded() != null) {
+                    size = sk.getEncoded().length * 8;
+
+                }
+            }
+
+            // it is an asymmetric key
+            if (key instanceof RSAKey) {
+                RSAKey pubk = (RSAKey)key;
+                size = pubk.getModulus().bitLength();
+            } else if (key instanceof ECKey) {
+                ECKey pubk = (ECKey)key;
+                size = pubk.getParams().getOrder().bitLength();
+            } else if (key instanceof DSAKey) {
+                DSAKey pubk = (DSAKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } else if (key instanceof DHKey) {
+                DHKey pubk = (DHKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } // else, it is not a key we know.
+
+            if (size == 0) {
+                return true;    // we don't allow any key of size 0.
+            }
+
+            if (size >= 0) {
+                return ((size < minSize) || (size > maxSize) ||
+                    (prohibitedSize == size));
+            }
+
+            return false;
+        }
+    }
+
+}
+
--- a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -31,20 +31,35 @@
 import java.security.cert.*;
 
 import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanAction;
+import sun.security.provider.certpath.AlgorithmChecker;
 
 /**
  * Validator implementation built on the PKIX CertPath API. This
  * implementation will be emphasized going forward.<p>
- *
+ * <p>
  * Note that the validate() implementation tries to use a PKIX validator
  * if that appears possible and a PKIX builder otherwise. This increases
  * performance and currently also leads to better exception messages
  * in case of failures.
+ * <p>
+ * {@code PKIXValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
 public final class PKIXValidator extends Validator {
 
+    /**
+     * Flag indicating whether to enable revocation check for the PKIX trust
+     * manager. Typically, this will only work if the PKIX implementation
+     * supports CRL distribution points as we do not manually setup CertStores.
+     */
+    private final static boolean checkTLSRevocation =
+        AccessController.doPrivileged
+            (new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
+
     // enable use of the validator if possible
     private final static boolean TRY_VALIDATOR = true;
 
@@ -53,10 +68,10 @@
     private int certPathLength = -1;
 
     // needed only for the validator
-    private Map<X500Principal, List<PublicKey>> trustedSubjects;
-    private CertificateFactory factory;
+    private final Map<X500Principal, List<PublicKey>> trustedSubjects;
+    private final CertificateFactory factory;
 
-    private boolean plugin = false;
+    private final boolean plugin;
 
     PKIXValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_PKIX, variant);
@@ -75,7 +90,33 @@
             throw new RuntimeException("Unexpected error: " + e.toString(), e);
         }
         setDefaultParameters(variant);
-        initCommon();
+
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
+        }
     }
 
     PKIXValidator(String variant, PKIXBuilderParameters params) {
@@ -88,31 +129,33 @@
             }
         }
         parameterTemplate = params;
-        initCommon();
-    }
 
-    private void initCommon() {
-        if (TRY_VALIDATOR == false) {
-            return;
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
         }
-        trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
-        for (X509Certificate cert : trustedCerts) {
-            X500Principal dn = cert.getSubjectX500Principal();
-            List<PublicKey> keys;
-            if (trustedSubjects.containsKey(dn)) {
-                keys = trustedSubjects.get(dn);
-            } else {
-                keys = new ArrayList<PublicKey>();
-                trustedSubjects.put(dn, keys);
-            }
-            keys.add(cert.getPublicKey());
-        }
-        try {
-            factory = CertificateFactory.getInstance("X.509");
-        } catch (CertificateException e) {
-            throw new RuntimeException("Internal error", e);
-        }
-        plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
     }
 
     public Collection<X509Certificate> getTrustedCertificates() {
@@ -129,7 +172,7 @@
      * @return the length of the last certification path passed to
      *   CertPathValidator.validate, or -1 if it has not been invoked yet
      */
-    public int getCertPathLength() {
+    public int getCertPathLength() { // mutable, should be private
         return certPathLength;
     }
 
@@ -138,7 +181,12 @@
      * revocation checking. In the future, this should be configurable.
      */
     private void setDefaultParameters(String variant) {
-        parameterTemplate.setRevocationEnabled(false);
+        if ((variant == Validator.VAR_TLS_SERVER) ||
+                (variant == Validator.VAR_TLS_CLIENT)) {
+            parameterTemplate.setRevocationEnabled(checkTLSRevocation);
+        } else {
+            parameterTemplate.setRevocationEnabled(false);
+        }
     }
 
     /**
@@ -146,17 +194,29 @@
      * modify the parameters but must make sure not to perform any concurrent
      * validations.
      */
-    public PKIXBuilderParameters getParameters() {
+    public PKIXBuilderParameters getParameters() { // mutable, should be private
         return parameterTemplate;
     }
 
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
         }
+
+        // add  new algorithm constraints checker
+        PKIXBuilderParameters pkixParameters =
+                    (PKIXBuilderParameters) parameterTemplate.clone();
+        AlgorithmChecker algorithmChecker = null;
+        if (constraints != null) {
+            algorithmChecker = new AlgorithmChecker(constraints);
+            pkixParameters.addCertPathChecker(algorithmChecker);
+        }
+
         if (TRY_VALIDATOR) {
             // check that chain is in correct order and check if chain contains
             // trust anchor
@@ -167,7 +227,7 @@
                 if (i != 0 &&
                     !dn.equals(prevIssuer)) {
                     // chain is not ordered correctly, call builder instead
-                    return doBuild(chain, otherCerts);
+                    return doBuild(chain, otherCerts, pkixParameters);
                 }
 
                 // Check if chain[i] is already trusted. It may be inside
@@ -186,7 +246,7 @@
                     // Remove and call validator on partial chain [0 .. i-1]
                     X509Certificate[] newChain = new X509Certificate[i];
                     System.arraycopy(chain, 0, newChain, 0, i);
-                    return doValidate(newChain);
+                    return doValidate(newChain, pkixParameters);
                 }
                 prevIssuer = cert.getIssuerX500Principal();
             }
@@ -197,7 +257,7 @@
             X500Principal subject = last.getSubjectX500Principal();
             if (trustedSubjects.containsKey(issuer) &&
                     isSignatureValid(trustedSubjects.get(issuer), last)) {
-                return doValidate(chain);
+                return doValidate(chain, pkixParameters);
             }
 
             // don't fallback to builder if called from plugin/webstart
@@ -209,18 +269,17 @@
                     X509Certificate[] newChain =
                         new X509Certificate[chain.length-1];
                     System.arraycopy(chain, 0, newChain, 0, newChain.length);
+
                     // temporarily set last cert as sole trust anchor
-                    PKIXBuilderParameters params =
-                        (PKIXBuilderParameters) parameterTemplate.clone();
                     try {
-                        params.setTrustAnchors
+                        pkixParameters.setTrustAnchors
                             (Collections.singleton(new TrustAnchor
                                 (chain[chain.length-1], null)));
                     } catch (InvalidAlgorithmParameterException iape) {
                         // should never occur, but ...
                         throw new CertificateException(iape);
                     }
-                    doValidate(newChain, params);
+                    doValidate(newChain, pkixParameters);
                 }
                 // if the rest of the chain is valid, throw exception
                 // indicating no trust anchor was found
@@ -230,10 +289,11 @@
             // otherwise, fall back to builder
         }
 
-        return doBuild(chain, otherCerts);
+        return doBuild(chain, otherCerts, pkixParameters);
     }
 
-    private boolean isSignatureValid(List<PublicKey> keys, X509Certificate sub) {
+    private boolean isSignatureValid(List<PublicKey> keys,
+            X509Certificate sub) {
         if (plugin) {
             for (PublicKey key: keys) {
                 try {
@@ -273,13 +333,6 @@
         }
     }
 
-    private X509Certificate[] doValidate(X509Certificate[] chain)
-            throws CertificateException {
-        PKIXBuilderParameters params =
-            (PKIXBuilderParameters)parameterTemplate.clone();
-        return doValidate(chain, params);
-    }
-
     private X509Certificate[] doValidate(X509Certificate[] chain,
             PKIXBuilderParameters params) throws CertificateException {
         try {
@@ -300,11 +353,10 @@
     }
 
     private X509Certificate[] doBuild(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts) throws CertificateException {
+        Collection<X509Certificate> otherCerts,
+        PKIXBuilderParameters params) throws CertificateException {
 
         try {
-            PKIXBuilderParameters params =
-                (PKIXBuilderParameters)parameterTemplate.clone();
             setDate(params);
 
             // setup target constraints
--- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -48,6 +48,10 @@
  * deployed certificates and previous J2SE versions. It will never support
  * more advanced features and will be deemphasized in favor of the PKIX
  * validator going forward.
+ * <p>
+ * {@code SimpleValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
@@ -80,13 +84,14 @@
      * The list is used because there may be multiple certificates
      * with an identical subject DN.
      */
-    private Map<X500Principal, List<X509Certificate>> trustedX500Principals;
+    private final Map<X500Principal, List<X509Certificate>>
+                                            trustedX500Principals;
 
     /**
      * Set of the trusted certificates. Present only for
      * getTrustedCertificates().
      */
-    private Collection<X509Certificate> trustedCerts;
+    private final Collection<X509Certificate> trustedCerts;
 
     SimpleValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_SIMPLE, variant);
@@ -114,9 +119,11 @@
      * Perform simple validation of chain. The arguments otherCerts and
      * parameter are ignored.
      */
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
@@ -129,6 +136,17 @@
         if (date == null) {
             date = new Date();
         }
+
+        // create default algorithm constraints checker
+        TrustAnchor anchor = new TrustAnchor(chain[chain.length - 1], null);
+        AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor);
+
+        // create application level algorithm constraints checker
+        AlgorithmChecker appAlgChecker = null;
+        if (constraints != null) {
+            appAlgChecker = new AlgorithmChecker(anchor, constraints);
+        }
+
         // verify top down, starting at the certificate issued by
         // the trust anchor
         int maxPathLength = chain.length - 1;
@@ -138,7 +156,12 @@
 
             // check certificate algorithm
             try {
-                AlgorithmChecker.check(cert);
+                // Algorithm checker don't care about the unresolved critical
+                // extensions.
+                defaultAlgChecker.check(cert, Collections.<String>emptySet());
+                if (appAlgChecker != null) {
+                    appAlgChecker.check(cert, Collections.<String>emptySet());
+                }
             } catch (CertPathValidatorException cpve) {
                 throw new ValidatorException
                         (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
--- a/jdk/src/share/classes/sun/security/validator/Validator.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/validator/Validator.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,6 +27,7 @@
 
 import java.util.*;
 
+import java.security.AlgorithmConstraints;
 import java.security.KeyStore;
 import java.security.cert.*;
 
@@ -232,16 +233,44 @@
     public final X509Certificate[] validate(X509Certificate[] chain,
             Collection<X509Certificate> otherCerts, Object parameter)
             throws CertificateException {
-        chain = engineValidate(chain, otherCerts, parameter);
+        return validate(chain, otherCerts, null, parameter);
+    }
+
+    /**
+     * Validate the given certificate chain.
+     *
+     * @param chain the target certificate chain
+     * @param otherCerts a Collection of additional X509Certificates that
+     *        could be helpful for path building (or null)
+     * @param constraints algorithm constraints for certification path
+     *        processing
+     * @param parameter an additional parameter with variant specific meaning.
+     *        Currently, it is only defined for TLS_SERVER variant validators,
+     *        where it must be non null and the name of the TLS key exchange
+     *        algorithm being used (see JSSE X509TrustManager specification).
+     *        In the future, it could be used to pass in a PKCS#7 object for
+     *        code signing to check time stamps.
+     * @return a non-empty chain that was used to validate the path. The
+     *        end entity cert is at index 0, the trust anchor at index n-1.
+     */
+    public final X509Certificate[] validate(X509Certificate[] chain,
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException {
+        chain = engineValidate(chain, otherCerts, constraints, parameter);
+
         // omit EE extension check if EE cert is also trust anchor
         if (chain.length > 1) {
             endEntityChecker.check(chain[0], parameter);
         }
+
         return chain;
     }
 
     abstract X509Certificate[] engineValidate(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts, Object parameter) throws CertificateException;
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException;
 
     /**
      * Returns an immutable Collection of the X509Certificates this instance
--- a/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -764,6 +764,15 @@
     }
 
     /**
+     * Gets the signature AlgorithmId from the CRL.
+     *
+     * @return the signature AlgorithmId
+     */
+    public AlgorithmId getSigAlgId() {
+        return sigAlgId;
+    }
+
+    /**
      * return the AuthorityKeyIdentifier, if any.
      *
      * @returns AuthorityKeyIdentifier or null
--- a/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Tue Nov 09 22:53:18 2010 -0800
@@ -535,10 +535,6 @@
         }
 
         void doLog(int level, String msg, Object... params) {
-            int paramsNumber = (params != null) ? params.length : 0;
-            for (int i = 0; i < paramsNumber; i++) {
-                params[i] = String.valueOf(params[i]);
-            }
             LoggingSupport.log(javaLogger, levelObjects.get(level), msg, params);
         }
 
--- a/jdk/src/share/classes/sun/util/resources/LocaleNames.properties	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/classes/sun/util/resources/LocaleNames.properties	Tue Nov 09 22:53:18 2010 -0800
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
@@ -21,7 +21,7 @@
 # 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.
-# 
+#
 
 # (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
 # (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
@@ -228,6 +228,492 @@
 zh=Chinese
 zu=Zulu
 
+# key is ISO 639.2 language code
+aar=Afar
+abk=Abkhazian
+ace=Achinese
+ach=Acoli
+ada=Adangme
+ady=Adyghe
+afa=Afro-Asiatic
+afh=Afrihili
+afr=Afrikaans
+ain=Ainu
+aka=Akan
+akk=Akkadian
+alb=Albanian
+ale=Aleut
+alg=Algonquian
+alt=Southern Altai
+amh=Amharic
+ang=English, Old (ca.450-1100)
+anp=Angika
+apa=Apache
+ara=Arabic
+arc=Official Aramaic (700-300 BCE)
+arg=Aragonese
+arm=Armenian
+arn=Mapudungun
+arp=Arapaho
+art=Artificial
+arw=Arawak
+asm=Assamese
+ast=Asturian
+ath=Athapascan
+aus=Australian
+ava=Avaric
+ave=Avestan
+awa=Awadhi
+aym=Aymara
+aze=Azerbaijani
+bad=Banda
+bai=Bamileke
+bak=Bashkir
+bal=Baluchi
+bam=Bambara
+ban=Balinese
+baq=Basque
+bas=Basa
+bat=Baltic
+bej=Beja
+bel=Belarusian
+bem=Bemba
+ben=Bengali
+ber=Berber
+bho=Bhojpuri
+bih=Bihari
+bik=Bikol
+bin=Bini
+bis=Bislama
+bla=Siksika
+bnt=Bantu
+bos=Bosnian
+bra=Braj
+bre=Breton
+btk=Batak
+bua=Buriat
+bug=Buginese
+bul=Bulgarian
+bur=Burmese
+byn=Blin
+cad=Caddo
+cai=Central American Indian
+car=Galibi Carib
+cat=Catalan
+cau=Caucasian
+ceb=Cebuano
+cel=Celtic
+cha=Chamorro
+chb=Chibcha
+che=Chechen
+chg=Chagatai
+chi=Chinese
+chk=Chuukese
+chm=Mari
+chn=Chinook jargon
+cho=Choctaw
+chp=Chipewyan
+chr=Cherokee
+chu=Church Slavic
+chv=Chuvash
+chy=Cheyenne
+cmc=Chamic
+cop=Coptic
+cor=Cornish
+cos=Corsican
+cpe=Creoles and pidgins, English based
+cpf=Creoles and pidgins, French-based
+cpp=Creoles and pidgins, Portuguese-based
+cre=Cree
+crh=Crimean Tatar
+crp=Creoles and pidgins
+csb=Kashubian
+cus=Cushitic
+cze=Czech
+dak=Dakota
+dan=Danish
+dar=Dargwa
+day=Land Dayak
+del=Delaware
+den=Slave (Athapascan)
+dgr=Dogrib
+din=Dinka
+div=Divehi
+doi=Dogri
+dra=Dravidian
+dsb=Lower Sorbian
+dua=Duala
+dum=Dutch, Middle (ca.1050-1350)
+dut=Dutch
+dyu=Dyula
+dzo=Dzongkha
+efi=Efik
+egy=Egyptian (Ancient)
+eka=Ekajuk
+elx=Elamite
+eng=English
+enm=English, Middle (1100-1500)
+epo=Esperanto
+est=Estonian
+ewe=Ewe
+ewo=Ewondo
+fan=Fang
+fao=Faroese
+fat=Fanti
+fij=Fijian
+fil=Filipino
+fin=Finnish
+fiu=Finno-Ugrian
+fon=Fon
+fre=French
+frm=French, Middle (ca.1400-1600)
+fro=French, Old (842-ca.1400)
+frr=Northern Frisian
+frs=Eastern Frisian
+fry=Western Frisian
+ful=Fulah
+fur=Friulian
+gaa=Ga
+gay=Gayo
+gba=Gbaya
+gem=Germanic
+geo=Georgian
+ger=German
+gez=Geez
+gil=Gilbertese
+gla=Gaelic
+gle=Irish
+glg=Galician
+glv=Manx
+gmh=German, Middle High (ca.1050-1500)
+goh=German, Old High (ca.750-1050)
+gon=Gondi
+gor=Gorontalo
+got=Gothic
+grb=Grebo
+grc=Greek, Ancient (to 1453)
+gre=Greek, Modern (1453-)
+grn=Guarani
+gsw=Swiss German
+guj=Gujarati
+gwi=Gwich'in
+hai=Haida
+hat=Haitian
+hau=Hausa
+haw=Hawaiian
+heb=Hebrew
+her=Herero
+hil=Hiligaynon
+him=Himachali
+hin=Hindi
+hit=Hittite
+hmn=Hmong
+hmo=Hiri Motu
+hrv=Croatian
+hsb=Upper Sorbian
+hun=Hungarian
+hup=Hupa
+iba=Iban
+ibo=Igbo
+ice=Icelandic
+ido=Ido
+iii=Sichuan Yi
+ijo=Ijo
+iku=Inuktitut
+ile=Interlingue
+ilo=Iloko
+ina=Interlingua (International Auxiliary Language Association)
+inc=Indic
+ind=Indonesian
+ine=Indo-European
+inh=Ingush
+ipk=Inupiaq
+ira=Iranian
+iro=Iroquoian
+ita=Italian
+jav=Javanese
+jbo=Lojban
+jpn=Japanese
+jpr=Judeo-Persian
+jrb=Judeo-Arabic
+kaa=Kara-Kalpak
+kab=Kabyle
+kac=Kachin
+kal=Kalaallisut
+kam=Kamba
+kan=Kannada
+kar=Karen
+kas=Kashmiri
+kau=Kanuri
+kaw=Kawi
+kaz=Kazakh
+kbd=Kabardian
+kha=Khasi
+khi=Khoisan
+khm=Central Khmer
+kho=Khotanese
+kik=Kikuyu
+kin=Kinyarwanda
+kir=Kirghiz
+kmb=Kimbundu
+kok=Konkani
+kom=Komi
+kon=Kongo
+kor=Korean
+kos=Kosraean
+kpe=Kpelle
+krc=Karachay-Balkar
+krl=Karelian
+kro=Kru
+kru=Kurukh
+kua=Kuanyama
+kum=Kumyk
+kur=Kurdish
+kut=Kutenai
+lad=Ladino
+lah=Lahnda
+lam=Lamba
+lao=Lao
+lat=Latin
+lav=Latvian
+lez=Lezghian
+lim=Limburgan
+lin=Lingala
+lit=Lithuanian
+lol=Mongo
+loz=Lozi
+ltz=Luxembourgish
+lua=Luba-Lulua
+lub=Luba-Katanga
+lug=Ganda
+lui=Luiseno
+lun=Lunda
+luo=Luo (Kenya and Tanzania)
+lus=Lushai
+mac=Macedonian
+mad=Madurese
+mag=Magahi
+mah=Marshallese
+mai=Maithili
+mak=Makasar
+mal=Malayalam
+man=Mandingo
+mao=Maori
+map=Austronesian
+mar=Marathi
+mas=Masai
+may=Malay
+mdf=Moksha
+mdr=Mandar
+men=Mende
+mga=Irish, Middle (900-1200)
+mic=Mi'kmaq
+min=Minangkabau
+mis=Uncoded
+mkh=Mon-Khmer
+mlg=Malagasy
+mlt=Maltese
+mnc=Manchu
+mni=Manipuri
+mno=Manobo
+moh=Mohawk
+mon=Mongolian
+mos=Mossi
+mul=Multiple
+mun=Munda
+mus=Creek
+mwl=Mirandese
+mwr=Marwari
+myn=Mayan
+myv=Erzya
+nah=Nahuatl
+nai=North American Indian
+nap=Neapolitan
+nau=Nauru
+nav=Navajo
+nbl=Ndebele, South
+nde=Ndebele, North
+ndo=Ndonga
+nds=Low German
+nep=Nepali
+new=Nepal Bhasa
+nia=Nias
+nic=Niger-Kordofanian
+niu=Niuean
+nno=Norwegian Nynorsk
+nob=Bokm\u00e5l, Norwegian
+nog=Nogai
+non=Norse, Old
+nor=Norwegian
+nqo=N'Ko
+nso=Pedi
+nub=Nubian
+nwc=Classical Newari
+nya=Chichewa
+nym=Nyamwezi
+nyn=Nyankole
+nyo=Nyoro
+nzi=Nzima
+oci=Occitan (post 1500)
+oji=Ojibwa
+ori=Oriya
+orm=Oromo
+osa=Osage
+oss=Ossetian
+ota=Turkish, Ottoman (1500-1928)
+oto=Otomian
+paa=Papuan
+pag=Pangasinan
+pal=Pahlavi
+pam=Pampanga
+pan=Panjabi
+pap=Papiamento
+pau=Palauan
+peo=Persian, Old (ca.600-400 B.C.)
+per=Persian
+phi=Philippine
+phn=Phoenician
+pli=Pali
+pol=Polish
+pon=Pohnpeian
+por=Portuguese
+pra=Prakrit
+pro=Proven\u00e7al, Old (to 1500)
+pus=Pushto; Pashto
+que=Quechua
+raj=Rajasthani
+rap=Rapanui
+rar=Rarotongan
+roa=Romance
+roh=Romansh
+rom=Romany
+rum=Romanian
+run=Rundi
+rup=Aromanian
+rus=Russian
+sad=Sandawe
+sag=Sango
+sah=Yakut
+sai=South American Indian
+sal=Salishan
+sam=Samaritan Aramaic
+san=Sanskrit
+sas=Sasak
+sat=Santali
+scn=Sicilian
+sco=Scots
+sel=Selkup
+sem=Semitic
+sga=Irish, Old (to 900)
+sgn=Sign
+shn=Shan
+sid=Sidamo
+sin=Sinhala
+sio=Siouan
+sit=Sino-Tibetan
+sla=Slavic
+slo=Slovak
+slv=Slovenian
+sma=Southern Sami
+sme=Northern Sami
+smi=Sami
+smj=Lule Sami
+smn=Inari Sami
+smo=Samoan
+sms=Skolt Sami
+sna=Shona
+snd=Sindhi
+snk=Soninke
+sog=Sogdian
+som=Somali
+son=Songhai
+sot=Sotho, Southern
+spa=Spanish
+srd=Sardinian
+srn=Sranan Tongo
+srp=Serbian
+srr=Serer
+ssa=Nilo-Saharan
+ssw=Swati
+suk=Sukuma
+sun=Sundanese
+sus=Susu
+sux=Sumerian
+swa=Swahili
+swe=Swedish
+syc=Classical Syriac
+syr=Syriac
+tah=Tahitian
+tai=Tai
+tam=Tamil
+tat=Tatar
+tel=Telugu
+tem=Timne
+ter=Tereno
+tet=Tetum
+tgk=Tajik
+tgl=Tagalog
+tha=Thai
+tib=Tibetan
+tig=Tigre
+tir=Tigrinya
+tiv=Tiv
+tkl=Tokelau
+tlh=Klingon
+tli=Tlingit
+tmh=Tamashek
+tog=Tonga (Nyasa)
+ton=Tonga (Tonga Islands)
+tpi=Tok Pisin
+tsi=Tsimshian
+tsn=Tswana
+tso=Tsonga
+tuk=Turkmen
+tum=Tumbuka
+tup=Tupi
+tur=Turkish
+tut=Altaic
+tvl=Tuvalu
+twi=Twi
+tyv=Tuvinian
+udm=Udmurt
+uga=Ugaritic
+uig=Uighur
+ukr=Ukrainian
+umb=Umbundu
+und=Undetermined
+urd=Urdu
+uzb=Uzbek
+vai=Vai
+ven=Venda
+vie=Vietnamese
+vol=Volap\u00fck
+vot=Votic
+wak=Wakashan
+wal=Wolaitta
+war=Waray
+was=Washo
+wel=Welsh
+wen=Sorbian
+wln=Walloon
+wol=Wolof
+xal=Kalmyk
+xho=Xhosa
+yao=Yao
+yap=Yapese
+yid=Yiddish
+yor=Yoruba
+ypk=Yupik
+zap=Zapotec
+zbl=Blissymbols
+zen=Zenaga
+zha=Zhuang
+znd=Zande
+zul=Zulu
+zun=Zuni
+zxx=No linguistic content
+zza=Zaza
+
 # script names
 # key is ISO 15924 script code
 
--- a/jdk/src/share/lib/security/java.security	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/lib/security/java.security	Tue Nov 09 22:53:18 2010 -0800
@@ -282,3 +282,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/lib/security/java.security-solaris	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/lib/security/java.security-solaris	Tue Nov 09 22:53:18 2010 -0800
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -119,11 +119,6 @@
 keystore.type=jks
 
 #
-# Class to instantiate as the system scope:
-#
-system.scope=sun.security.provider.IdentityDatabase
-
-#
 # List of comma-separated packages that start with or equal this string
 # will cause a security exception to be thrown when
 # passed to checkPackageAccess unless the
@@ -150,7 +145,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +160,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +179,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +188,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +197,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +209,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +233,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +255,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +283,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+i
--- a/jdk/src/share/lib/security/java.security-windows	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/lib/security/java.security-windows	Tue Nov 09 22:53:18 2010 -0800
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -119,11 +119,6 @@
 keystore.type=jks
 
 #
-# Class to instantiate as the system scope:
-#
-system.scope=sun.security.provider.IdentityDatabase
-
-#
 # List of comma-separated packages that start with or equal this string
 # will cause a security exception to be thrown when
 # passed to checkPackageAccess unless the
@@ -150,7 +145,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +160,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +179,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +188,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +197,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +209,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +233,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +255,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +283,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/native/common/jdk_util.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/native/common/jdk_util.c	Tue Nov 09 22:53:18 2010 -0800
@@ -25,6 +25,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
+#include <assert.h>
 
 #include "jvm.h"
 #include "jdk_util.h"
@@ -45,6 +47,7 @@
         (unsigned int) atoi(JDK_MICRO_VERSION);
 
     const char* jdk_build_string = JDK_BUILD_NUMBER;
+    char build_number[4];
     unsigned int jdk_build_number = 0;
 
     const char* jdk_update_string = JDK_UPDATE_VERSION;
@@ -55,16 +58,28 @@
     /* If the JDK_BUILD_NUMBER is of format bXX and XX is an integer
      * XX is the jdk_build_number.
      */
-    if (strlen(jdk_build_string) == 3) {
-        if (jdk_build_string[0] == 'b' &&
-            jdk_build_string[1] >= '0' && jdk_build_string[1] <= '9' &&
-            jdk_build_string[2] >= '0' && jdk_build_string[2] <= '9') {
-            jdk_build_number = (unsigned int) atoi(&jdk_build_string[1]);
+    int len = strlen(jdk_build_string);
+    if (jdk_build_string[0] == 'b' && len >= 2) {
+        int i = 0;
+        for (i = 1; i < len; i++) {
+            if (isdigit(jdk_build_string[i])) {
+                build_number[i-1] = jdk_build_string[i];
+            } else {
+                // invalid build number
+                i = -1;
+                break;
+            }
+        }
+        if (i == len) {
+            build_number[len-1] = '\0';
+            jdk_build_number = (unsigned int) atoi(build_number) ;
         }
     }
+
+    assert(jdk_build_number >= 0 && jdk_build_number <= 255);
+
     if (strlen(jdk_update_string) == 2 || strlen(jdk_update_string) == 3) {
-        if (jdk_update_string[0] >= '0' && jdk_update_string[0] <= '9' &&
-            jdk_update_string[1] >= '0' && jdk_update_string[1] <= '9') {
+        if (isdigit(jdk_update_string[0]) && isdigit(jdk_update_string[1])) {
             update_ver[0] = jdk_update_string[0];
             update_ver[1] = jdk_update_string[1];
             update_ver[2] = '\0';
@@ -75,7 +90,6 @@
         }
     }
 
-
     memset(info, 0, info_size);
     info->jdk_version = ((jdk_major_version & 0xFF) << 24) |
                         ((jdk_minor_version & 0xFF) << 16) |
--- a/jdk/src/share/native/java/lang/System.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/native/java/lang/System.c	Tue Nov 09 22:53:18 2010 -0800
@@ -219,11 +219,14 @@
 
     /*
      *  user.language
-     *  user.country, user.variant (if user's environment specifies them)
+     *  user.script, user.country, user.variant (if user's environment specifies them)
      *  file.encoding
      *  file.encoding.pkg
      */
     PUTPROP(props, "user.language", sprops->language);
+    if (sprops->script) {
+        PUTPROP(props, "user.script", sprops->script);
+    }
     if (sprops->country) {
         PUTPROP(props, "user.country", sprops->country);
     }
@@ -305,11 +308,12 @@
     }
 
     /*
-     * unset "user.language", "user.country", and "user.variant"
+     * unset "user.language", "user.script", "user.country", and "user.variant"
      * in order to tell whether the command line option "-DXXXX=YYYY" is
      * specified or not.  They will be reset in fillI18nProps() below.
      */
     REMOVEPROP(props, "user.language");
+    REMOVEPROP(props, "user.script");
     REMOVEPROP(props, "user.country");
     REMOVEPROP(props, "user.variant");
     REMOVEPROP(props, "file.encoding");
@@ -328,6 +332,8 @@
     /* reconstruct i18n related properties */
     fillI18nProps(env, props, "user.language", sprops->display_language,
         sprops->format_language, putID, getPropID);
+    fillI18nProps(env, props, "user.script",
+        sprops->display_script, sprops->format_script, putID, getPropID);
     fillI18nProps(env, props, "user.country",
         sprops->display_country, sprops->format_country, putID, getPropID);
     fillI18nProps(env, props, "user.variant",
--- a/jdk/src/share/native/java/lang/java_props.h	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/native/java/lang/java_props.h	Tue Nov 09 22:53:18 2010 -0800
@@ -55,6 +55,9 @@
     char *language;
     char *format_language;
     char *display_language;
+    char *script;
+    char *format_script;
+    char *display_script;
     char *country;
     char *format_country;
     char *display_country;
--- a/jdk/src/share/native/java/util/zip/zlib-1.2.3/zcrc32.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/native/java/util/zip/zlib-1.2.3/zcrc32.c	Tue Nov 09 22:53:18 2010 -0800
@@ -406,7 +406,7 @@
         return crc1;
 
     /* put operator for one zero bit in odd */
-    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    odd[0] = 0xedb88320UL;           /* CRC-32 polynomial */
     row = 1;
     for (n = 1; n < GF2_DIM; n++) {
         odd[n] = row;
--- a/jdk/src/share/native/sun/java2d/loops/ProcessPath.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/share/native/sun/java2d/loops/ProcessPath.c	Tue Nov 09 22:53:18 2010 -0800
@@ -116,14 +116,26 @@
         jint Y0 = (fY0) >> MDP_PREC;                                        \
         jint X1 = (fX1) >> MDP_PREC;                                        \
         jint Y1 = (fY1) >> MDP_PREC;                                        \
-        /* Handling lines having just one pixel                           */\
+        jint res;                                                           \
+                                                                            \
+        /* Checking bounds and clipping if necessary */                     \
+        if (checkBounds) {                                                  \
+            TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y0, X0, Y1, X1,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y1, X1, Y0, X0,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X0, Y0, X1, Y1,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X1, Y1, X0, Y0,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+        }                                                                   \
+                                                                            \
+        /* Handling lines having just one pixel      */                     \
         if (((X0^X1) | (Y0^Y1)) == 0) {                                     \
-            if (checkBounds &&                                              \
-                (hnd->dhnd->yMin > Y0  ||                                   \
-                 hnd->dhnd->yMax <= Y0 ||                                   \
-                 hnd->dhnd->xMin > X0  ||                                   \
-                 hnd->dhnd->xMax <= X0)) break;                             \
-                                                                            \
             if (pixelInfo[0] == 0) {                                        \
                 pixelInfo[0] = 1;                                           \
                 pixelInfo[1] = X0;                                          \
@@ -140,18 +152,11 @@
             break;                                                          \
         }                                                                   \
                                                                             \
-        if (!checkBounds ||                                                 \
-            (hnd->dhnd->yMin <= Y0  &&                                      \
-             hnd->dhnd->yMax > Y0 &&                                        \
-             hnd->dhnd->xMin <= X0  &&                                      \
-             hnd->dhnd->xMax > X0))                                         \
+        if (pixelInfo[0] &&                                                 \
+            ((pixelInfo[1] == X0 && pixelInfo[2] == Y0) ||                  \
+            (pixelInfo[3] == X0 && pixelInfo[4] == Y0)))                    \
         {                                                                   \
-                if (pixelInfo[0] &&                                         \
-                    ((pixelInfo[1] == X0 && pixelInfo[2] == Y0) ||          \
-                     (pixelInfo[3] == X0 && pixelInfo[4] == Y0)))           \
-                {                                                           \
-                    hnd->dhnd->pDrawPixel(hnd->dhnd, X0, Y0);               \
-                }                                                           \
+            hnd->dhnd->pDrawPixel(hnd->dhnd, X0, Y0);                       \
         }                                                                   \
                                                                             \
         hnd->dhnd->pDrawLine(hnd->dhnd, X0, Y0, X1, Y1);                    \
@@ -170,14 +175,6 @@
         if ((pixelInfo[1] == X1 && pixelInfo[2] == Y1) ||                   \
             (pixelInfo[3] == X1 && pixelInfo[4] == Y1))                     \
         {                                                                   \
-            if (checkBounds &&                                              \
-                (hnd->dhnd->yMin > Y1  ||                                   \
-                 hnd->dhnd->yMax <= Y1 ||                                   \
-                 hnd->dhnd->xMin > X1  ||                                   \
-                 hnd->dhnd->xMax <= X1)) {                                  \
-                break;                                                      \
-            }                                                               \
-                                                                            \
             hnd->dhnd->pDrawPixel(hnd->dhnd, X1, Y1);                       \
         }                                                                   \
         pixelInfo[3] = X1;                                                  \
--- a/jdk/src/solaris/bin/java_md.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/bin/java_md.c	Tue Nov 09 22:53:18 2010 -0800
@@ -868,7 +868,7 @@
     while (dp != NULL) {
         cp = JLI_StrChr(dp, (int)':');
         if (cp != NULL)
-            *cp = (char)NULL;
+            *cp = '\0';
         if ((target = ProcessDir(info, dp)) != NULL)
             break;
         dp = cp;
--- a/jdk/src/solaris/bin/jexec.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/bin/jexec.c	Tue Nov 09 22:53:18 2010 -0800
@@ -221,6 +221,7 @@
      * implies an error in the exec. */
     free(nargv);
     errorExit(errno, BAD_EXEC_MSG);
+    return 0; // keep the compiler happy
 }
 
 
--- a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -94,6 +94,12 @@
         preClose0(fd);
     }
 
+    FileDescriptor duplicateForMapping(FileDescriptor fd) {
+        // file descriptor not required for mapping operations; okay
+        // to return invalid file descriptor.
+        return new FileDescriptor();
+    }
+
     // -- Native methods --
 
     static native int read0(FileDescriptor fd, long address, int len)
--- a/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class LinuxAsynchronousChannelProvider
@@ -88,12 +87,4 @@
     {
         return new UnixAsynchronousSocketChannelImpl(toPort(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toPort(group));
-    }
 }
--- a/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class SolarisAsynchronousChannelProvider
@@ -91,12 +90,4 @@
     {
         return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toEventPort(group));
-    }
 }
--- a/jdk/src/solaris/native/java/lang/java_props_md.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/native/java/lang/java_props_md.c	Tue Nov 09 22:53:18 2010 -0800
@@ -117,7 +117,8 @@
 #define P_tmpdir "/var/tmp"
 #endif
 
-static int ParseLocale(int cat, char ** std_language, char ** std_country, char ** std_variant, char ** std_encoding) {
+static int ParseLocale(int cat, char ** std_language, char ** std_script,
+                       char ** std_country, char ** std_variant, char ** std_encoding) {
     char temp[64];
     char *language = NULL, *country = NULL, *variant = NULL,
          *encoding = NULL;
@@ -181,14 +182,22 @@
         strcpy(encoding_variant, p); /* Copy the leading '.' */
         *p = '\0';
     } else if ((p = strchr(temp, '@')) != NULL) {
-         strcpy(encoding_variant, p); /* Copy the leading '@' */
-         *p = '\0';
+        strcpy(encoding_variant, p); /* Copy the leading '@' */
+        *p = '\0';
     } else {
         *encoding_variant = '\0';
     }
 
     if (mapLookup(locale_aliases, temp, &p)) {
         strcpy(temp, p);
+        // check the "encoding_variant" again, if any.
+        if ((p = strchr(temp, '.')) != NULL) {
+            strcpy(encoding_variant, p); /* Copy the leading '.' */
+            *p = '\0';
+        } else if ((p = strchr(temp, '@')) != NULL) {
+            strcpy(encoding_variant, p); /* Copy the leading '@' */
+            *p = '\0';
+        }
     }
 
     language = temp;
@@ -219,10 +228,17 @@
         mapLookup(country_names, country, std_country);
     }
 
-    /* Normalize the variant name.  Note that we only use
-     * variants listed in the mapping array; others are ignored. */
-    if (std_variant != NULL && variant != NULL) {
-        mapLookup(variant_names, variant, std_variant);
+    /* Normalize the script and variant name.  Note that we only use
+     * variants listed in the mapping array; others are ignored.
+     */
+    if (variant != NULL) {
+        if (std_script != NULL) {
+            mapLookup(script_names, variant, std_script);
+        }
+
+        if (std_variant != NULL) {
+            mapLookup(variant_names, variant, std_variant);
+        }
     }
 
     /* Normalize the encoding name.  Note that we IGNORE the string
@@ -358,11 +374,13 @@
     setlocale(LC_ALL, "");
     if (ParseLocale(LC_CTYPE,
                     &(sprops.format_language),
+                    &(sprops.format_script),
                     &(sprops.format_country),
                     &(sprops.format_variant),
                     &(sprops.encoding))) {
         ParseLocale(LC_MESSAGES,
                     &(sprops.language),
+                    &(sprops.script),
                     &(sprops.country),
                     &(sprops.variant),
                     NULL);
@@ -371,6 +389,7 @@
         sprops.encoding = "ISO8859-1";
     }
     sprops.display_language = sprops.language;
+    sprops.display_script = sprops.script;
     sprops.display_country = sprops.country;
     sprops.display_variant = sprops.variant;
     sprops.sun_jnu_encoding = sprops.encoding;
--- a/jdk/src/solaris/native/java/lang/locale_str.h	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/native/java/lang/locale_str.h	Tue Nov 09 22:53:18 2010 -0800
@@ -86,6 +86,8 @@
     "wa", "wa_BE",
     "zh", "zh_CN",
 #ifdef __linux__
+    "bokmal", "nb_NO",
+    "bokm\u00e5l", "nb_NO",
     "catalan", "ca_ES",
     "croatian", "hr_HR",
     "czech", "cs_CZ",
@@ -93,9 +95,13 @@
     "dansk", "da_DK",
     "deutsch", "de_DE",
     "dutch", "nl_NL",
+    "eesti", "et_EE",
+    "estonian", "et_EE",
     "finnish", "fi_FI",
     "fran\xE7\x61is", "fr_FR",
     "french", "fr_FR",
+    "galego", "gl_ES",
+    "galician", "gl_ES",
     "german", "de_DE",
     "greek", "el_GR",
     "hebrew", "iw_IL",
@@ -104,7 +110,10 @@
     "icelandic", "is_IS",
     "italian", "it_IT",
     "japanese", "ja_JP",
+    "korean", "ko_KR",
+    "lithuanian", "lt_LT",
     "norwegian", "no_NO",
+    "nynorsk", "nn_NO",
     "polish", "pl_PL",
     "portuguese", "pt_PT",
     "romanian", "ro_RO",
@@ -114,11 +123,16 @@
     "slovenian", "sl_SI",
     "spanish", "es_ES",
     "swedish", "sv_SE",
+    "thai", "th_TH",
     "turkish", "tr_TR",
 #else
     "big5", "zh_TW.Big5",
     "chinese", "zh_CN",
+    "iso_8859_1", "en_US.ISO8859-1",
+    "iso_8859_15", "en_US.ISO8859-15",
     "japanese", "ja_JP",
+    "no_NY", "no_NO@nynorsk",
+    "sr_SP", "sr_YU",
     "tchinese", "zh_TW",
 #endif
     ""
@@ -361,6 +375,506 @@
     "japanese", "ja",
     "korean", "ko",
 #endif
+
+    /* ISO 639.2 codes */
+    "aar", "aar",
+    "abk", "abk",
+    "ace", "ace",
+    "ach", "ach",
+    "ada", "ada",
+    "ady", "ady",
+    "afa", "afa",
+    "afh", "afh",
+    "afr", "afr",
+    "ain", "ain",
+    "aka", "aka",
+    "akk", "akk",
+    "alb", "alb",
+    "ale", "ale",
+    "alg", "alg",
+    "alt", "alt",
+    "amh", "amh",
+    "ang", "ang",
+    "anp", "anp",
+    "apa", "apa",
+    "ara", "ara",
+    "arc", "arc",
+    "arg", "arg",
+    "arm", "arm",
+    "arn", "arn",
+    "arp", "arp",
+    "art", "art",
+    "arw", "arw",
+    "asm", "asm",
+    "ast", "ast",
+    "ath", "ath",
+    "aus", "aus",
+    "ava", "ava",
+    "ave", "ave",
+    "awa", "awa",
+    "aym", "aym",
+    "aze", "aze",
+    "bad", "bad",
+    "bai", "bai",
+    "bak", "bak",
+    "bal", "bal",
+    "bam", "bam",
+    "ban", "ban",
+    "baq", "baq",
+    "bas", "bas",
+    "bat", "bat",
+    "bej", "bej",
+    "bel", "bel",
+    "bem", "bem",
+    "ben", "ben",
+    "ber", "ber",
+    "bho", "bho",
+    "bih", "bih",
+    "bik", "bik",
+    "bin", "bin",
+    "bis", "bis",
+    "bla", "bla",
+    "bnt", "bnt",
+    "bos", "bos",
+    "bra", "bra",
+    "bre", "bre",
+    "btk", "btk",
+    "bua", "bua",
+    "bug", "bug",
+    "bul", "bul",
+    "bur", "bur",
+    "byn", "byn",
+    "cad", "cad",
+    "cai", "cai",
+    "car", "car",
+    "cat", "cat",
+    "cau", "cau",
+    "ceb", "ceb",
+    "cel", "cel",
+    "cha", "cha",
+    "chb", "chb",
+    "che", "che",
+    "chg", "chg",
+    "chi", "chi",
+    "chk", "chk",
+    "chm", "chm",
+    "chn", "chn",
+    "cho", "cho",
+    "chp", "chp",
+    "chr", "chr",
+    "chu", "chu",
+    "chv", "chv",
+    "chy", "chy",
+    "cmc", "cmc",
+    "cop", "cop",
+    "cor", "cor",
+    "cos", "cos",
+    "cpe", "cpe",
+    "cpf", "cpf",
+    "cpp", "cpp",
+    "cre", "cre",
+    "crh", "crh",
+    "crp", "crp",
+    "csb", "csb",
+    "cus", "cus",
+    "cze", "cze",
+    "dak", "dak",
+    "dan", "dan",
+    "dar", "dar",
+    "day", "day",
+    "del", "del",
+    "den", "den",
+    "dgr", "dgr",
+    "din", "din",
+    "div", "div",
+    "doi", "doi",
+    "dra", "dra",
+    "dsb", "dsb",
+    "dua", "dua",
+    "dum", "dum",
+    "dut", "dut",
+    "dyu", "dyu",
+    "dzo", "dzo",
+    "efi", "efi",
+    "egy", "egy",
+    "eka", "eka",
+    "elx", "elx",
+    "eng", "eng",
+    "enm", "enm",
+    "epo", "epo",
+    "est", "est",
+    "ewe", "ewe",
+    "ewo", "ewo",
+    "fan", "fan",
+    "fao", "fao",
+    "fat", "fat",
+    "fij", "fij",
+    "fil", "fil",
+    "fin", "fin",
+    "fiu", "fiu",
+    "fon", "fon",
+    "fre", "fre",
+    "frm", "frm",
+    "fro", "fro",
+    "frr", "frr",
+    "frs", "frs",
+    "fry", "fry",
+    "ful", "ful",
+    "fur", "fur",
+    "gaa", "gaa",
+    "gay", "gay",
+    "gba", "gba",
+    "gem", "gem",
+    "geo", "geo",
+    "ger", "ger",
+    "gez", "gez",
+    "gil", "gil",
+    "gla", "gla",
+    "gle", "gle",
+    "glg", "glg",
+    "glv", "glv",
+    "gmh", "gmh",
+    "goh", "goh",
+    "gon", "gon",
+    "gor", "gor",
+    "got", "got",
+    "grb", "grb",
+    "grc", "grc",
+    "gre", "gre",
+    "grn", "grn",
+    "gsw", "gsw",
+    "guj", "guj",
+    "gwi", "gwi",
+    "hai", "hai",
+    "hat", "hat",
+    "hau", "hau",
+    "haw", "haw",
+    "heb", "heb",
+    "her", "her",
+    "hil", "hil",
+    "him", "him",
+    "hin", "hin",
+    "hit", "hit",
+    "hmn", "hmn",
+    "hmo", "hmo",
+    "hrv", "hrv",
+    "hsb", "hsb",
+    "hun", "hun",
+    "hup", "hup",
+    "iba", "iba",
+    "ibo", "ibo",
+    "ice", "ice",
+    "ido", "ido",
+    "iii", "iii",
+    "ijo", "ijo",
+    "iku", "iku",
+    "ile", "ile",
+    "ilo", "ilo",
+    "ina", "ina",
+    "inc", "inc",
+    "ind", "ind",
+    "ine", "ine",
+    "inh", "inh",
+    "ipk", "ipk",
+    "ira", "ira",
+    "iro", "iro",
+    "ita", "ita",
+    "jav", "jav",
+    "jbo", "jbo",
+    "jpn", "jpn",
+    "jpr", "jpr",
+    "jrb", "jrb",
+    "kaa", "kaa",
+    "kab", "kab",
+    "kac", "kac",
+    "kal", "kal",
+    "kam", "kam",
+    "kan", "kan",
+    "kar", "kar",
+    "kas", "kas",
+    "kau", "kau",
+    "kaw", "kaw",
+    "kaz", "kaz",
+    "kbd", "kbd",
+    "kha", "kha",
+    "khi", "khi",
+    "khm", "khm",
+    "kho", "kho",
+    "kik", "kik",
+    "kin", "kin",
+    "kir", "kir",
+    "kmb", "kmb",
+    "kok", "kok",
+    "kom", "kom",
+    "kon", "kon",
+    "kor", "kor",
+    "kos", "kos",
+    "kpe", "kpe",
+    "krc", "krc",
+    "krl", "krl",
+    "kro", "kro",
+    "kru", "kru",
+    "kua", "kua",
+    "kum", "kum",
+    "kur", "kur",
+    "kut", "kut",
+    "lad", "lad",
+    "lah", "lah",
+    "lam", "lam",
+    "lao", "lao",
+    "lat", "lat",
+    "lav", "lav",
+    "lez", "lez",
+    "lim", "lim",
+    "lin", "lin",
+    "lit", "lit",
+    "lol", "lol",
+    "loz", "loz",
+    "ltz", "ltz",
+    "lua", "lua",
+    "lub", "lub",
+    "lug", "lug",
+    "lui", "lui",
+    "lun", "lun",
+    "luo", "luo",
+    "lus", "lus",
+    "mac", "mac",
+    "mad", "mad",
+    "mag", "mag",
+    "mah", "mah",
+    "mai", "mai",
+    "mak", "mak",
+    "mal", "mal",
+    "man", "man",
+    "mao", "mao",
+    "map", "map",
+    "mar", "mar",
+    "mas", "mas",
+    "may", "may",
+    "mdf", "mdf",
+    "mdr", "mdr",
+    "men", "men",
+    "mga", "mga",
+    "mic", "mic",
+    "min", "min",
+    "mis", "mis",
+    "mkh", "mkh",
+    "mlg", "mlg",
+    "mlt", "mlt",
+    "mnc", "mnc",
+    "mni", "mni",
+    "mno", "mno",
+    "moh", "moh",
+    "mon", "mon",
+    "mos", "mos",
+    "mul", "mul",
+    "mun", "mun",
+    "mus", "mus",
+    "mwl", "mwl",
+    "mwr", "mwr",
+    "myn", "myn",
+    "myv", "myv",
+    "nah", "nah",
+    "nai", "nai",
+    "nap", "nap",
+    "nau", "nau",
+    "nav", "nav",
+    "nbl", "nbl",
+    "nde", "nde",
+    "ndo", "ndo",
+    "nds", "nds",
+    "nep", "nep",
+    "new", "new",
+    "nia", "nia",
+    "nic", "nic",
+    "niu", "niu",
+    "nno", "nno",
+    "nob", "nob",
+    "nog", "nog",
+    "non", "non",
+    "nor", "nor",
+    "nqo", "nqo",
+    "nso", "nso",
+    "nub", "nub",
+    "nwc", "nwc",
+    "nya", "nya",
+    "nym", "nym",
+    "nyn", "nyn",
+    "nyo", "nyo",
+    "nzi", "nzi",
+    "oci", "oci",
+    "oji", "oji",
+    "ori", "ori",
+    "orm", "orm",
+    "osa", "osa",
+    "oss", "oss",
+    "ota", "ota",
+    "oto", "oto",
+    "paa", "paa",
+    "pag", "pag",
+    "pal", "pal",
+    "pam", "pam",
+    "pan", "pan",
+    "pap", "pap",
+    "pau", "pau",
+    "peo", "peo",
+    "per", "per",
+    "phi", "phi",
+    "phn", "phn",
+    "pli", "pli",
+    "pol", "pol",
+    "pon", "pon",
+    "por", "por",
+    "pra", "pra",
+    "pro", "pro",
+    "pus", "pus",
+    "que", "que",
+    "raj", "raj",
+    "rap", "rap",
+    "rar", "rar",
+    "roa", "roa",
+    "roh", "roh",
+    "rom", "rom",
+    "rum", "rum",
+    "run", "run",
+    "rup", "rup",
+    "rus", "rus",
+    "sad", "sad",
+    "sag", "sag",
+    "sah", "sah",
+    "sai", "sai",
+    "sal", "sal",
+    "sam", "sam",
+    "san", "san",
+    "sas", "sas",
+    "sat", "sat",
+    "scn", "scn",
+    "sco", "sco",
+    "sel", "sel",
+    "sem", "sem",
+    "sga", "sga",
+    "sgn", "sgn",
+    "shn", "shn",
+    "sid", "sid",
+    "sin", "sin",
+    "sio", "sio",
+    "sit", "sit",
+    "sla", "sla",
+    "slo", "slo",
+    "slv", "slv",
+    "sma", "sma",
+    "sme", "sme",
+    "smi", "smi",
+    "smj", "smj",
+    "smn", "smn",
+    "smo", "smo",
+    "sms", "sms",
+    "sna", "sna",
+    "snd", "snd",
+    "snk", "snk",
+    "sog", "sog",
+    "som", "som",
+    "son", "son",
+    "sot", "sot",
+    "spa", "spa",
+    "srd", "srd",
+    "srn", "srn",
+    "srp", "srp",
+    "srr", "srr",
+    "ssa", "ssa",
+    "ssw", "ssw",
+    "suk", "suk",
+    "sun", "sun",
+    "sus", "sus",
+    "sux", "sux",
+    "swa", "swa",
+    "swe", "swe",
+    "syc", "syc",
+    "syr", "syr",
+    "tah", "tah",
+    "tai", "tai",
+    "tam", "tam",
+    "tat", "tat",
+    "tel", "tel",
+    "tem", "tem",
+    "ter", "ter",
+    "tet", "tet",
+    "tgk", "tgk",
+    "tgl", "tgl",
+    "tha", "tha",
+    "tib", "tib",
+    "tig", "tig",
+    "tir", "tir",
+    "tiv", "tiv",
+    "tkl", "tkl",
+    "tlh", "tlh",
+    "tli", "tli",
+    "tmh", "tmh",
+    "tog", "tog",
+    "ton", "ton",
+    "tpi", "tpi",
+    "tsi", "tsi",
+    "tsn", "tsn",
+    "tso", "tso",
+    "tuk", "tuk",
+    "tum", "tum",
+    "tup", "tup",
+    "tur", "tur",
+    "tut", "tut",
+    "tvl", "tvl",
+    "twi", "twi",
+    "tyv", "tyv",
+    "udm", "udm",
+    "uga", "uga",
+    "uig", "uig",
+    "ukr", "ukr",
+    "umb", "umb",
+    "und", "und",
+    "urd", "urd",
+    "uzb", "uzb",
+    "vai", "vai",
+    "ven", "ven",
+    "vie", "vie",
+    "vol", "vol",
+    "vot", "vot",
+    "wak", "wak",
+    "wal", "wal",
+    "war", "war",
+    "was", "was",
+    "wel", "wel",
+    "wen", "wen",
+    "wln", "wln",
+    "wol", "wol",
+    "xal", "xal",
+    "xho", "xho",
+    "yao", "yao",
+    "yap", "yap",
+    "yid", "yid",
+    "yor", "yor",
+    "ypk", "ypk",
+    "zap", "zap",
+    "zbl", "zbl",
+    "zen", "zen",
+    "zha", "zha",
+    "znd", "znd",
+    "zul", "zul",
+    "zun", "zun",
+    "zxx", "zxx",
+    "zza", "zza",
+
+    "",
+};
+
+/*
+ * Linux/Solaris script string to Java script name mapping table.
+ */
+static char *script_names[] = {
+#ifdef __linux__
+    "cyrillic", "Cyrl",
+    "devanagari", "Deva",
+    "iqtelif", "Latn",
+    "latin", "Latn",
+#endif
     "",
 };
 
@@ -503,6 +1017,7 @@
     "MA", "MA",
     "MC", "MC",
     "MD", "MD",
+    "ME", "ME",
     "MG", "MG",
     "MH", "MH",
     "MK", "MK",
@@ -554,6 +1069,7 @@
     "RN", "US", // used on Linux, not clear what it stands for
 #endif
     "RO", "RO",
+    "RS", "RS",
     "RU", "RU",
     "RW", "RW",
     "SA", "SA",
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Tue Nov 09 22:53:18 2010 -0800
@@ -381,7 +381,15 @@
       n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
                  sizeof(struct sockaddr));
       if (n < 0 && errno != EINPROGRESS ) {
-        NET_ThrowNew(env, errno, "Can't send ICMP packet");
+#ifdef __linux__
+        if (errno != EINVAL)
+          /*
+           * On some Linuxes, when bound to the loopback interface, sendto
+           * will fail and errno will be set to EINVAL. When that happens,
+           * don't throw an exception, just return false.
+           */
+#endif /*__linux__ */
+          NET_ThrowNew(env, errno, "Can't send ICMP packet");
         close(fd);
         return JNI_FALSE;
       }
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Tue Nov 09 22:53:18 2010 -0800
@@ -506,7 +506,16 @@
       plen = sizeof(struct icmp6_hdr) + sizeof(tv);
       n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
       if (n < 0 && errno != EINPROGRESS) {
+#ifdef __linux__
+        if (errno != EINVAL)
+          /*
+           * On some Linuxes, when bound to the loopback interface, sendto
+           * will fail and errno will be set to EINVAL. When that happens,
+           * don't throw an exception, just return false.
+           */
+#endif /*__linux__ */
         NET_ThrowNew(env, errno, "Can't send ICMP packet");
+        close(fd);
         return JNI_FALSE;
       }
 
--- a/jdk/src/solaris/native/java/nio/MappedByteBuffer.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/solaris/native/java/nio/MappedByteBuffer.c	Tue Nov 09 22:53:18 2010 -0800
@@ -82,8 +82,8 @@
 
 
 JNIEXPORT void JNICALL
-Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jlong address,
-                                      jlong len)
+Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jobject fdo,
+                                      jlong address, jlong len)
 {
     void* a = (void *)jlong_to_ptr(address);
     int result = msync(a, (size_t)len, MS_SYNC);
--- a/jdk/src/windows/bin/java_md.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/bin/java_md.c	Tue Nov 09 22:53:18 2010 -0800
@@ -51,6 +51,92 @@
 static jboolean GetJREPath(char *path, jint pathsize);
 static void EnsureJreInstallation(const char *jrepath);
 
+/* We supports warmup for UI stack that is performed in parallel
+ * to VM initialization.
+ * This helps to improve startup of UI application as warmup phase
+ * might be long due to initialization of OS or hardware resources.
+ * It is not CPU bound and therefore it does not interfere with VM init.
+ * Obviously such warmup only has sense for UI apps and therefore it needs
+ * to be explicitly requested by passing -Dsun.awt.warmup=true property
+ * (this is always the case for plugin/javaws).
+ *
+ * Implementation launches new thread after VM starts and use it to perform
+ * warmup code (platform dependent).
+ * This thread is later reused as AWT toolkit thread as graphics toolkit
+ * often assume that they are used from the same thread they were launched on.
+ *
+ * At the moment we only support warmup for D3D. It only possible on windows
+ * and only if other flags do not prohibit this (e.g. OpenGL support requested).
+ */
+#undef ENABLE_AWT_PRELOAD
+#ifndef JAVA_ARGS /* turn off AWT preloading for javac, jar, etc */
+    #define ENABLE_AWT_PRELOAD
+#endif
+
+#ifdef ENABLE_AWT_PRELOAD
+/* "AWT was preloaded" flag;
+ * turned on by AWTPreload().
+ */
+int awtPreloaded = 0;
+
+/* Calls a function with the name specified
+ * the function must be int(*fn)(void).
+ */
+int AWTPreload(const char *funcName);
+/* stops AWT preloading */
+void AWTPreloadStop();
+
+/* D3D preloading */
+/* -1: not initialized; 0: OFF, 1: ON */
+int awtPreloadD3D = -1;
+/* command line parameter to swith D3D preloading on */
+#define PARAM_PRELOAD_D3D "-Dsun.awt.warmup"
+/* D3D/OpenGL management parameters */
+#define PARAM_NODDRAW "-Dsun.java2d.noddraw"
+#define PARAM_D3D "-Dsun.java2d.d3d"
+#define PARAM_OPENGL "-Dsun.java2d.opengl"
+/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */
+#define D3D_PRELOAD_FUNC "preloadD3D"
+
+
+/* Extracts value of a parameter with the specified name
+ * from command line argument (returns pointer in the argument).
+ * Returns NULL if the argument does not contains the parameter.
+ * e.g.:
+ * GetParamValue("theParam", "theParam=value") returns pointer to "value".
+ */
+const char * GetParamValue(const char *paramName, const char *arg) {
+    int nameLen = JLI_StrLen(paramName);
+    if (JLI_StrNCmp(paramName, arg, nameLen) == 0) {
+        /* arg[nameLen] is valid (may contain final NULL) */
+        if (arg[nameLen] == '=') {
+            return arg + nameLen + 1;
+        }
+    }
+    return NULL;
+}
+
+/* Checks if commandline argument contains property specified
+ * and analyze it as boolean property (true/false).
+ * Returns -1 if the argument does not contain the parameter;
+ * Returns 1 if the argument contains the parameter and its value is "true";
+ * Returns 0 if the argument contains the parameter and its value is "false".
+ */
+int GetBoolParamValue(const char *paramName, const char *arg) {
+    const char * paramValue = GetParamValue(paramName, arg);
+    if (paramValue != NULL) {
+        if (JLI_StrCaseCmp(paramValue, "true") == 0) {
+            return 1;
+        }
+        if (JLI_StrCaseCmp(paramValue, "false") == 0) {
+            return 0;
+        }
+    }
+    return -1;
+}
+#endif /* ENABLE_AWT_PRELOAD */
+
+
 static jboolean _isjavaw = JNI_FALSE;
 
 
@@ -132,6 +218,30 @@
         exit(4);
     }
     /* If we got here, jvmpath has been correctly initialized. */
+
+    /* Check if we need preload AWT */
+#ifdef ENABLE_AWT_PRELOAD
+    argv = *pargv;
+    for (i = 0; i < *pargc ; i++) {
+        /* Tests the "turn on" parameter only if not set yet. */
+        if (awtPreloadD3D < 0) {
+            if (GetBoolParamValue(PARAM_PRELOAD_D3D, argv[i]) == 1) {
+                awtPreloadD3D = 1;
+            }
+        }
+        /* Test parameters which can disable preloading if not already disabled. */
+        if (awtPreloadD3D != 0) {
+            if (GetBoolParamValue(PARAM_NODDRAW, argv[i]) == 1
+                || GetBoolParamValue(PARAM_D3D, argv[i]) == 0
+                || GetBoolParamValue(PARAM_OPENGL, argv[i]) == 1)
+            {
+                awtPreloadD3D = 0;
+                /* no need to test the rest of the parameters */
+                break;
+            }
+        }
+    }
+#endif /* ENABLE_AWT_PRELOAD */
 }
 
 
@@ -208,7 +318,7 @@
     struct stat s;
 
     /* Make sure the jrepath contains something */
-    if (jrepath[0] == NULL) {
+    if ((void*)jrepath[0] == NULL) {
         return;
     }
     /* 32 bit windows only please */
@@ -540,7 +650,7 @@
         /* get the length of the string we need */
         int len = mlen =  _vscprintf(fmt, vl) + 1;
         if (freeit) {
-           mlen += JLI_StrLen(errtext);
+           mlen += (int)JLI_StrLen(errtext);
         }
 
         message = (char *)JLI_MemAlloc(mlen);
@@ -997,7 +1107,6 @@
 
         exit(exitCode);
     }
-
 }
 
 /*
@@ -1087,6 +1196,40 @@
                              0,
                              &thread_id);
     }
+
+    /* AWT preloading (AFTER main thread start) */
+#ifdef ENABLE_AWT_PRELOAD
+    /* D3D preloading */
+    if (awtPreloadD3D != 0) {
+        char *envValue;
+        /* D3D routines checks env.var J2D_D3D if no appropriate
+         * command line params was specified
+         */
+        envValue = getenv("J2D_D3D");
+        if (envValue != NULL && JLI_StrCaseCmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        /* Test that AWT preloading isn't disabled by J2D_D3D_PRELOAD env.var */
+        envValue = getenv("J2D_D3D_PRELOAD");
+        if (envValue != NULL && JLI_StrCaseCmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        if (awtPreloadD3D < 0) {
+            /* If awtPreloadD3D is still undefined (-1), test
+             * if it is turned on by J2D_D3D_PRELOAD env.var.
+             * By default it's turned OFF.
+             */
+            awtPreloadD3D = 0;
+            if (envValue != NULL && JLI_StrCaseCmp(envValue, "true") == 0) {
+                awtPreloadD3D = 1;
+            }
+         }
+    }
+    if (awtPreloadD3D) {
+        AWTPreload(D3D_PRELOAD_FUNC);
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
     if (thread_handle) {
       WaitForSingleObject(thread_handle, INFINITE);
       GetExitCodeThread(thread_handle, &rslt);
@@ -1094,6 +1237,13 @@
     } else {
       rslt = continuation(args);
     }
+
+#ifdef ENABLE_AWT_PRELOAD
+    if (awtPreloaded) {
+        AWTPreloadStop();
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
     return rslt;
 }
 
@@ -1140,3 +1290,98 @@
     _isjavaw = javaw;
     JLI_SetTraceLauncher();
 }
+
+
+/* ============================== */
+/* AWT preloading */
+#ifdef ENABLE_AWT_PRELOAD
+
+typedef int FnPreloadStart(void);
+typedef void FnPreloadStop(void);
+static FnPreloadStop *fnPreloadStop = NULL;
+static HMODULE hPreloadAwt = NULL;
+
+/*
+ * Starts AWT preloading
+ */
+int AWTPreload(const char *funcName)
+{
+    int result = -1;
+    /* load AWT library once (if several preload function should be called) */
+    if (hPreloadAwt == NULL) {
+        /* awt.dll is not loaded yet */
+        char libraryPath[MAXPATHLEN];
+        int jrePathLen = 0;
+        HMODULE hJava = NULL;
+        HMODULE hVerify = NULL;
+
+        while (1) {
+            /* awt.dll depends on jvm.dll & java.dll;
+             * jvm.dll is already loaded, so we need only java.dll;
+             * java.dll depends on MSVCRT lib & verify.dll.
+             */
+            if (!GetJREPath(libraryPath, MAXPATHLEN)) {
+                break;
+            }
+
+            /* save path length */
+            jrePathLen = JLI_StrLen(libraryPath);
+
+            /* load msvcrt 1st */
+            LoadMSVCRT();
+
+            /* load verify.dll */
+            JLI_StrCat(libraryPath, "\\bin\\verify.dll");
+            hVerify = LoadLibrary(libraryPath);
+            if (hVerify == NULL) {
+                break;
+            }
+
+            /* restore jrePath */
+            libraryPath[jrePathLen] = 0;
+            /* load java.dll */
+            JLI_StrCat(libraryPath, "\\bin\\" JAVA_DLL);
+            hJava = LoadLibrary(libraryPath);
+            if (hJava == NULL) {
+                break;
+            }
+
+            /* restore jrePath */
+            libraryPath[jrePathLen] = 0;
+            /* load awt.dll */
+            JLI_StrCat(libraryPath, "\\bin\\awt.dll");
+            hPreloadAwt = LoadLibrary(libraryPath);
+            if (hPreloadAwt == NULL) {
+                break;
+            }
+
+            /* get "preloadStop" func ptr */
+            fnPreloadStop = (FnPreloadStop *)GetProcAddress(hPreloadAwt, "preloadStop");
+
+            break;
+        }
+    }
+
+    if (hPreloadAwt != NULL) {
+        FnPreloadStart *fnInit = (FnPreloadStart *)GetProcAddress(hPreloadAwt, funcName);
+        if (fnInit != NULL) {
+            /* don't forget to stop preloading */
+            awtPreloaded = 1;
+
+            result = fnInit();
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Terminates AWT preloading
+ */
+void AWTPreloadStop() {
+    if (fnPreloadStop != NULL) {
+        fnPreloadStop();
+    }
+}
+
+#endif /* ENABLE_AWT_PRELOAD */
--- a/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java	Tue Nov 09 22:53:18 2010 -0800
@@ -169,7 +169,7 @@
                     locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) ||
                     locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) {
                 if (isActive) {
-                    setNativeLocale(locale.toString(), onActivate);
+                    setNativeLocale(locale.toLanguageTag(), onActivate);
                 }
                 currentLocale = locale;
                 return true;
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Tue Nov 09 22:53:18 2010 -0800
@@ -218,6 +218,8 @@
 
     private static native void postDispose();
 
+    private static native boolean startToolkitThread(Runnable thread);
+
     public WToolkit() {
         // Startup toolkit threads
         if (PerformanceLogger.loggingEnabled()) {
@@ -231,9 +233,6 @@
             // where notifyAll can be called before
             // the "AWT-Windows" thread's parent thread is
             // waiting, resulting in a deadlock on startup.
-            Thread toolkitThread = new Thread(this, "AWT-Windows");
-            toolkitThread.setDaemon(true);
-            toolkitThread.setPriority(Thread.NORM_PRIORITY+1);
 
             /*
              * Fix for 4701990.
@@ -242,7 +241,11 @@
              */
             AWTAutoShutdown.notifyToolkitThreadBusy();
 
-            toolkitThread.start();
+            if (!startToolkitThread(this)) {
+                Thread toolkitThread = new Thread(this, "AWT-Windows");
+                toolkitThread.setDaemon(true);
+                toolkitThread.start();
+            }
 
             try {
                 wait();
@@ -263,6 +266,7 @@
     }
 
     public void run() {
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
         boolean startPump = init();
 
         if (startPump) {
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -600,6 +600,7 @@
     }
 
     private native void setOpacity(int iOpacity);
+    private float opacity = 1.0f;
 
     public void setOpacity(float opacity) {
         if (!((SunToolkit)((Window)target).getToolkit()).
@@ -608,7 +609,21 @@
             return;
         }
 
-        replaceSurfaceDataRecursively((Component)getTarget());
+        if (opacity < 0.0f || opacity > 1.0f) {
+            throw new IllegalArgumentException(
+                "The value of opacity should be in the range [0.0f .. 1.0f].");
+        }
+
+        if (((this.opacity == 1.0f && opacity <  1.0f) ||
+             (this.opacity <  1.0f && opacity == 1.0f)) &&
+            !Win32GraphicsEnvironment.isVistaOS())
+        {
+            // non-Vista OS: only replace the surface data if opacity status
+            // changed (see WComponentPeer.isAccelCapable() for more)
+            replaceSurfaceDataRecursively((Component)getTarget());
+        }
+
+        this.opacity = opacity;
 
         final int maxOpacity = 0xff;
         int iOpacity = (int)(opacity * maxOpacity);
@@ -650,7 +665,7 @@
 
         boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS();
 
-        if (!isVistaOS) {
+        if (this.isOpaque != isOpaque && !isVistaOS) {
             // non-Vista OS: only replace the surface data if the opacity
             // status changed (see WComponentPeer.isAccelCapable() for more)
             replaceSurfaceDataRecursively(target);
--- a/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Tue Nov 09 22:53:18 2010 -0800
@@ -26,10 +26,11 @@
 package sun.nio.ch;
 
 import java.io.*;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
 
 class FileDispatcherImpl extends FileDispatcher
 {
-
     static {
         Util.load();
     }
@@ -94,6 +95,16 @@
         close0(fd);
     }
 
+    FileDescriptor duplicateForMapping(FileDescriptor fd) throws IOException {
+        // on Windows we need to keep a handle to the file
+        JavaIOFileDescriptorAccess fdAccess =
+            SharedSecrets.getJavaIOFileDescriptorAccess();
+        FileDescriptor result = new FileDescriptor();
+        long handle = duplicateHandle(fdAccess.getHandle(fd));
+        fdAccess.setHandle(result, handle);
+        return result;
+    }
+
     //-- Native methods
 
     static native int read0(FileDescriptor fd, long address, int len)
@@ -132,4 +143,5 @@
 
     static native void closeByHandle(long fd) throws IOException;
 
+    static native long duplicateHandle(long fd) throws IOException;
 }
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class WindowsAsynchronousChannelProvider
@@ -90,12 +89,4 @@
     {
         return new WindowsAsynchronousSocketChannelImpl(toIocp(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toIocp(group));
-    }
 }
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -39,10 +39,11 @@
 import java.text.DateFormat;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.Locale;
 import sun.security.krb5.internal.crypto.EType;
 /**
  * This class can execute as a command-line tool to help the user manage
- * entires in the key table.
+ * entries in the key table.
  * Available functions include list/add/update/delete service key(s).
  *
  * @author Yanni Zhang
@@ -60,30 +61,20 @@
     int etype = -1;
     char[] password = null;
 
+    boolean forced = false; // true if delete without prompt. Default false
+    boolean append = false; // true if new keys are appended. Default false
+    int vDel = -1;          // kvno to delete, -1 all, -2 old. Default -1
+    int vAdd = -1;          // kvno to add. Default -1, means auto incremented
+
     /**
      * The main program that can be invoked at command line.
-     * <br>Usage: ktab <options>
-     * <br>available options to Ktab:
-     * <ul>
-     * <li><b>-l [-e] [-t]</b>  list the keytab name and entries, -e show
-     * encryption etypes, -t show timestamps.
-     * <li><b>-a</b>  &lt;<i>principal name</i>&gt;
-     * (&lt;<i>password</i>&gt;)  add an entry to the keytab.
-     * The entry is added only to the keytab. No changes are made to the
-     * Kerberos database.
-     * <li><b>-d</b>  &lt;<i>principal name</i>&gt; [&lt;<i>etype</i>&gt;]
-     * delete an entry from the keytab.
-     * The entry is deleted only from the keytab. No changes are made to the
-     * Kerberos database.
-     * <li><b>-k</b>  &lt;<i>keytab name</i> &gt;
-     * specify keytab name and path with prefix FILE:
-     * <li><b>-help</b> display instructions.
+     * See {@link #printHelp} for usages.
      */
     public static void main(String[] args) {
         Ktab ktab = new Ktab();
         if ((args.length == 1) && (args[0].equalsIgnoreCase("-help"))) {
             ktab.printHelp();
-            System.exit(0);
+            return;
         } else if ((args == null) || (args.length == 0)) {
             ktab.action = 'l';
         } else {
@@ -139,7 +130,6 @@
             break;
         default:
             ktab.printHelp();
-            System.exit(-1);
         }
     }
 
@@ -147,84 +137,129 @@
      * Parses the command line arguments.
      */
     void processArgs(String[] args) {
-        Character arg = null;
+
+        // Commands (should appear before options):
+        //   -l
+        //   -a <princ>
+        //   -d <princ>
+        // Options:
+        //   -e <etype> (for -d)
+        //   -e (for -l)
+        //   -n <kvno>
+        //   -k <keytab>
+        //   -t
+        //   -f
+        //   -append
+        // Optional extra arguments:
+        //   password for -a
+        //   [kvno|all|old] for -d
+
+        boolean argAlreadyAppeared = false;
         for (int i = 0; i < args.length; i++) {
-            if ((args[i].length() == 2) && (args[i].startsWith("-"))) {
-                arg = new Character(args[i].charAt(1));
-            } else {
-                printHelp();
-                System.exit(-1);
-            }
-            switch (arg.charValue()) {
-            case 'l':
-            case 'L':
-                action = 'l';    // list keytab location, name and entries
-                break;
-            case 'a':
-            case 'A':
-                action = 'a'; // add a new entry to keytab.
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    principal = args[i];
-                } else {
-                    System.out.println("Please specify the principal name"+
-                                       " after -a option.");
-                    printHelp();
-                    System.exit(-1);
+            if (args[i].startsWith("-")) {
+                switch (args[i].toLowerCase(Locale.US)) {
+
+                    // Commands
+                    case "-l":   // list
+                        action = 'l';
+                        break;
+                    case "-a":   // add a new entry to keytab.
+                        action = 'a';
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A principal name must be specified after -a");
+                        }
+                        principal = args[i];
+                        break;
+                    case "-d":   // delete entries
+                        action = 'd';
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A principal name must be specified after -d");
+                        }
+                        principal = args[i];
+                        break;
+
+                        // Options
+                    case "-e":
+                        if (action == 'l') {    // list etypes
+                            showEType = true;
+                        } else if (action == 'd') { // delete etypes
+                            if (++i >= args.length || args[i].startsWith("-")) {
+                                error("An etype must be specified after -e");
+                            }
+                            try {
+                                etype = Integer.parseInt(args[i]);
+                                if (etype <= 0) {
+                                    throw new NumberFormatException();
+                                }
+                            } catch (NumberFormatException nfe) {
+                                error(args[i] + " is not a valid etype");
+                            }
+                        } else {
+                            error(args[i] + " is not valid after -" + action);
+                        }
+                        break;
+                    case "-n":   // kvno for -a
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A KVNO must be specified after -n");
+                        }
+                        try {
+                            vAdd = Integer.parseInt(args[i]);
+                            if (vAdd < 0) {
+                                throw new NumberFormatException();
+                            }
+                        } catch (NumberFormatException nfe) {
+                            error(args[i] + " is not a valid KVNO");
+                        }
+                        break;
+                    case "-k":  // specify keytab to use
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A keytab name must be specified after -k");
+                        }
+                        if (args[i].length() >= 5 &&
+                            args[i].substring(0, 5).equalsIgnoreCase("FILE:")) {
+                            name = args[i].substring(5);
+                        } else {
+                            name = args[i];
+                        }
+                        break;
+                    case "-t":   // list timestamps
+                        showTime = true;
+                        break;
+                    case "-f":   // force delete, no prompt
+                        forced = true;
+                        break;
+                    case "-append": // -a, new keys append to file
+                        append = true;
+                        break;
+                    default:
+                        printHelp();
+                        break;
                 }
-                if ((i + 1 < args.length) &&
-                    (!args[i + 1].startsWith("-"))) {
-                    password = args[i + 1].toCharArray();
-                    i++;
-                } else {
-                    password = null; // prompt user for password later.
+            } else {    // optional standalone arguments
+                if (argAlreadyAppeared) {
+                    error("Useless extra argument " + args[i]);
                 }
-                break;
-            case 'd':
-            case 'D':
-                action = 'd'; // delete an entry.
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    principal = args[i];
-                    int j = i + 1;
-                    if ((j < args.length) && (!args[j].startsWith("-"))) {
-                        etype = Integer.parseInt(args[j]);
-                        i = j;
+                if (action == 'a') {
+                    password = args[i].toCharArray();
+                } else if (action == 'd') {
+                    switch (args[i]) {
+                        case "all": vDel = -1; break;
+                        case "old": vDel = -2; break;
+                        default: {
+                            try {
+                                vDel = Integer.parseInt(args[i]);
+                                if (vDel < 0) {
+                                    throw new NumberFormatException();
+                                }
+                            } catch (NumberFormatException nfe) {
+                                error(args[i] + " is not a valid KVNO");
+                            }
+                        }
                     }
                 } else {
-                    System.out.println("Please specify the principal" +
-                                       "name of the entry you want to " +
-                                       " delete after -d option.");
-                    printHelp();
-                    System.exit(-1);
+                    error("Useless extra argument " + args[i]);
                 }
-                break;
-            case 'k':
-            case 'K':
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    if (args[i].length() >= 5 &&
-                        args[i].substring(0, 5).equalsIgnoreCase("FILE:")) {
-                        name = args[i].substring(5);
-                    } else
-                        name = args[i];
-                } else {
-                    System.out.println("Please specify the keytab "+
-                                       "file name and location " +
-                                       "after -k option");
-                    printHelp();
-                    System.exit(-1);
-                }
-                break;
-            case 'e':
-                showEType = true;
-                break;
-            case 't':
-                showTime = true;
-                break;
-            default:
-                printHelp();
-                System.exit(-1);
+                argAlreadyAppeared = true;
             }
         }
     }
@@ -263,7 +298,7 @@
         }
         try {
             // admin.addEntry(pname, password);
-            table.addEntry(pname, password);
+            table.addEntry(pname, password, vAdd, append);
             Arrays.fill(password, '0');  // clear password
             // admin.save();
             table.save();
@@ -350,23 +385,25 @@
             if (pname.getRealm() == null) {
                 pname.setRealm(Config.getInstance().getDefaultRealm());
             }
-            String answer;
-            BufferedReader cis =
-                new BufferedReader(new InputStreamReader(System.in));
-            System.out.print("Are you sure you want to"+
-                             " delete service key for " + pname.toString() +
-                             " (" + (etype==-1?"all etypes":("etype = "+etype)) +
-                             ") in " + table.tabName() + "?(Y/N): ");
+            if (!forced) {
+                String answer;
+                BufferedReader cis =
+                    new BufferedReader(new InputStreamReader(System.in));
+                System.out.print("Are you sure you want to delete "+
+                        "service key(s) for " + pname.toString() +
+                        " (" + (etype==-1?"all etypes":("etype="+etype)) + ", " +
+                        (vDel==-1?"all kvno":(vDel==-2?"old kvno":("kvno=" + vDel))) +
+                        ") in " + table.tabName() + "? (Y/[N]): ");
 
-            System.out.flush();
-            answer = cis.readLine();
-            if (answer.equalsIgnoreCase("Y") ||
-                answer.equalsIgnoreCase("Yes"));
-            else {
-                // no error, the user did not want to delete the entry
-                System.exit(0);
+                System.out.flush();
+                answer = cis.readLine();
+                if (answer.equalsIgnoreCase("Y") ||
+                    answer.equalsIgnoreCase("Yes"));
+                else {
+                    // no error, the user did not want to delete the entry
+                    System.exit(0);
+                }
             }
-
         } catch (KrbException e) {
             System.err.println("Error occured while deleting the entry. "+
                                "Deletion failed.");
@@ -379,9 +416,7 @@
             System.exit(-1);
         }
 
-        int count;
-        if (etype == -1) count = table.deleteEntry(pname);
-        else count = table.deleteEntry(pname, etype);
+        int count = table.deleteEntries(pname, etype, vDel);
 
         if (count == 0) {
             System.err.println("No matched entry in the keytab. " +
@@ -396,23 +431,47 @@
                 e.printStackTrace();
                 System.exit(-1);
             }
-            System.out.println("Done!");
+            System.out.println("Done! " + count + " entries removed.");
         }
     }
 
+    void error(String... errors) {
+        for (String error: errors) {
+            System.out.println("Error: " + error + ".");
+        }
+        printHelp();
+        System.exit(-1);
+    }
     /**
      * Prints out the help information.
      */
     void printHelp() {
-        System.out.println("\nUsage: ktab " +
-                           "<options>");
-        System.out.println("available options to Ktab:");
-        System.out.println("-l [-e] [-t]\t\t\tlist the keytab name and entries,\n\t\t\t\t-e with etype, -t with timestamp");
-        System.out.println("-a <principal name> (<password>)add an entry " +
-                           "to the keytab");
-        System.out.println("-d <principal name> [<etype>]\tdelete an "+
-                           "entry from the keytab");
-        System.out.println("-k <keytab name>\t\tspecify keytab name and "+
-                           "path with prefix FILE:");
+        System.out.println("\nUsage: ktab <commands> <options>");
+        System.out.println();
+        System.out.println("Available commands:");
+        System.out.println();
+        System.out.println("-l [-e] [-t]\n"
+                + "    list the keytab name and entries. -e with etype, -t with timestamp.");
+        System.out.println("-a <principal name> [<password>] [-n <kvno>] [-append]\n"
+                + "    add new key entries to the keytab for the given principal name with\n"
+                + "    optional <password>. If a <kvno> is specified, new keys' Key Version\n"
+                + "    Numbers equal to the value, otherwise, automatically incrementing\n"
+                + "    the Key Version Numbers. If -append is specified, new keys are\n"
+                + "    appended to the keytab, otherwise, old keys for the\n"
+                + "    same principal are removed.");
+        System.out.println("-d <principal name> [-f] [-e <etype>] [<kvno> | all | old]\n"
+                + "    delete key entries from the keytab for the specified principal. If\n"
+                + "    <kvno> is specified, delete keys whose Key Version Numbers match\n"
+                + "    kvno. If \"all\" is specified, delete all keys. If \"old\" is specified,\n"
+                + "    delete all keys except those with the highest kvno. Default action\n"
+                + "    is \"all\". If <etype> is specified, only keys of this encryption type\n"
+                + "    are deleted. <etype> should be specified as the numberic value etype\n"
+                + "    defined in RFC 3961, section 8. A prompt to confirm the deletion is\n"
+                + "    displayed unless -f is specified.");
+        System.out.println();
+        System.out.println("Common option(s):");
+        System.out.println();
+        System.out.println("-k <keytab name>\n"
+                + "    specify keytab name and path with prefix FILE:");
     }
 }
--- a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_DirectSound.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_DirectSound.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -476,6 +476,7 @@
 
 DWORD WINAPI __stdcall DS_StartBufferHelper::ThreadProc(void *param)
 {
+    ::CoInitialize(NULL);
     while (1) {
         // wait for something to do
         ::WaitForSingleObject(data.startEvent, INFINITE);
@@ -492,6 +493,7 @@
         }
         ::SetEvent(data.startedEvent);
     }
+    ::CoUninitialize();
     return 0;
 }
 
--- a/jdk/src/windows/native/java/lang/java_props_md.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/java/lang/java_props_md.c	Tue Nov 09 22:53:18 2010 -0800
@@ -43,11 +43,14 @@
 #endif
 
 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
-static void SetupI18nProps(LCID lcid, char** language, char** country,
+static void SetupI18nProps(LCID lcid, char** language, char** script, char** country,
                char** variant, char** encoding);
 
 #define SHELL_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
 
+#define PROPSIZE 9      // eight-letter + null terminator
+#define SNAMESIZE 86    // max number of chars for LOCALE_SNAME is 85
+
 static char *
 getEncodingInternal(LCID lcid)
 {
@@ -127,30 +130,31 @@
     return getEncodingInternal(MAKELCID(langID, SORT_DEFAULT));
 }
 
+// Returns BCP47 Language Tag
 DllExport const char *
 getJavaIDFromLangID(LANGID langID)
 {
-    char * lang;
-    char * ctry;
-    char * vrnt;
-    char * enc;
-    char * ret = malloc(16);
+    char * elems[5]; // lang, script, ctry, variant, encoding
+    char * ret = malloc(SNAMESIZE);
+    int index;
+
+    SetupI18nProps(MAKELCID(langID, SORT_DEFAULT),
+                   &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]));
 
-    SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), &lang, &ctry, &vrnt, &enc);
-    if (ctry[0] != '\0') {
-        if (vrnt[0] != '\0') {
-            sprintf(ret, "%s_%s_%s", lang, ctry, vrnt);
-        } else {
-            sprintf(ret, "%s_%s", lang, ctry);
+    // there always is the "language" tag
+    strcpy(ret, elems[0]);
+
+    // append other elements, if any
+    for (index = 1; index < 4; index++) {
+        if ((elems[index])[0] != '\0') {
+            strcat(ret, "-");
+            strcat(ret, elems[index]);
         }
-    } else {
-        strcpy(ret, lang);
     }
 
-    free(lang);
-    free(ctry);
-    free(vrnt);
-    free(enc);
+    for (index = 0; index < 5; index++) {
+        free(elems[index]);
+    }
 
     return ret;
 }
@@ -289,39 +293,38 @@
     return NULL;
 }
 
-#define PROPSIZE 3      // two-letter + null terminator
 static void
-SetupI18nProps(LCID lcid, char** language, char** country,
+SetupI18nProps(LCID lcid, char** language, char** script, char** country,
                char** variant, char** encoding) {
+    /* script */
+    char tmp[SNAMESIZE];
+    *script = malloc(PROPSIZE);
+    if (GetLocaleInfo(lcid,
+                      LOCALE_SNAME, tmp, SNAMESIZE) == 0 ||
+        sscanf(tmp, "%*[a-z\\-]%1[A-Z]%[a-z]", *script, &((*script)[1])) == 0 ||
+        strlen(*script) != 4) {
+        (*script)[0] = '\0';
+    }
+
     /* country */
     *country = malloc(PROPSIZE);
     if (GetLocaleInfo(lcid,
-                      LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0) {
+                      LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0 &&
+        GetLocaleInfo(lcid,
+                      LOCALE_SISO3166CTRYNAME2, *country, PROPSIZE) == 0) {
         (*country)[0] = '\0';
     }
 
     /* language */
     *language = malloc(PROPSIZE);
-    if (lcid == 0x46c) {
-        /* Windows returns non-existent language code "ns" for Northern Sotho.
-         * Defaults to en_US
-         */
-        strcpy(*language, "en");
-        strcpy(*country, "US");
-    } else if (GetLocaleInfo(lcid,
-                      LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0) {
-        if (lcid == 0x465) {
-            /* for some reason, Windows returns "div" for this Divehi LCID, even though
-             * there is a two letter language code "dv".  Tweak it here.
-             */
-            strcpy(*language, "dv");
-            strcpy(*country, "MV");
-        } else {
+    if (GetLocaleInfo(lcid,
+                      LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0 &&
+        GetLocaleInfo(lcid,
+                      LOCALE_SISO639LANGNAME2, *language, PROPSIZE) == 0) {
             /* defaults to en_US */
             strcpy(*language, "en");
             strcpy(*country, "US");
         }
-    }
 
     /* variant */
     *variant = malloc(PROPSIZE);
@@ -564,7 +567,7 @@
 
     /*
      *  user.language
-     *  user.country, user.variant (if user's environment specifies them)
+     *  user.script, user.country, user.variant (if user's environment specifies them)
      *  file.encoding
      *  file.encoding.pkg
      */
@@ -582,16 +585,19 @@
 
             SetupI18nProps(userDefaultUILang,
                            &sprops.language,
+                           &sprops.script,
                            &sprops.country,
                            &sprops.variant,
                            &display_encoding);
             SetupI18nProps(userDefaultLCID,
                            &sprops.format_language,
+                           &sprops.format_script,
                            &sprops.format_country,
                            &sprops.format_variant,
                            &sprops.encoding);
             SetupI18nProps(userDefaultUILang,
                            &sprops.display_language,
+                           &sprops.display_script,
                            &sprops.display_country,
                            &sprops.display_variant,
                            &display_encoding);
--- a/jdk/src/windows/native/java/nio/MappedByteBuffer.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/java/nio/MappedByteBuffer.c	Tue Nov 09 22:53:18 2010 -0800
@@ -51,11 +51,11 @@
 }
 
 JNIEXPORT void JNICALL
-Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jlong address,
-                                      jlong len)
+Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jobject fdo,
+                                      jlong address, jlong len)
 {
     void *a = (void *) jlong_to_ptr(address);
-    int result;
+    BOOL result;
     int retry;
 
     /*
@@ -71,6 +71,30 @@
         retry++;
     } while (retry < 3);
 
+    /**
+     * FlushViewOfFile only initiates the writing of dirty pages to disk
+     * so we have to call FlushFileBuffers to and ensure they are written.
+     */
+    if (result != 0) {
+        // by right, the jfieldID initialization should be in a static
+        // initializer but we do it here instead to avoiding needing to
+        // load nio.dll during startup.
+        static jfieldID handle_fdID;
+        HANDLE h;
+        if (handle_fdID == NULL) {
+            jclass clazz = (*env)->FindClass(env, "java/io/FileDescriptor");
+            if (clazz == NULL)
+                return; // exception thrown
+            handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J");
+        }
+        h = jlong_to_ptr((*env)->GetLongField(env, fdo, handle_fdID));
+        result = FlushFileBuffers(h);
+        if (result == 0 && GetLastError() == ERROR_ACCESS_DENIED) {
+            // read-only mapping
+            result = 1;
+        }
+    }
+
     if (result == 0) {
         JNU_ThrowIOExceptionWithLastError(env, "Flush failed");
     }
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -36,22 +36,6 @@
 extern void addDisplayMode(JNIEnv* env, jobject arrayList, jint width,
                            jint height, jint bitDepth, jint refreshRate);
 
-void InitD3D(void *pReturn)
-{
-    J2dTraceLn(J2D_TRACE_INFO, "InitD3D");
-
-    jboolean *pRet = (jboolean *)pReturn;
-
-    D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
-    if (pMgr == NULL) {
-        J2dTraceLn(J2D_TRACE_ERROR, "InitD3D: could not create or init d3d");
-        *pRet = JNI_FALSE;
-    } else {
-        J2dTraceLn(J2D_TRACE_INFO, "InitD3D: successfully initialized d3d");
-        *pRet = JNI_TRUE;
-    }
-}
-
 extern "C" {
 /*
  * Class:     sun_java2d_d3d_D3DGraphicsDevice
@@ -63,8 +47,8 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "D3DGD_initD3D");
 
-    jboolean result = JNI_FALSE;
-    AwtToolkit::GetInstance().InvokeFunction(InitD3D, &result);
+    jboolean result = D3DInitializer::GetInstance().EnsureInited()
+                      ? JNI_TRUE : JNI_FALSE;
     J2dTraceLn1(J2D_TRACE_INFO, "D3DGD_initD3D: result=%x", result);
     return result;
 }
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -40,6 +40,7 @@
 
 D3DPipelineManager *D3DPipelineManager::pMgr = NULL;
 
+
 D3DPipelineManager * D3DPipelineManager::CreateInstance(void)
 {
     if (!IsD3DEnabled() ||
@@ -179,6 +180,12 @@
     HMONITOR hMon;
     int gdiScreen;
     D3DPipelineManager *pMgr;
+
+    // fix for 6946559: if d3d preloading fails jmv may be NULL
+    if (jvm == NULL) {
+        return;
+    }
+
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     pMgr = D3DPipelineManager::GetInstance();
@@ -934,3 +941,87 @@
     *ppd3dContext = pAdapters[adapterOrdinal].pd3dContext;
     return res;
 }
+
+
+//==============================================================
+// D3DInitializer
+//==============================================================
+
+D3DInitializer D3DInitializer::theInstance;
+
+D3DInitializer::D3DInitializer()
+    : bComInitialized(false), pAdapterIniters(NULL)
+{
+}
+
+D3DInitializer::~D3DInitializer()
+{
+    if (pAdapterIniters) {
+        delete[] pAdapterIniters;
+    }
+}
+
+void D3DInitializer::InitImpl()
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::InitImpl");
+    if (SUCCEEDED(::CoInitialize(NULL))) {
+        bComInitialized = true;
+    }
+    D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
+    if (pMgr != NULL) {
+        UINT adapterCount = pMgr->adapterCount;
+
+        pAdapterIniters = new D3DAdapterInitializer[adapterCount];
+        for (UINT i=0; i<adapterCount; i++) {
+            pAdapterIniters[i].setAdapter(i);
+            AwtToolkit::GetInstance().GetPreloadThread().AddAction(&pAdapterIniters[i]);
+        }
+    }
+}
+
+void D3DInitializer::CleanImpl(bool reInit)
+{
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)",
+                                    reInit ? "RELAUNCH" : "normal");
+    D3DPipelineManager::DeleteInstance();
+    if (bComInitialized) {
+        CoUninitialize();
+    }
+}
+
+
+void D3DInitializer::D3DAdapterInitializer::InitImpl()
+{
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter);
+
+    D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
+    if (pMgr == NULL) {
+        return;
+    }
+
+    D3DContext *pd3dContext;
+    pMgr->GetD3DContext(adapter, &pd3dContext);
+
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter);
+}
+
+void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit)
+{
+    // nothing to do - D3DPipelineManager cleans adapters
+}
+
+
+extern "C" {
+/*
+ * Export function to start D3D preloading
+ * (called from java/javaw - see src/windows/bin/java-md.c)
+ */
+__declspec(dllexport) int preloadD3D()
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "AWT warmup: preloadD3D");
+    AwtToolkit::GetInstance().GetPreloadThread().AddAction(&D3DInitializer::GetInstance());
+    return 1;
+}
+
+}
+
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.h	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.h	Tue Nov 09 22:53:18 2010 -0800
@@ -26,6 +26,7 @@
 
 #include "D3DPipeline.h"
 #include "D3DContext.h"
+#include "awt_Toolkit.h"
 
 typedef class D3DPipelineManager *LPD3DPIPELINEMANAGER;
 
@@ -38,11 +39,15 @@
 
 class D3DPIPELINE_API D3DPipelineManager
 {
-public:
+    friend class D3DInitializer;
+private:
     // creates and initializes instance of D3DPipelineManager, may return NULL
     static D3DPipelineManager* CreateInstance(void);
+
     // deletes the single instance of the manager
     static void DeleteInstance();
+
+public:
     // returns the single instance of the manager, may return NULL
     static D3DPipelineManager* GetInstance(void);
 
@@ -143,3 +148,40 @@
 #define OS_ALL (OS_VISTA|OS_WINSERV_2008|OS_WINXP|OS_WINXP_64|OS_WINSERV_2003)
 #define OS_UNKNOWN      (~OS_ALL)
 BOOL D3DPPLM_OsVersionMatches(USHORT osInfo);
+
+
+class D3DInitializer : public AwtToolkit::PreloadAction {
+private:
+    D3DInitializer();
+    ~D3DInitializer();
+
+protected:
+    // PreloadAction overrides
+    virtual void InitImpl();
+    virtual void CleanImpl(bool reInit);
+
+public:
+    static D3DInitializer& GetInstance() { return theInstance; }
+
+private:
+    // single instance
+    static D3DInitializer theInstance;
+
+    // adapter initializer class
+    class D3DAdapterInitializer : public AwtToolkit::PreloadAction {
+    public:
+        void setAdapter(UINT adapter) { this->adapter = adapter; }
+    protected:
+        // PreloadAction overrides
+        virtual void InitImpl();
+        virtual void CleanImpl(bool reInit);
+    private:
+        UINT adapter;
+    };
+
+    // the flag indicates success of COM initialization
+    bool bComInitialized;
+    D3DAdapterInitializer *pAdapterIniters;
+
+};
+
--- a/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -28,7 +28,8 @@
 #include "WindowsFlags.h"
 
 BOOL      accelReset;         // reset registry 2d acceleration settings
-BOOL      useD3D;             // d3d enabled flag
+BOOL      useD3D = TRUE;      // d3d enabled flag
+                              // initially is TRUE to allow D3D preloading
 BOOL      forceD3DUsage;      // force d3d on or off
 jboolean  g_offscreenSharing; // JAWT accelerated surface sharing
 BOOL      checkRegistry;      // Diagnostic tool: outputs 2d registry settings
--- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c	Tue Nov 09 22:53:18 2010 -0800
@@ -32,6 +32,7 @@
 #include <io.h>
 #include "nio.h"
 #include "nio_util.h"
+#include "jlong.h"
 
 
 /**************************************************************
@@ -441,3 +442,15 @@
 {
     closeFile(env, fd);
 }
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong hFile)
+{
+    HANDLE hProcess = GetCurrentProcess();
+    HANDLE hResult;
+    BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE,
+                               DUPLICATE_SAME_ACCESS);
+    if (res == 0)
+       JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed");
+    return ptr_to_jlong(hResult);
+}
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -540,34 +540,15 @@
 {
     TRY;
 
-    // get language, country, variant information
-    char * language = (char *)safe_Malloc(strlen(name) + 1);
-    char * country;
-    char * variant;
-    DASSERT(!safe_ExceptionOccurred(env));
-    strcpy(language, name);
-    for (country = language; *country != '_' && *country != '\0'; country++);
-    if (*country == '_') {
-        *country++ = '\0';
-        for (variant = country; *variant != '_' && *variant != '\0'; variant++);
-        if (*variant == '_') {
-            *variant++ = '\0';
-        }
-    } else {
-        variant = country;
-    }
-
     // create Locale object
-    jobject langObj = env->NewStringUTF(language);
-    jobject ctryObj = env->NewStringUTF(country);
-    jobject vrntObj = env->NewStringUTF(variant);
-    jobject localeObj = JNU_NewObjectByName(env, "java/util/Locale",
-                                            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
-                                            langObj, ctryObj, vrntObj);
-    free(language);
-    env->DeleteLocalRef(langObj);
-    env->DeleteLocalRef(ctryObj);
-    env->DeleteLocalRef(vrntObj);
+    jobject langtagObj = env->NewStringUTF(name);
+    jobject localeObj = JNU_CallStaticMethodByName(env,
+                                                   NULL,
+                                                   "java/util/Locale",
+                                                   "forLanguageTag",
+                                                   "(Ljava/lang/String;)Ljava/util/Locale;",
+                                                   langtagObj).l;
+    env->DeleteLocalRef(langtagObj);
 
     return localeObj;
 
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Tue Nov 09 22:53:18 2010 -0800
@@ -28,6 +28,7 @@
 #include "awt.h"
 #include <signal.h>
 #include <windowsx.h>
+#include <process.h>
 
 #include "awt_DrawingSurface.h"
 #include "awt_AWTEvent.h"
@@ -88,7 +89,7 @@
 
 /* Initialize the Java VM instance variable when the library is
    first loaded */
-JavaVM *jvm;
+JavaVM *jvm = NULL;
 
 JNIEXPORT jint JNICALL
 JNI_OnLoad(JavaVM *vm, void *reserved)
@@ -358,6 +359,95 @@
     return hwnd;
 }
 
+
+struct ToolkitThreadProc_Data {
+    bool result;
+    HANDLE hCompleted;
+
+    jobject thread;
+};
+
+void ToolkitThreadProc(void *param)
+{
+    ToolkitThreadProc_Data *data = (ToolkitThreadProc_Data *)param;
+
+    bool bNotified = false;
+
+    JNIEnv *env;
+    JavaVMAttachArgs attachArgs;
+    attachArgs.version  = JNI_VERSION_1_2;
+    attachArgs.name     = "AWT-Windows";
+    attachArgs.group    = NULL;
+
+    jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
+    if (res < 0) {
+        return;
+    }
+
+    jobject thread = env->NewGlobalRef(data->thread);
+    if (thread != NULL) {
+        jclass cls = env->GetObjectClass(thread);
+        if (cls != NULL) {
+            jmethodID runId = env->GetMethodID(cls, "run", "()V");
+            if (runId != NULL) {
+                data->result = true;
+                ::SetEvent(data->hCompleted);
+                bNotified = true;
+
+                env->CallVoidMethod(thread, runId);
+
+                if (env->ExceptionCheck()) {
+                    env->ExceptionDescribe();
+                    env->ExceptionClear();
+                    // TODO: handle
+                }
+            }
+            env->DeleteLocalRef(cls);
+        }
+        env->DeleteGlobalRef(thread);
+    }
+    if (!bNotified) {
+        ::SetEvent(data->hCompleted);
+    }
+
+    jvm->DetachCurrentThread();
+}
+
+/*
+ * Class:     sun_awt_windows_WToolkit
+ * Method:    startToolkitThread
+ * Signature: (Ljava/lang/Runnable;)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread)
+{
+    AwtToolkit& tk = AwtToolkit::GetInstance();
+
+    ToolkitThreadProc_Data data;
+    data.result = false;
+    data.thread = env->NewGlobalRef(thread);
+    if (data.thread == NULL) {
+        return JNI_FALSE;
+    }
+    data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    bool result = tk.GetPreloadThread()
+                    .InvokeAndTerminate(ToolkitThreadProc, &data);
+
+    if (result) {
+        ::WaitForSingleObject(data.hCompleted, INFINITE);
+        result = data.result;
+    } else {
+        // no awt preloading
+        // return back to the usual toolkit way
+    }
+    ::CloseHandle(data.hCompleted);
+
+    env->DeleteGlobalRef(data.thread);
+
+    return result ? JNI_TRUE : JNI_FALSE;
+}
+
 BOOL AwtToolkit::Initialize(BOOL localPump) {
     AwtToolkit& tk = AwtToolkit::GetInstance();
 
@@ -371,6 +461,11 @@
     // ComCtl32Util was constructed but not disposed
     ComCtl32Util::GetInstance().InitLibraries();
 
+    if (!localPump) {
+        // if preload thread was run, terminate it
+        preloadThread.Terminate(true);
+    }
+
     /* Register this toolkit's helper window */
     VERIFY(tk.RegisterClass() != NULL);
 
@@ -439,7 +534,7 @@
     // dispose Direct3D-related resources. This should be done
     // before AwtObjectList::Cleanup() as the d3d will attempt to
     // shutdown when the last of its windows is disposed of
-    D3DPipelineManager::DeleteInstance();
+    D3DInitializer::GetInstance().Clean();
 
     AwtObjectList::Cleanup();
     AwtFont::Cleanup();
@@ -1635,6 +1730,270 @@
     ::GetWindowRect(hWnd, lpRect);
 }
 
+
+/************************************************************************
+ * AWT preloading support
+ */
+bool AwtToolkit::PreloadAction::EnsureInited()
+{
+    DWORD _initThreadId = GetInitThreadID();
+    if (_initThreadId != 0) {
+        // already inited
+        // ensure the action is inited on correct thread
+        PreloadThread &preloadThread
+            = AwtToolkit::GetInstance().GetPreloadThread();
+        if (_initThreadId == preloadThread.GetThreadId()) {
+            if (!preloadThread.IsWrongThread()) {
+                return true;
+            }
+            // inited on preloadThread (wrongThread), not cleaned yet
+            // have to wait cleanup completion
+            preloadThread.Wait4Finish();
+        } else {
+            // inited on other thread (Toolkit thread?)
+            // consider as correctly inited
+            return true;
+        }
+    }
+
+    // init on Toolkit thread
+    AwtToolkit::GetInstance().InvokeFunction(InitWrapper, this);
+
+    return true;
+}
+
+DWORD AwtToolkit::PreloadAction::GetInitThreadID()
+{
+    CriticalSection::Lock lock(initLock);
+    return initThreadId;
+}
+
+bool AwtToolkit::PreloadAction::Clean()
+{
+    DWORD _initThreadId = GetInitThreadID();
+    if (_initThreadId == ::GetCurrentThreadId()) {
+        // inited on this thread
+        Clean(false);
+        return true;
+    }
+    return false;
+}
+
+/*static*/
+void AwtToolkit::PreloadAction::InitWrapper(void *param)
+{
+    PreloadAction *pThis = (PreloadAction *)param;
+    pThis->Init();
+}
+
+void AwtToolkit::PreloadAction::Init()
+{
+    CriticalSection::Lock lock(initLock);
+    if (initThreadId == 0) {
+        initThreadId = ::GetCurrentThreadId();
+        InitImpl();
+    }
+}
+
+void AwtToolkit::PreloadAction::Clean(bool reInit) {
+    CriticalSection::Lock lock(initLock);
+    if (initThreadId != 0) {
+        //ASSERT(initThreadId == ::GetCurrentThreadId());
+        CleanImpl(reInit);
+        initThreadId = 0;
+    }
+}
+
+// PreloadThread implementation
+AwtToolkit::PreloadThread::PreloadThread()
+    : status(None), wrongThread(false), threadId(0),
+    pActionChain(NULL), pLastProcessedAction(NULL),
+    execFunc(NULL), execParam(NULL)
+{
+    hFinished = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    hAwake = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+AwtToolkit::PreloadThread::~PreloadThread()
+{
+    //Terminate(false);
+    ::CloseHandle(hFinished);
+    ::CloseHandle(hAwake);
+}
+
+bool AwtToolkit::PreloadThread::AddAction(AwtToolkit::PreloadAction *pAction)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status > Preloading) {
+        // too late - the thread already terminated or run as toolkit thread
+        return false;
+    }
+
+    if (pActionChain == NULL) {
+        // 1st action
+        pActionChain = pAction;
+    } else {
+        // add the action to the chain
+        PreloadAction *pChain = pActionChain;
+        while (true) {
+            PreloadAction *pNext = pChain->GetNext();
+            if (pNext == NULL) {
+                break;
+            }
+            pChain = pNext;
+        }
+        pChain->SetNext(pAction);
+    }
+
+    if (status > None) {
+        // the thread is already running (status == Preloading)
+        AwakeThread();
+        return true;
+    }
+
+    // need to start thread
+    ::ResetEvent(hAwake);
+    ::ResetEvent(hFinished);
+
+    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0x100000, StaticThreadProc,
+                                            this, 0, &threadId);
+
+    if (hThread == 0) {
+        threadId = 0;
+        return false;
+    }
+
+    status = Preloading;
+
+    ::CloseHandle(hThread);
+
+    return true;
+}
+
+bool AwtToolkit::PreloadThread::Terminate(bool wrongThread)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status != Preloading) {
+        return false;
+    }
+
+    execFunc = NULL;
+    execParam = NULL;
+    this->wrongThread = wrongThread;
+    status = Cleaning;
+    AwakeThread();
+
+    return true;
+}
+
+bool AwtToolkit::PreloadThread::InvokeAndTerminate(void(_cdecl *fn)(void *), void *param)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status != Preloading) {
+        return false;
+    }
+
+    execFunc = fn;
+    execParam = param;
+    status = fn == NULL ? Cleaning : RunningToolkit;
+    AwakeThread();
+
+    return true;
+}
+
+/*static*/
+unsigned WINAPI AwtToolkit::PreloadThread::StaticThreadProc(void *param)
+{
+    AwtToolkit::PreloadThread *pThis = (AwtToolkit::PreloadThread *)param;
+    return pThis->ThreadProc();
+}
+
+unsigned AwtToolkit::PreloadThread::ThreadProc()
+{
+    void(_cdecl *_execFunc)(void *) = NULL;
+    void *_execParam = NULL;
+    bool _wrongThread = false;
+
+    // initialization
+    while (true) {
+        PreloadAction *pAction;
+        {
+            CriticalSection::Lock lock(threadLock);
+            if (status != Preloading) {
+                // get invoke parameters
+                _execFunc = execFunc;
+                _execParam = execParam;
+                _wrongThread = wrongThread;
+                break;
+            }
+            pAction = GetNextAction();
+        }
+        if (pAction != NULL) {
+            pAction->Init();
+        } else {
+            ::WaitForSingleObject(hAwake, INFINITE);
+        }
+    }
+
+    // call a function from InvokeAndTerminate
+    if (_execFunc != NULL) {
+        _execFunc(_execParam);
+    } else {
+        // time to terminate..
+    }
+
+    // cleanup
+    {
+        CriticalSection::Lock lock(threadLock);
+        pLastProcessedAction = NULL; // goto 1st action in the chain
+        status = Cleaning;
+    }
+    for (PreloadAction *pAction = GetNextAction(); pAction != NULL;
+            pAction = GetNextAction()) {
+        pAction->Clean(_wrongThread);
+    }
+
+    // don't clear threadId! it is used by PreloadAction::EnsureInited
+
+    {
+        CriticalSection::Lock lock(threadLock);
+        status = Finished;
+    }
+    ::SetEvent(hFinished);
+    return 0;
+}
+
+AwtToolkit::PreloadAction* AwtToolkit::PreloadThread::GetNextAction()
+{
+    CriticalSection::Lock lock(threadLock);
+    PreloadAction *pAction = (pLastProcessedAction == NULL)
+                                    ? pActionChain
+                                    : pLastProcessedAction->GetNext();
+    if (pAction != NULL) {
+        pLastProcessedAction = pAction;
+    }
+
+    return pAction;
+}
+
+
+extern "C" {
+
+/* Terminates preload thread (if it's still alive
+ * - it may occur if the application doesn't use AWT).
+ * The function is called from launcher after completion main java thread.
+ */
+__declspec(dllexport) void preloadStop()
+{
+    AwtToolkit::GetInstance().GetPreloadThread().Terminate(false);
+}
+
+}
+
+
 /************************************************************************
  * Toolkit native methods
  */
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Tue Nov 09 22:53:18 2010 -0800
@@ -465,6 +465,151 @@
 
     void InstallMouseLowLevelHook();
     void UninstallMouseLowLevelHook();
+
+
+/* AWT preloading (early Toolkit thread start)
+ */
+public:
+    /* Toolkit preload action class.
+     * Preload actions should be registered with
+     * AwtToolkit::getInstance().GetPreloadThread().AddAction().
+     * AwtToolkit thread calls InitImpl method at the beghining
+     * and CleanImpl(false) before exiting for all registered actions.
+     * If an application provides own Toolkit thread
+     * (sun.awt.windows.WToolkit.embeddedInit), the thread calls Clean(true)
+     * for each action.
+     */
+    class PreloadThread;    // forward declaration
+    class PreloadAction {
+        friend class PreloadThread;
+    public:
+        PreloadAction() : initThreadId(0), pNext(NULL) {}
+        virtual ~PreloadAction() {}
+
+    protected:
+        // called by PreloadThread or as result
+        // of EnsureInited() call (on Toolkit thread!).
+        virtual void InitImpl() = 0;
+
+        // called by PreloadThread (before exiting).
+        // reInit == false: normal shutdown;
+        // reInit == true: PreloadThread is shutting down due external
+        //   Toolkit thread was provided.
+        virtual void CleanImpl(bool reInit) = 0;
+
+    public:
+        // Initialized the action on the Toolkit thread if not yet initialized.
+        bool EnsureInited();
+
+        // returns thread ID which the action was inited on (0 if not inited)
+        DWORD GetInitThreadID();
+
+        // Allows to deinitialize action earlier.
+        // The method must be called on the Toolkit thread only.
+        // returns true on success,
+        //         false if the action was inited on other thread.
+        bool Clean();
+
+    private:
+        unsigned initThreadId;
+        // lock for Init/Clean
+        CriticalSection initLock;
+
+        // Chain support (for PreloadThread)
+        PreloadAction *pNext;   // for action chain used by PreloadThread
+        void SetNext(PreloadAction *pNext) { this->pNext = pNext; }
+        PreloadAction *GetNext() { return pNext; }
+
+        // wrapper for AwtToolkit::InvokeFunction
+        static void InitWrapper(void *param);
+
+        void Init();
+        void Clean(bool reInit);
+
+    };
+
+    /** Toolkit preload thread class.
+     */
+    class PreloadThread {
+    public:
+        PreloadThread();
+        ~PreloadThread();
+
+        // adds action & start the thread if not yet started
+        bool AddAction(PreloadAction *pAction);
+
+        // sets termination flag; returns true if the thread is running.
+        // wrongThread specifies cause of the termination:
+        //   false means termination on the application shutdown;
+        // wrongThread is used as reInit parameter for action cleanup.
+        bool Terminate(bool wrongThread);
+        bool InvokeAndTerminate(void(_cdecl *fn)(void *), void *param);
+
+        // waits for the the thread completion;
+        // use the method after Terminate() only if Terminate() returned true
+        INLINE void Wait4Finish() {
+            ::WaitForSingleObject(hFinished, INFINITE);
+        }
+
+        INLINE unsigned GetThreadId() {
+            CriticalSection::Lock lock(threadLock);
+            return threadId;
+        }
+        INLINE bool IsWrongThread() {
+            CriticalSection::Lock lock(threadLock);
+            return wrongThread;
+        }
+
+    private:
+        // data access lock
+        CriticalSection threadLock;
+
+        // the thread status
+        enum Status {
+            None = -1,      // initial
+            Preloading = 0, // preloading in progress
+            RunningToolkit, // Running as Toolkit thread
+            Cleaning,       // exited from Toolkit thread proc, cleaning
+            Finished        //
+        } status;
+
+        // "wrong thread" flag
+        bool wrongThread;
+
+        // thread proc (calls (this)param->ThreadProc())
+        static unsigned WINAPI StaticThreadProc(void *param);
+        unsigned ThreadProc();
+
+        INLINE void AwakeThread() {
+            ::SetEvent(hAwake);
+        }
+
+        // if threadId != 0 -> we are running
+        unsigned threadId;
+        // ThreadProc sets the event on exit
+        HANDLE hFinished;
+        // ThreadProc waits on the event for NewAction/Terminate/InvokeAndTerminate
+        HANDLE hAwake;
+
+        // function/param to invoke (InvokeAndTerminate)
+        // if execFunc == NULL => just terminate
+        void(_cdecl *execFunc)(void *);
+        void *execParam;
+
+        // action chain
+        PreloadAction *pActionChain;
+        PreloadAction *pLastProcessedAction;
+
+        // returns next action in the list (NULL if no more actions)
+        PreloadAction* GetNextAction();
+
+    };
+
+    INLINE PreloadThread& GetPreloadThread() { return preloadThread; }
+
+private:
+    PreloadThread preloadThread;
+
 };
 
 
--- a/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -117,16 +117,23 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
-                SecretKey masterKey = new SecretKeySpec(master, "TlsMasterSecret");
-                TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-                (masterKey, major, minor, clientRandom, serverRandom, cipherAlgorithm,
-                keyLength, expandedKeyLength, ivLength, macLength);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
+                SecretKey masterKey =
+                    new SecretKeySpec(master, "TlsMasterSecret");
+                TlsKeyMaterialParameterSpec spec =
+                    new TlsKeyMaterialParameterSpec(masterKey, major, minor,
+                        clientRandom, serverRandom, cipherAlgorithm,
+                        keyLength, expandedKeyLength, ivLength, macLength,
+                        null, -1, -1);
 
                 kg.init(spec);
-                TlsKeyMaterialSpec result = (TlsKeyMaterialSpec)kg.generateKey();
-                match(lineNumber, clientCipherBytes, result.getClientCipherKey());
-                match(lineNumber, serverCipherBytes, result.getServerCipherKey());
+                TlsKeyMaterialSpec result =
+                    (TlsKeyMaterialSpec)kg.generateKey();
+                match(lineNumber, clientCipherBytes,
+                    result.getClientCipherKey());
+                match(lineNumber, serverCipherBytes,
+                    result.getServerCipherKey());
                 match(lineNumber, clientIv, result.getClientIv());
                 match(lineNumber, serverIv, result.getServerIv());
                 match(lineNumber, clientMacBytes, result.getClientMacKey());
@@ -144,7 +151,8 @@
         System.out.println("OK: " + n + " tests");
     }
 
-    private static void match(int lineNumber, byte[] out, Object res) throws Exception {
+    private static void match(int lineNumber, byte[] out, Object res)
+            throws Exception {
         if ((out == null) || (res == null)) {
             if (out != res) {
                 throw new Exception("null mismatch line " + lineNumber);
--- a/jdk/test/com/sun/crypto/provider/TLS/TestMasterSecret.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestMasterSecret.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -97,17 +97,22 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsMasterSecret", provider);
-                SecretKey premasterKey = new SecretKeySpec(premaster, algorithm);
-                TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                    (premasterKey, protoMajor, protoMinor, clientRandom, serverRandom);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsMasterSecret", provider);
+                SecretKey premasterKey =
+                    new SecretKeySpec(premaster, algorithm);
+                TlsMasterSecretParameterSpec spec =
+                    new TlsMasterSecretParameterSpec(premasterKey, protoMajor,
+                        protoMinor, clientRandom, serverRandom,
+                        null, -1, -1);
                 kg.init(spec);
                 TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
                 byte[] enc = key.getEncoded();
                 if (Arrays.equals(master, enc) == false) {
                     throw new Exception("mismatch line: " + lineNumber);
                 }
-                if ((preMajor != key.getMajorVersion()) || (preMinor != key.getMinorVersion())) {
+                if ((preMajor != key.getMajorVersion()) ||
+                        (preMinor != key.getMinorVersion())) {
                     throw new Exception("version mismatch line: " + lineNumber);
                 }
             } else {
--- a/jdk/test/com/sun/crypto/provider/TLS/TestPRF.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPRF.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -85,14 +85,17 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsPrf", provider);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsPrf", provider);
                 SecretKey inKey;
                 if (secret == null) {
                     inKey = null;
                 } else {
                     inKey = new SecretKeySpec(secret, "Generic");
                 }
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(inKey, label, seed, length);
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        null, -1, -1);
                 kg.init(spec);
                 SecretKey key = kg.generateKey();
                 byte[] enc = key.getEncoded();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPRF12.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6313661
+ * @summary Basic known-answer-test for TlsPrf 12
+ *
+ * Vector obtained from the IETF TLS working group mailing list:
+ *
+ *     http://www.ietf.org/mail-archive/web/tls/current/msg03416.html
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.security.Security;
+import java.security.Provider;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import javax.crypto.spec.*;
+
+import sun.security.internal.spec.*;
+
+public class TestPRF12 extends Utils {
+
+    private static int PREFIX_LENGTH = "prf-output: ".length();
+
+    public static void main(String[] args) throws Exception {
+        Provider provider = Security.getProvider("SunJCE");
+
+        InputStream in = new FileInputStream(new File(BASE, "prf12data.txt"));
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+
+        int n = 0;
+        int lineNumber = 0;
+
+        byte[] secret = null;
+        String label = null;
+        byte[] seed = null;
+        int length = 0;
+        String prfAlg = null;
+        int prfHashLength = 0;
+        int prfBlockSize = 0;
+        byte[] output = null;
+
+        while (true) {
+            String line = reader.readLine();
+            lineNumber++;
+            if (line == null) {
+                break;
+            }
+            if (line.startsWith("prf-") == false) {
+                continue;
+            }
+
+            String data = line.substring(PREFIX_LENGTH);
+            if (line.startsWith("prf-secret:")) {
+                secret = parse(data);
+            } else if (line.startsWith("prf-label:")) {
+                label = data;
+            } else if (line.startsWith("prf-seed:")) {
+                seed = parse(data);
+            } else if (line.startsWith("prf-length:")) {
+                length = Integer.parseInt(data);
+            } else if (line.startsWith("prf-alg:")) {
+                prfAlg = data;
+                switch (prfAlg) {
+                case "SHA-224":
+                    prfHashLength = 28;
+                    prfBlockSize =  64;
+                    break;
+                case "SHA-256":
+                    prfHashLength = 32;
+                    prfBlockSize =  64;
+                    break;
+                case "SHA-384":
+                    prfHashLength = 48;
+                    prfBlockSize = 128;
+                    break;
+                case "SHA-512":
+                    prfHashLength = 64;
+                    prfBlockSize = 128;
+                    break;
+                default:
+                    throw new Exception("Unknown Alg in the data.");
+                }
+            } else if (line.startsWith("prf-output:")) {
+                output = parse(data);
+
+                System.out.print(".");
+                n++;
+
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTls12Prf", provider);
+                SecretKey inKey;
+                if (secret == null) {
+                    inKey = null;
+                } else {
+                    inKey = new SecretKeySpec(secret, "Generic");
+                }
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        prfAlg, prfHashLength, prfBlockSize);
+                kg.init(spec);
+                SecretKey key = kg.generateKey();
+                byte[] enc = key.getEncoded();
+                if (Arrays.equals(output, enc) == false) {
+                    throw new Exception("mismatch line: " + lineNumber);
+                }
+            } else {
+                throw new Exception("Unknown line: " + line);
+            }
+        }
+        if (n == 0) {
+            throw new Exception("no tests");
+        }
+        in.close();
+        System.out.println();
+        System.out.println("OK: " + n + " tests");
+    }
+
+}
--- a/jdk/test/com/sun/crypto/provider/TLS/TestPremaster.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPremaster.java	Tue Nov 09 22:53:18 2010 -0800
@@ -60,7 +60,8 @@
         System.out.println("Done.");
     }
 
-    private static void test(KeyGenerator kg, int major, int minor) throws Exception {
+    private static void test(KeyGenerator kg, int major, int minor)
+            throws Exception {
 
         kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
         SecretKey key = kg.generateKey();
@@ -69,7 +70,8 @@
             throw new Exception("length: " + encoded.length);
         }
         if ((encoded[0] != major) || (encoded[1] != minor)) {
-            throw new Exception("version mismatch: "  + encoded[0] + "." + encoded[1]);
+            throw new Exception("version mismatch: "  + encoded[0] +
+                "." + encoded[1]);
         }
         System.out.println("OK: " + major + "." + minor);
     }
--- a/jdk/test/com/sun/crypto/provider/TLS/Utils.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/com/sun/crypto/provider/TLS/Utils.java	Tue Nov 09 22:53:18 2010 -0800
@@ -22,7 +22,6 @@
  */
 
 import java.io.*;
-import java.util.*;
 
 class Utils {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/TLS/prf12data.txt	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,19 @@
+prf-secret: 9b:be:43:6b:a9:40:f0:17:b1:76:52:84:9a:71:db:35
+prf-seed:   a0:ba:9f:93:6c:da:31:18:27:a6:f7:96:ff:d5:19:8c
+prf-label:  test label
+prf-length: 100
+prf-alg:    SHA-256
+prf-output: e3:f2:29:ba:72:7b:e1:7b:8d:12:26:20:55:7c:d4:53:c2:aa:b2:1d:07:c3:d4:95:32:9b:52:d4:e6:1e:db:5a:6b:30:17:91:e9:0d:35:c9:c9:a4:6b:4e:14:ba:f9:af:0f:a0:22:f7:07:7d:ef:17:ab:fd:37:97:c0:56:4b:ab:4f:bc:91:66:6e:9d:ef:9b:97:fc:e3:4f:79:67:89:ba:a4:80:82:d1:22:ee:42:c5:a7:2e:5a:51:10:ff:f7:01:87:34:7b:66
+prf-secret: b8:0b:73:3d:6c:ee:fc:dc:71:56:6e:a4:8e:55:67:df
+prf-seed:   cd:66:5c:f6:a8:44:7d:d6:ff:8b:27:55:5e:db:74:65
+prf-label:  test label
+prf-length: 148
+prf-alg:    SHA-384
+prf-output: 7b:0c:18:e9:ce:d4:10:ed:18:04:f2:cf:a3:4a:33:6a:1c:14:df:fb:49:00:bb:5f:d7:94:21:07:e8:1c:83:cd:e9:ca:0f:aa:60:be:9f:e3:4f:82:b1:23:3c:91:46:a0:e5:34:cb:40:0f:ed:27:00:88:4f:9d:c2:36:f8:0e:dd:8b:fa:96:11:44:c9:e8:d7:92:ec:a7:22:a7:b3:2f:c3:d4:16:d4:73:eb:c2:c5:fd:4a:bf:da:d0:5d:91:84:25:9b:5b:f8:cd:4d:90:fa:0d:31:e2:de:c4:79:e4:f1:a2:60:66:f2:ee:a9:a6:92:36:a3:e5:26:55:c9:e9:ae:e6:91:c8:f3:a2:68:54:30:8d:5e:aa:3b:e8:5e:09:90:70:3d:73:e5:6f
+prf-secret: b0:32:35:23:c1:85:35:99:58:4d:88:56:8b:bb:05:eb
+prf-seed:   d4:64:0e:12:e4:bc:db:fb:43:7f:03:e6:ae:41:8e:e5
+prf-label:  test label
+prf-length: 196
+prf-alg:    SHA-512
+prf-output: 12:61:f5:88:c7:98:c5:c2:01:ff:03:6e:7a:9c:b5:ed:cd:7f:e3:f9:4c:66:9a:12:2a:46:38:d7:d5:08:b2:83:04:2d:f6:78:98:75:c7:14:7e:90:6d:86:8b:c7:5c:45:e2:0e:b4:0c:1c:f4:a1:71:3b:27:37:1f:68:43:25:92:f7:dc:8e:a8:ef:22:3e:12:ea:85:07:84:13:11:bf:68:65:3d:0c:fc:40:56:d8:11:f0:25:c4:5d:df:a6:e6:fe:c7:02:f0:54:b4:09:d6:f2:8d:d0:a3:23:3e:49:8d:a4:1a:3e:75:c5:63:0e:ed:be:22:fe:25:4e:33:a1:b0:e9:f6:b9:82:66:75:be:c7:d0:1a:84:56:58:dc:9c:39:75:45:40:1d:40:b9:f4:6c:7a:40:0e:e1:b8:f8:1c:a0:a6:0d:1a:39:7a:10:28:bf:f5:d2:ef:50:66:12:68:42:fb:8d:a4:19:76:32:bd:b5:4f:f6:63:3f:86:bb:c8:36:e6:40:d4:d8:98
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_BasicStroke.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests BasicStroke encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.BasicStroke;
+
+public final class java_awt_BasicStroke extends AbstractTest<BasicStroke> {
+    public static void main(String[] args) {
+        new java_awt_BasicStroke().test(true);
+    }
+
+    protected BasicStroke getObject() {
+        return new BasicStroke();
+    }
+
+    protected BasicStroke getAnotherObject() {
+        float[] f = {1.0f, 2.0f, 3.0f, 4.0f};
+        return new BasicStroke(f[1], BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, f[2], f, f[3]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_GradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests GradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+
+public final class java_awt_GradientPaint extends AbstractTest<GradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_GradientPaint().test(true);
+    }
+
+    protected GradientPaint getObject() {
+        return new GradientPaint(0.1f, 0.2f, Color.BLACK, 0.3f, 0.4f, Color.WHITE, true);
+    }
+
+    protected GradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        return new GradientPaint(0.4f, 0.3f, Color.WHITE, 0.2f, 0.1f, Color.BLACK, false);*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_LinearGradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests LinearGradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.LinearGradientPaint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import static java.awt.MultipleGradientPaint.ColorSpaceType.LINEAR_RGB;
+import static java.awt.MultipleGradientPaint.CycleMethod.REFLECT;
+
+public final class java_awt_LinearGradientPaint extends AbstractTest<LinearGradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_LinearGradientPaint().test(true);
+    }
+
+    protected LinearGradientPaint getObject() {
+        float[] f = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f };
+        Color[] c = { Color.BLUE, Color.GREEN, Color.RED, Color.BLUE, Color.GREEN, Color.RED };
+        return new LinearGradientPaint(f[0], f[1], f[2], f[3], f, c);
+    }
+
+    protected LinearGradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        float[] f = { 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f };
+        Color[] c = { Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE };
+        return new LinearGradientPaint(
+                new Point2D.Float(f[0], f[1]),
+                new Point2D.Float(f[2], f[3]),
+                f, c, REFLECT, LINEAR_RGB,
+                new AffineTransform(f));*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_RadialGradientPaint.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests RadialGradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import static java.awt.MultipleGradientPaint.ColorSpaceType.LINEAR_RGB;
+import static java.awt.MultipleGradientPaint.CycleMethod.REFLECT;
+
+public final class java_awt_RadialGradientPaint extends AbstractTest<RadialGradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_RadialGradientPaint().test(true);
+    }
+
+    protected RadialGradientPaint getObject() {
+        float[] f = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f };
+        Color[] c = { Color.BLUE, Color.GREEN, Color.RED, Color.BLUE, Color.GREEN, Color.RED };
+        return new RadialGradientPaint(f[0], f[1], f[2], f, c);
+    }
+
+    protected RadialGradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        float[] f = { 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f };
+        Color[] c = { Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE };
+        return new RadialGradientPaint(
+                new Point2D.Float(f[0], f[1]), 100.0f,
+                new Point2D.Float(f[2], f[3]),
+                f, c, REFLECT, LINEAR_RGB,
+                new AffineTransform(f));*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_geom_AffineTransform.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests AffineTransform encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.geom.AffineTransform;
+
+public final class java_awt_geom_AffineTransform extends AbstractTest<AffineTransform> {
+    public static void main(String[] args) {
+        new java_awt_geom_AffineTransform().test(true);
+    }
+
+    protected AffineTransform getObject() {
+        return new AffineTransform(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f);
+    }
+
+    protected AffineTransform getAnotherObject() {
+        return new AffineTransform(0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/javax_swing_border_StrokeBorder.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4358979
+ * @summary Tests StrokeBorder encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import javax.swing.border.StrokeBorder;
+
+public final class javax_swing_border_StrokeBorder extends AbstractTest<StrokeBorder> {
+    public static void main(String[] args) {
+        new javax_swing_border_StrokeBorder().test(true);
+    }
+
+    protected StrokeBorder getObject() {
+        return new StrokeBorder(new BasicStroke(0), Color.WHITE);
+    }
+
+    protected StrokeBorder getAnotherObject() {
+        return null; // TODO: could not update property
+        //return new StrokeBorder(new BasicStroke(1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/EnsureCapacity.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6955504 6992121
+ * @summary Test the StringBuilder.ensureCapacity() with negative minimumCapacity
+ *    and append() method with negative length input argument.
+ *    Also, test the StringBuffer class.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+    public static void main(String[] args) {
+        testStringBuilder();
+        testStringBuffer();
+    }
+
+    private static void checkCapacity(int before, int after) {
+        if (before != after) {
+            throw new RuntimeException("capacity is expected to be unchanged: " +
+                "before=" + before + " after=" + after);
+        }
+    }
+
+    private static void testStringBuilder() {
+        StringBuilder sb = new StringBuilder("abc");
+        int cap = sb.capacity();
+
+        // test if negative minimumCapacity
+        sb.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, sb.capacity());
+
+        try {
+            char[] str = {'a', 'b', 'c', 'd'};
+            // test if negative length
+            sb.append(str, 0, Integer.MIN_VALUE + 10);
+            throw new RuntimeException("IndexOutOfBoundsException not thrown");
+        } catch (IndexOutOfBoundsException ex) {
+        }
+    }
+
+    private static void testStringBuffer() {
+        StringBuffer sb = new StringBuffer("abc");
+        int cap = sb.capacity();
+
+        // test if negative minimumCapacity
+        sb.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, sb.capacity());
+
+        try {
+            char[] str = {'a', 'b', 'c', 'd'};
+            // test if negative length
+            sb.append(str, 0, Integer.MIN_VALUE + 10);
+            throw new RuntimeException("IndexOutOfBoundsException not thrown");
+        } catch (IndexOutOfBoundsException ex) {
+        }
+    }
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     4959889
+ * @bug     4959889 6992968
  * @summary Basic unit test of memory management testing:
  *          1) setCollectionUsageThreshold() and getCollectionUsageThreshold()
  *          2) test notification emitted for two different memory pools.
@@ -34,8 +34,10 @@
  * @run main/timeout=300 CollectionUsageThreshold
  */
 
+import java.lang.Thread.*;
 import java.lang.management.*;
 import java.util.*;
+import java.util.concurrent.*;
 import javax.management.*;
 import javax.management.openmbean.CompositeData;
 
@@ -52,6 +54,12 @@
     private static Checker checker;
     private static int numGCs = 0;
 
+    // semaphore to signal the arrival of a low memory notification
+    private static Semaphore signals = new Semaphore(0);
+    // barrier for the main thread to wait until the checker thread
+    // finishes checking the low memory notification result
+    private static CyclicBarrier barrier = new CyclicBarrier(2);
+
     static class PoolRecord {
         private MemoryPoolMXBean pool;
         private int listenerInvoked = 0;
@@ -98,10 +106,9 @@
                 }
                 pr.addNotification(minfo);
                 synchronized (this) {
+                    System.out.println("notifying the checker thread to check result");
                     numNotifs++;
-                    if (numNotifs > 0 && (numNotifs % EXPECTED_NUM_POOLS) == 0) {
-                        checker.goCheckResult();
-                    }
+                    signals.release();
                 }
             }
         }
@@ -134,6 +141,9 @@
         }
 
         try {
+            // This test creates a checker thread responsible for checking
+            // the low memory notifications.  It blocks until a permit
+            // from the signals semaphore is available.
             checker = new Checker("Checker thread");
             checker.setDaemon(true);
             checker.start();
@@ -148,9 +158,18 @@
             NotificationEmitter emitter = (NotificationEmitter) mm;
             emitter.addNotificationListener(listener, null, null);
 
+            // The main thread invokes GC to trigger the VM to perform
+            // low memory detection and then waits until the checker thread
+            // finishes its work to check for a low-memory notification.
+            //
+            // At GC time, VM will issue low-memory notification and invoke
+            // the listener which will release a permit to the signals semaphore.
+            // When the checker thread acquires the permit and finishes
+            // checking the low-memory notification, it will also call
+            // barrier.await() to signal the main thread to resume its work.
             for (int i = 0; i < NUM_GCS; i++) {
                 invokeGC();
-                checker.waitForCheckResult();
+                barrier.await();
             }
         } finally {
             // restore the default
@@ -166,6 +185,7 @@
 
     }
 
+
     private static void invokeGC() {
         System.out.println("Calling System.gc()");
         numGCs++;
@@ -180,8 +200,6 @@
     }
 
     static class Checker extends Thread {
-        private Object lock = new Object();
-        private Object go = new Object();
         private boolean checkerReady = false;
         private int waiters = 0;
         private boolean readyToCheck = false;
@@ -190,83 +208,48 @@
         };
         public void run() {
             while (true) {
-                synchronized (lock) {
-                    checkerReady = true;
-                    try {
-                        lock.wait();
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
+                try {
+                    signals.acquire(EXPECTED_NUM_POOLS);
                     checkResult();
-                    checkerReady = false;
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                } catch (BrokenBarrierException e) {
+                    throw new RuntimeException(e);
                 }
             }
         }
-        private void checkResult() {
+        private void checkResult() throws InterruptedException, BrokenBarrierException {
             for (PoolRecord pr : result.values()) {
                 if (pr.getListenerInvokedCount() != numGCs) {
-                    throw new RuntimeException("Listeners invoked count = " +
+                    fail("Listeners invoked count = " +
                          pr.getListenerInvokedCount() + " expected to be " +
                          numGCs);
                 }
                 if (pr.getNotifCount() != numGCs) {
-                    throw new RuntimeException("Notif Count = " +
+                    fail("Notif Count = " +
                          pr.getNotifCount() + " expected to be " +
                          numGCs);
                 }
 
                 long count = pr.getPool().getCollectionUsageThresholdCount();
                 if (count != numGCs) {
-                    throw new RuntimeException("CollectionUsageThresholdCount = " +
+                    fail("CollectionUsageThresholdCount = " +
                          count + " expected to be " + numGCs);
                 }
                 if (!pr.getPool().isCollectionUsageThresholdExceeded()) {
-                    throw new RuntimeException("isCollectionUsageThresholdExceeded" +
+                    fail("isCollectionUsageThresholdExceeded" +
                          " expected to be true");
                 }
             }
-            synchronized (go) {
-                // wait until the main thread is waiting for notification
-                while (waiters == 0) {
-                    try {
-                        go.wait(50);
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
-                }
-
-                System.out.println(Thread.currentThread().getName() +
-                    " notifying main thread to continue - result checking finished");
-                go.notify();
-            }
-        }
-        public void goCheckResult() {
-            System.out.println(Thread.currentThread().getName() +
-                " notifying to check result");
-            synchronized (lock) {
-                while (!checkerReady) {
-                    try {
-                        lock.wait(50);
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
-                }
-                lock.notify();
-            }
+            // wait until the main thread is waiting for notification
+            barrier.await();
+            System.out.println("notifying main thread to continue - result checking finished");
         }
 
-        public void waitForCheckResult() {
-            System.out.println(Thread.currentThread().getName() +
-                " waiting for result checking finishes");
-            synchronized (go) {
-                waiters++;
-                try {
-                    go.wait();
-                } catch (InterruptedException e) {
-                    // ignore
-                }
-                waiters--;
-            }
+        private void fail(String msg) {
+            // reset the barrier to cause BrokenBarrierException to avoid hanging
+            barrier.reset();
+            throw new RuntimeException(msg);
         }
     }
 }
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh	Tue Nov 09 22:53:18 2010 -0800
@@ -27,6 +27,7 @@
 # @summary Test CollectionUsageThreshold with concurrent marksweep collector
 # @author  Mandy Chung
 #
+# @ignore  6982965
 # @run build CollectionUsageThreshold
 # @run shell/timeout=300 CollectionUsageThresholdConcMarkSweepGC.sh
 #
--- a/jdk/test/java/nio/MappedByteBuffer/Basic.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/nio/MappedByteBuffer/Basic.java	Tue Nov 09 22:53:18 2010 -0800
@@ -24,7 +24,6 @@
 /* @test
  * @bug 4462336 6799037
  * @summary Simple MappedByteBuffer tests
- * @run main/othervm Basic
  */
 
 import java.io.*;
@@ -76,5 +75,10 @@
             throw new RuntimeException("Incorrect isReadOnly");
         fc.close();
         raf.close();
+
+        // clean-up
+        mbb = null;
+        System.gc();
+        Thread.sleep(500);
     }
 }
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Tue Nov 09 22:53:18 2010 -0800
@@ -89,10 +89,9 @@
             }
             // create channel that is bound to group
             AsynchronousChannel ch;
-            switch (rand.nextInt(3)) {
+            switch (rand.nextInt(2)) {
                 case 0 : ch = AsynchronousSocketChannel.open(group); break;
                 case 1 : ch = AsynchronousServerSocketChannel.open(group); break;
-                case 2 : ch = AsynchronousDatagramChannel.open(null, group); break;
                 default : throw new AssertionError();
             }
             group.shutdown();
@@ -128,18 +127,9 @@
             }
 
             // I/O in progress
-            AsynchronousChannel ch;
-            if (rand.nextBoolean()) {
-                AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel
-                    .open(group).bind(new InetSocketAddress(0));
-                listener.accept();
-                ch = listener;
-            } else {
-                AsynchronousDatagramChannel adc =
-                    AsynchronousDatagramChannel.open(null, group);
-                adc.receive(ByteBuffer.allocate(100));
-                ch = adc;
-            }
+            AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel
+                .open(group).bind(new InetSocketAddress(0));
+            ch.accept();
 
             // forceful shutdown
             group.shutdownNow();
--- a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Tue Nov 09 11:45:00 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +0,0 @@
-/*
- * Copyright (c) 2008, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @bug 4527345 6842687
- * @summary Unit test for AsynchronousDatagramChannel
- */
-
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.net.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-public class Basic {
-
-    public static void main(String[] args) throws Exception {
-        doReceiveTests();
-        doReadTests();
-        doSendTests();
-        doWriteTests();
-        doCancelTests();
-        doMulticastTests();
-    }
-
-    // basic receive tests
-    static void doReceiveTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        final SocketAddress sa = new InetSocketAddress(rh, port);
-
-        DatagramChannel sender = DatagramChannel.open();
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-
-        // Test: datagram packet received immediately
-        sender.send(ByteBuffer.wrap(msg), sa);
-        dst.clear();
-        ch.receive(dst).get(1, TimeUnit.SECONDS);
-        if (dst.flip().remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes read");
-
-        // Test: datagram packet not received immediately
-        dst.clear();
-        final CountDownLatch latch = new CountDownLatch(1);
-        ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-                latch.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        Thread.sleep(2000);
-        sender.send(ByteBuffer.wrap(msg), sa);
-        latch.await(2, TimeUnit.SECONDS);  // wait for completion handler
-
-        // Test: timeout
-        dst.clear();
-        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
-        ch.receive(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        Throwable result;
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof InterruptedByTimeoutException))
-            throw new RuntimeException("InterruptedByTimeoutException expected");
-
-        // AsynchronousCloseException
-        dst = ByteBuffer.allocateDirect(100);
-        exception.set(null);
-        ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        ch.close();
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof AsynchronousCloseException))
-            throw new RuntimeException("AsynchronousCloseException expected");
-
-        // done
-        sender.close();
-    }
-
-    // basic read tests
-    static void doReadTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-        InetAddress lh = InetAddress.getLocalHost();
-        final SocketAddress sa = new InetSocketAddress(lh, port);
-
-        DatagramChannel sender = DatagramChannel.open();
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-
-        // Test: not connected
-        try {
-            ch.read(dst);
-            throw new RuntimeException("NotYetConnectedException expected");
-        } catch (NotYetConnectedException e) {
-        }
-
-        // connect the channel
-        sender.bind(new InetSocketAddress(0));
-        ch.connect(new InetSocketAddress(lh,
-                ((InetSocketAddress)(sender.getLocalAddress())).getPort()));
-
-        // Test: datagram packet received immediately
-        sender.send(ByteBuffer.wrap(msg), sa);
-        dst.clear();
-        ch.read(dst).get(1, TimeUnit.SECONDS);
-        if (dst.flip().remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes read");
-
-        // Test: datagram packet not received immediately
-        dst.clear();
-        final CountDownLatch l1 = new CountDownLatch(1);
-        ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-                l1.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        Thread.sleep(2000);
-        sender.send(ByteBuffer.wrap(msg), sa);
-        l1.await(2, TimeUnit.SECONDS);
-
-        // Test: timeout
-        dst.clear();
-        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
-        ch.read(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        Throwable result;
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof InterruptedByTimeoutException))
-            throw new RuntimeException("InterruptedByTimeoutException expected");
-
-        // AsynchronousCloseException
-        dst.clear();
-        exception.set(null);
-        ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        ch.close();
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof AsynchronousCloseException))
-            throw new RuntimeException("AsynchronousCloseException expected");
-
-        // done
-        sender.close();
-    }
-
-    // basic send tests
-    static void doSendTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        DatagramChannel reader = DatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        SocketAddress sa = new InetSocketAddress(rh, port);
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
-
-        // Test: send datagram packet to reader
-        int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get();
-        if (bytesSent != msg.length)
-            throw new RuntimeException("Unexpected number of bytes sent");
-
-        // check received
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: send datagram packet to reader and check completion handler
-        // is invoked
-        final CountDownLatch l2 = new CountDownLatch(1);
-        ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                if (bytesSent != msg.length)
-                    throw new RuntimeException("Unexpected number of bytes received");
-                l2.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        l2.await(5, TimeUnit.SECONDS);
-
-        // check received
-        dst.clear();
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: check that failed method is invoked
-        ch.close();
-        final CountDownLatch l3 = new CountDownLatch(1);
-        ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                throw new RuntimeException("completed method invoked");
-            }
-            public void failed (Throwable exc, Void att) {
-                if (exc instanceof ClosedChannelException) {
-                    l3.countDown();
-                } else {
-                    throw new RuntimeException(exc);
-                }
-            }
-        });
-        l3.await(5, TimeUnit.SECONDS);
-
-        // done
-        reader.close();
-    }
-
-    // basic write tests
-    static void doWriteTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        DatagramChannel reader = DatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        SocketAddress sa = new InetSocketAddress(rh, port);
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
-
-        // Test: unconnected
-        try {
-            ch.write(ByteBuffer.wrap(msg)).get();
-            throw new RuntimeException("NotYetConnectedException expected");
-        } catch (NotYetConnectedException e) {
-        }
-
-        // Test: connect, and write datagram
-        ch.connect(sa);
-        int bytesSent = ch.write(ByteBuffer.wrap(msg)).get();
-        if (bytesSent != msg.length)
-            throw new RuntimeException("Unexpected number of bytes sent");
-
-        // check received
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: write datagram and check completion handler is invoked
-        final CountDownLatch l2 = new CountDownLatch(1);
-        ch.write(ByteBuffer.wrap(msg), (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                if (bytesSent != msg.length)
-                    throw new RuntimeException("Unexpected number of bytes received");
-                l2.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        l2.await(5, TimeUnit.SECONDS);
-
-        // check received
-        dst.clear();
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // done
-        ch.close();
-        reader.close();
-    }
-
-    static void cancelAndCheck(Future<?> result)
-        throws InterruptedException
-    {
-        boolean cancelled = result.cancel(false);
-        if (!cancelled)
-            throw new RuntimeException("Not cancelled");
-        if (!result.isDone())
-            throw new RuntimeException("Should be done");
-        try {
-            result.get();
-            throw new RuntimeException("Result not expected");
-        } catch (CancellationException e) {
-            // expected
-        } catch (ExecutionException e) {
-            throw new RuntimeException("Should not fail");
-        }
-    }
-
-    // basic cancel tests
-    static void doCancelTests() throws Exception {
-        InetAddress lh = InetAddress.getLocalHost();
-
-        // receive
-        for (int i=0; i<2; i++) {
-            AsynchronousDatagramChannel ch =
-                AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
-            Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100));
-            cancelAndCheck(remote);
-            ch.close();
-        }
-
-        // read
-        for (int i=0; i<2; i++) {
-            AsynchronousDatagramChannel ch =
-                AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
-             ch.connect(new InetSocketAddress(lh,
-                ((InetSocketAddress)(ch.getLocalAddress())).getPort()));
-            final CountDownLatch latch = new CountDownLatch(1);
-            long timeout = (i == 0) ? 0L : 60L;
-            Future<Integer> result = ch.read(ByteBuffer.allocate(100));
-            cancelAndCheck(result);
-            ch.close();
-        }
-    }
-
-    // basic multicast test
-    static void doMulticastTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        InetAddress lh = InetAddress.getLocalHost();
-        NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
-        if (interf.isLoopback() || !interf.supportsMulticast()) {
-            System.out.println("Multicasting not tested");
-            return;
-        }
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
-            .open(StandardProtocolFamily.INET, null)
-            .setOption(StandardSocketOption.SO_REUSEADDR, true)
-            .bind(new InetSocketAddress(0));
-
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-
-        // join group
-        InetAddress group = InetAddress.getByName("225.4.5.6");
-        MembershipKey key = ch.join(group, interf);
-
-        // check key
-        if (key.channel() != ch)
-            throw new RuntimeException("Not the expected channel");
-
-        // send message to group
-        DatagramChannel sender = DatagramChannel.open();
-        sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port));
-        sender.close();
-
-        // check message received
-        ByteBuffer dst = ByteBuffer.allocate(200);
-        SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS);
-        if (!((InetSocketAddress)source).getAddress().equals(lh))
-            throw new RuntimeException("Unexpected source");
-
-        // done
-        ch.close();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/DatagramChannel/ChangingAddress.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6431343
+ * @summary Test that DatagramChannel.getLocalAddress returns the right local
+ *    address after connect/disconnect.
+ */
+import java.net.*;
+import java.nio.channels.DatagramChannel;
+
+public class ChangingAddress {
+
+    // Checks that the given DatagramSocket and DatagramChannel are bound to the
+    // same local address.
+    static void check(DatagramSocket ds, DatagramChannel dc) {
+        InetAddress expected = ds.getLocalAddress();
+        InetAddress actual = dc.socket().getLocalAddress();
+        // okay if one bound to 0.0.0.0 and the other to ::0
+        if ((expected.isAnyLocalAddress() != actual.isAnyLocalAddress()) &&
+            !expected.equals(actual))
+        {
+            throw new RuntimeException("Expected: " + expected + ", actual: " + actual);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        InetAddress lh = InetAddress.getLocalHost();
+        SocketAddress remote = new InetSocketAddress(lh, 1234);
+
+        DatagramSocket ds = null;
+        DatagramChannel dc = null;
+        try {
+
+            ds = new DatagramSocket();
+            dc = DatagramChannel.open().bind(new InetSocketAddress(0));
+            check(ds, dc);
+
+            ds.connect(remote);
+            dc.connect(remote);
+            check(ds, dc);
+
+            ds.disconnect();
+            dc.disconnect();
+            check(ds, dc);
+
+            // repeat tests using socket adapter
+            ds.connect(remote);
+            dc.socket().connect(remote);
+            check(ds, dc);
+
+            ds.disconnect();
+            dc.socket().disconnect();
+            check(ds, dc);
+
+       } finally {
+            if (ds != null) ds.close();
+            if (dc != null) dc.close();
+       }
+    }
+}
--- a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,6 @@
 
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.io.IOException;
@@ -59,11 +58,4 @@
     {
         throw new RuntimeException();
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
-    {
-        throw new RuntimeException();
-    }
 }
--- a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,6 @@
 
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.io.IOException;
@@ -59,11 +58,4 @@
     {
         throw new RuntimeException();
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
-    {
-        throw new RuntimeException();
-    }
 }
--- a/jdk/test/java/nio/file/Path/InterruptCopy.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/nio/file/Path/InterruptCopy.java	Tue Nov 09 22:53:18 2010 -0800
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6993267
  * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option
  * @library ..
  * @run main/othervm -XX:-UseVMInterruptibleIO InterruptCopy
@@ -36,8 +36,9 @@
 
 public class InterruptCopy {
 
-    private static final long FILE_SIZE_TO_COPY = 512 * 1024 * 1024;
+    private static final long FILE_SIZE_TO_COPY = 512L * 1024L * 1024L;
     private static final int DELAY_IN_MS = 500;
+    private static final int DURATION_MAX_IN_MS = 5000;
 
     public static void main(String[] args) throws Exception {
         Path dir = TestUtil.createTemporaryDirectory();
@@ -81,20 +82,27 @@
         try {
             // copy source to target in main thread, interrupting it after a delay
             final Thread me = Thread.currentThread();
-            pool.schedule(new Runnable() {
+            Future<?> wakeup = pool.schedule(new Runnable() {
                 public void run() {
                     me.interrupt();
                 }}, DELAY_IN_MS, TimeUnit.MILLISECONDS);
             System.out.println("Copying file...");
             try {
+                long start = System.currentTimeMillis();
                 source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE);
-                throw new RuntimeException("Copy completed (this is not expected)");
+                long duration = System.currentTimeMillis() - start;
+                if (duration > DURATION_MAX_IN_MS)
+                    throw new RuntimeException("Copy was not interrupted");
             } catch (IOException e) {
                 boolean interrupted = Thread.interrupted();
                 if (!interrupted)
                     throw new RuntimeException("Interrupt status was not set");
                 System.out.println("Copy failed (this is expected)");
             }
+            try {
+                wakeup.get();
+            } catch (InterruptedException ignore) { }
+            Thread.interrupted();
 
             // copy source to target via task in thread pool, interrupting it after
             // a delay using cancel(true)
@@ -113,7 +121,6 @@
             System.out.println("Copy cancelled.");
         } finally {
             pool.shutdown();
-            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ArrayList/EnsureCapacity.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6992121
+ * @summary Test the ArrayList.ensureCapacity() and Vector.ensureCapacity
+ *    method with negative minimumCapacity input argument.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+    public static void main(String[] args) {
+        testArrayList();
+        testVector();
+    }
+
+    private static void checkCapacity(int before, int after) {
+        if (before != after) {
+            throw new RuntimeException("capacity is expected to be unchanged: " +
+                "before=" + before + " after=" + after);
+        }
+    }
+
+    private static void testArrayList() {
+        ArrayList<String> al = new ArrayList<String>();
+        al.add("abc");
+        al.ensureCapacity(Integer.MIN_VALUE);
+
+        // there is no method to query the capacity of ArrayList
+        // so before and after capacity are not checked
+    }
+
+    private static void testVector() {
+        Vector<String> vector = new Vector<String>();
+        vector.add("abc");
+
+        int cap = vector.capacity();
+        vector.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, vector.capacity());
+    }
+}
--- a/jdk/test/java/util/Locale/LocaleCategory.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/LocaleCategory.java	Tue Nov 09 22:53:18 2010 -0800
@@ -29,15 +29,28 @@
     private static String enc = null;
 
     public static void main(String[] args) {
-        base = new Locale(System.getProperty("user.language", ""),
-                          System.getProperty("user.country", ""),
-                          System.getProperty("user.variant", ""));
-        disp = new Locale(System.getProperty("user.language.display", ""),
-                          System.getProperty("user.country.display", ""),
-                          System.getProperty("user.variant.display", ""));
-        fmt  = new Locale(System.getProperty("user.language.format", ""),
-                          System.getProperty("user.country.format", ""),
-                          System.getProperty("user.variant.format", ""));
+        Locale.Builder builder = new Locale.Builder();
+
+        base = builder.setLanguage(System.getProperty("user.language", ""))
+                      .setScript(System.getProperty("user.script", ""))
+                      .setRegion(System.getProperty("user.country", ""))
+                      .setVariant(System.getProperty("user.variant", "")).build();
+        disp = builder.setLanguage(System.getProperty("user.language.display",
+                                                      Locale.getDefault().getLanguage()))
+                      .setScript(System.getProperty("user.script.display",
+                                                    Locale.getDefault().getScript()))
+                      .setRegion(System.getProperty("user.country.display",
+                                                    Locale.getDefault().getCountry()))
+                      .setVariant(System.getProperty("user.variant.display",
+                                                     Locale.getDefault().getVariant())).build();
+        fmt = builder.setLanguage(System.getProperty("user.language.format",
+                                                     Locale.getDefault().getLanguage()))
+                     .setScript(System.getProperty("user.script.format",
+                                                   Locale.getDefault().getScript()))
+                     .setRegion(System.getProperty("user.country.format",
+                                                   Locale.getDefault().getCountry()))
+                     .setVariant(System.getProperty("user.variant.format",
+                                                     Locale.getDefault().getVariant())).build();
         checkDefault();
         testGetSetDefault();
     }
--- a/jdk/test/java/util/Locale/LocaleCategory.sh	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/LocaleCategory.sh	Tue Nov 09 22:53:18 2010 -0800
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 # @test
-# @bug 4700857
+# @bug 4700857 6997928
 # @summary tests for Locale.getDefault(Locale.Category) and 
 #    Locale.setDefault(Locale.Category, Locale)
 # @build LocaleCategory
--- a/jdk/test/java/util/Locale/data/deflocale.rhel5	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.rhel5	Tue Nov 09 22:53:18 2010 -0800
@@ -465,15 +465,15 @@
 default charset: UTF-8
 
 OS Locale:  be_BY.utf8@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  be_BY@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  bg_BG
@@ -518,18 +518,18 @@
 format locale: ID: bn_IN, Name: Bengali (India)
 default charset: UTF-8
 
+OS Locale:  bokmal
+default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+default charset: ISO-8859-1
+
 OS Locale:  bokmål
 default locale: ID: en, Name: English
 display locale: ID: en, Name: English
 format locale: ID: en, Name: English
 default charset: ISO-8859-1
 
-OS Locale:  bokmal
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
-default charset: ISO-8859-1
-
 OS Locale:  br_FR
 default locale: ID: br_FR, Name: Breton (France)
 display locale: ID: br_FR, Name: Breton (France)
@@ -579,15 +579,15 @@
 default charset: UTF-8
 
 OS Locale:  byn_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  byn_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  ca_AD
@@ -705,15 +705,15 @@
 default charset: UTF-8
 
 OS Locale:  csb_PL
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  csb_PL.utf8
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  cy_GB
@@ -939,9 +939,9 @@
 default charset: UTF-8
 
 OS Locale:  eesti
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  el_CY
@@ -1623,9 +1623,9 @@
 default charset: UTF-8
 
 OS Locale:  estonian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  et_EE
@@ -1929,15 +1929,15 @@
 default charset: ISO-8859-15
 
 OS Locale:  galego
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  galician
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  gd_GB
@@ -1965,51 +1965,51 @@
 default charset: ISO-8859-1
 
 OS Locale:  gez_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gl_ES
@@ -2139,21 +2139,21 @@
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.iso88592
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.utf8
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: UTF-8
 
 OS Locale:  hu_HU
@@ -2445,15 +2445,15 @@
 default charset: UTF-8
 
 OS Locale:  korean
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  korean.euc
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  ku_TR
@@ -2523,9 +2523,9 @@
 default charset: UTF-8
 
 OS Locale:  lithuanian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 default charset: ISO-8859-13
 
 OS Locale:  lo_LA
@@ -2577,15 +2577,15 @@
 default charset: UTF-8
 
 OS Locale:  mai_IN
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mai_IN.utf8
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mg_MG
@@ -2859,21 +2859,21 @@
 default charset: UTF-8
 
 OS Locale:  nso_ZA
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nso_ZA.utf8
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nynorsk
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
 default charset: ISO-8859-1
 
 OS Locale:  oc_FR
@@ -3147,15 +3147,15 @@
 default charset: UTF-8
 
 OS Locale:  sid_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sid_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sk_SK
@@ -3321,39 +3321,39 @@
 default charset: UTF-8
 
 OS Locale:  sr_ME
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_ME.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_RS
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  ss_ZA
@@ -3507,9 +3507,9 @@
 default charset: UTF-8
 
 OS Locale:  thai
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: th_TH, Name: Thai (Thailand)
+format locale: ID: th_TH, Name: Thai (Thailand)
 default charset: TIS-620
 
 OS Locale:  ti_ER
@@ -3537,15 +3537,15 @@
 default charset: UTF-8
 
 OS Locale:  tig_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tig_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tl_PH
@@ -3681,15 +3681,15 @@
 default charset: ISO-8859-1
 
 OS Locale:  uz_UZ.utf8@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  uz_UZ@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  ve_ZA
--- a/jdk/test/java/util/Locale/data/deflocale.rhel5.fmtasdefault	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.rhel5.fmtasdefault	Tue Nov 09 22:53:18 2010 -0800
@@ -465,15 +465,15 @@
 default charset: UTF-8
 
 OS Locale:  be_BY.utf8@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  be_BY@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  bg_BG
@@ -518,18 +518,18 @@
 format locale: ID: bn_IN, Name: Bengali (India)
 default charset: UTF-8
 
+OS Locale:  bokmal
+default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+default charset: ISO-8859-1
+
 OS Locale:  bokmål
 default locale: ID: en, Name: English
 display locale: ID: en, Name: English
 format locale: ID: en, Name: English
 default charset: ISO-8859-1
 
-OS Locale:  bokmal
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
-default charset: ISO-8859-1
-
 OS Locale:  br_FR
 default locale: ID: br_FR, Name: Breton (France)
 display locale: ID: br_FR, Name: Breton (France)
@@ -579,15 +579,15 @@
 default charset: UTF-8
 
 OS Locale:  byn_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  byn_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  ca_AD
@@ -705,15 +705,15 @@
 default charset: UTF-8
 
 OS Locale:  csb_PL
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  csb_PL.utf8
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  cy_GB
@@ -939,9 +939,9 @@
 default charset: UTF-8
 
 OS Locale:  eesti
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  el_CY
@@ -1623,9 +1623,9 @@
 default charset: UTF-8
 
 OS Locale:  estonian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  et_EE
@@ -1929,15 +1929,15 @@
 default charset: ISO-8859-15
 
 OS Locale:  galego
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  galician
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  gd_GB
@@ -1965,51 +1965,51 @@
 default charset: ISO-8859-1
 
 OS Locale:  gez_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gl_ES
@@ -2139,21 +2139,21 @@
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.iso88592
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.utf8
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: UTF-8
 
 OS Locale:  hu_HU
@@ -2445,15 +2445,15 @@
 default charset: UTF-8
 
 OS Locale:  korean
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  korean.euc
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  ku_TR
@@ -2523,9 +2523,9 @@
 default charset: UTF-8
 
 OS Locale:  lithuanian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 default charset: ISO-8859-13
 
 OS Locale:  lo_LA
@@ -2577,15 +2577,15 @@
 default charset: UTF-8
 
 OS Locale:  mai_IN
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mai_IN.utf8
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mg_MG
@@ -2859,21 +2859,21 @@
 default charset: UTF-8
 
 OS Locale:  nso_ZA
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nso_ZA.utf8
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nynorsk
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
 default charset: ISO-8859-1
 
 OS Locale:  oc_FR
@@ -3147,15 +3147,15 @@
 default charset: UTF-8
 
 OS Locale:  sid_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sid_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sk_SK
@@ -3321,39 +3321,39 @@
 default charset: UTF-8
 
 OS Locale:  sr_ME
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_ME.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_RS
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  ss_ZA
@@ -3507,9 +3507,9 @@
 default charset: UTF-8
 
 OS Locale:  thai
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: th_TH, Name: Thai (Thailand)
+format locale: ID: th_TH, Name: Thai (Thailand)
 default charset: TIS-620
 
 OS Locale:  ti_ER
@@ -3537,15 +3537,15 @@
 default charset: UTF-8
 
 OS Locale:  tig_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tig_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tl_PH
@@ -3681,15 +3681,15 @@
 default charset: ISO-8859-1
 
 OS Locale:  uz_UZ.utf8@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  uz_UZ@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  ve_ZA
--- a/jdk/test/java/util/Locale/data/deflocale.sol10	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.sol10	Tue Nov 09 22:53:18 2010 -0800
@@ -1128,9 +1128,9 @@
 default charset: ISO-8859-1
 
 OS Locale:  no_NY
-default locale: ID: no_, Name: Norwegian ()
-display locale: ID: no_, Name: Norwegian ()
-format locale: ID: no_, Name: Norwegian ()
+default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: ISO-8859-1
 
 OS Locale:  nr
@@ -1332,9 +1332,9 @@
 default charset: ISO-8859-2
 
 OS Locale:  sr_SP
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 default charset: ISO-8859-5
 
 OS Locale:  sr_YU
@@ -1721,5 +1721,5 @@
 OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: zh_CN, Name: Chinese (China)
-format locale: ID: en, Name: English
+format locale: ID: en_CN, Name: English (China)
 default charset: US-ASCII
--- a/jdk/test/java/util/Locale/data/deflocale.sol10.fmtasdefault	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.sol10.fmtasdefault	Tue Nov 09 22:53:18 2010 -0800
@@ -1128,9 +1128,9 @@
 default charset: ISO-8859-1
 
 OS Locale:  no_NY
-default locale: ID: no_, Name: Norwegian ()
-display locale: ID: no_, Name: Norwegian ()
-format locale: ID: no_, Name: Norwegian ()
+default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: ISO-8859-1
 
 OS Locale:  nr
@@ -1332,9 +1332,9 @@
 default charset: ISO-8859-2
 
 OS Locale:  sr_SP
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 default charset: ISO-8859-5
 
 OS Locale:  sr_YU
--- a/jdk/test/java/util/Locale/data/deflocale.win7	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.win7	Tue Nov 09 22:53:18 2010 -0800
@@ -1,1493 +1,1493 @@
-# OSVersionInfo
-# MajorVersion: 6
-# MinorVersion: 1
-# BuildNumber: 7600
-# CSDVersion: 
-
-
-OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-default charset: windows-1252
-
-OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-default charset: windows-1252
-
-OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ca_ES, Name: Catalan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zh_TW, Name: Chinese (Taiwan)
-default charset: windows-1252
-
-OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cs_CZ, Name: Czech (Czech Republic)
-default charset: windows-1252
-
-OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: da_DK, Name: Danish (Denmark)
-default charset: windows-1252
-
-OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: de_DE, Name: German (Germany)
-default charset: windows-1252
-
-OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: el_GR, Name: Greek (Greece)
-default charset: windows-1252
-
-OS Locale (lcid: 409, name: en-US): English (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fi_FI, Name: Finnish (Finland)
-default charset: windows-1252
-
-OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fr_FR, Name: French (France)
-default charset: windows-1252
-
-OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iw_IL, Name: Hebrew (Israel)
-default charset: windows-1252
-
-OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hu_HU, Name: Hungarian (Hungary)
-default charset: windows-1252
-
-OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: is_IS, Name: Icelandic (Iceland)
-default charset: windows-1252
-
-OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: it_IT, Name: Italian (Italy)
-default charset: windows-1252
-
-OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ja_JP, Name: Japanese (Japan)
-default charset: windows-1252
-
-OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ko_KR, Name: Korean (South Korea)
-default charset: windows-1252
-
-OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: nl_NL, Name: Dutch (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: no_NO, Name: Norwegian (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pl_PL, Name: Polish (Poland)
-default charset: windows-1252
-
-OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pt_BR, Name: Portuguese (Brazil)
-default charset: windows-1252
-
-OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-default charset: windows-1252
-
-OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ro_RO, Name: Romanian (Romania)
-default charset: windows-1252
-
-OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ru_RU, Name: Russian (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hr_HR, Name: Croatian (Croatia)
-default charset: windows-1252
-
-OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sk_SK, Name: Slovak (Slovakia)
-default charset: windows-1252
-
-OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sq_AL, Name: Albanian (Albania)
-default charset: windows-1252
-
-OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sv_SE, Name: Swedish (Sweden)
-default charset: windows-1252
-
-OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: th_TH, Name: Thai (Thailand)
-default charset: windows-1252
-
-OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tr_TR, Name: Turkish (Turkey)
-default charset: windows-1252
-
-OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ur_PK, Name: Urdu (Pakistan)
-default charset: windows-1252
-
-OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: in_ID, Name: Indonesian (Indonesia)
-default charset: windows-1252
-
-OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-default charset: windows-1252
-
-OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
-default charset: windows-1252
-
-OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sl_SI, Name: Slovenian (Slovenia)
-default charset: windows-1252
-
-OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: et_EE, Name: Estonian (Estonia)
-default charset: windows-1252
-
-OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lv_LV, Name: Latvian (Latvia)
-default charset: windows-1252
-
-OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-default charset: windows-1252
-
-OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1252
-
-OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1252
-
-OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fa_IR, Name: Persian (Iran)
-default charset: windows-1252
-
-OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-default charset: windows-1252
-
-OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hy_AM, Name: Armenian (Armenia)
-default charset: windows-1252
-
-OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1252
-
-OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1252
-
-OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: eu_ES, Name: Basque (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+# OSVersionInfo
+# MajorVersion: 6
+# MinorVersion: 1
+# BuildNumber: 7600
+# CSDVersion: 
+
+
+OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mk_MK, Name: Macedonian (Macedonia)
-default charset: windows-1252
-
-OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tn_ZA, Name: Tswana (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: xh_ZA, Name: Xhosa (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zu_ZA, Name: Zulu (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: af_ZA, Name: Afrikaans (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ka_GE, Name: Georgian (Georgia)
-default charset: windows-1252
-
-OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-default charset: windows-1252
-
-OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hi_IN, Name: Hindi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+
+OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mt_MT, Name: Maltese (Malta)
-default charset: windows-1252
-
-OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: se_NO, Name: Northern Sami (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ms_MY, Name: Malay (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-default charset: windows-1252
-
-OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 default charset: windows-1252
-
-OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sw_KE, Name: Swahili (Kenya)
-default charset: windows-1252
-
-OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-default charset: windows-1252
-
-OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1252
-
-OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1252
-
-OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+
+OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: tt_RU, Name: Tatar (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bn_IN, Name: Bengali (India)
-default charset: windows-1252
-
-OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pa_IN, Name: Panjabi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gu_IN, Name: Gujarati (India)
-default charset: windows-1252
-
-OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: or_IN, Name: Oriya (India)
+format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 default charset: windows-1252
-
-OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ta_IN, Name: Tamil (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: te_IN, Name: Telugu (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kn_IN, Name: Kannada (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ml_IN, Name: Malayalam (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+
+OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: as_IN, Name: Assamese (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mr_IN, Name: Marathi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sa_IN, Name: Sanskrit (India)
-default charset: windows-1252
-
-OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1252
-
-OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+format locale: ID: ca_ES, Name: Catalan (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bo_CN, Name: Tibetan (China)
-default charset: windows-1252
-
-OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cy_GB, Name: Welsh (United Kingdom)
-default charset: windows-1252
-
-OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: km_KH, Name: Khmer (Cambodia)
-default charset: windows-1252
-
-OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lo_LA, Name: Lao (Laos)
-default charset: windows-1252
-
-OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gl_ES, Name: Gallegan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+
+OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: zh_TW, Name: Chinese (Taiwan)
 default charset: windows-1252
-
-OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-default charset: windows-1252
-
-OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: windows-1252
-
-OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: windows-1252
-
-OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: am_ET, Name: Amharic (Ethiopia)
-default charset: windows-1252
-
-OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+
+OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ne_NP, Name: Nepali (Nepal)
-default charset: windows-1252
-
-OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fy_NL, Name: Frisian (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ps_AF, Name: Pushto (Afghanistan)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: dv_MV, Name: Divehi (Maldives)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: yo_NG, Name: Yoruba (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+
+OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ba_RU, Name: Bashkir (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+format locale: ID: da_DK, Name: Danish (Denmark)
 default charset: windows-1252
-
-OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kl_GL, Name: Greenlandic (Greenland)
-default charset: windows-1252
-
-OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ig_NG, Name: Igbo (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ii_CN, Name: Sichuan Yi (China)
-default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+
+OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: de_DE, Name: German (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: br_FR, Name: Breton (France)
-default charset: windows-1252
-
-OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+
+OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ug_CN, Name: Uighur (China)
-default charset: windows-1252
-
-OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mi_NZ, Name: Maori (New Zealand)
-default charset: windows-1252
-
-OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: oc_FR, Name: Occitan (France)
+format locale: ID: el_GR, Name: Greek (Greece)
 default charset: windows-1252
-
-OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: co_FR, Name: Corsican (France)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+
+OS Locale (lcid: 409, name: en-US): English (United States) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+
+OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fi_FI, Name: Finnish (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fr_FR, Name: French (France)
+default charset: windows-1252
+
+OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iw_IL, Name: Hebrew (Israel)
+default charset: windows-1252
+
+OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hu_HU, Name: Hungarian (Hungary)
+default charset: windows-1252
+
+OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: is_IS, Name: Icelandic (Iceland)
+default charset: windows-1252
+
+OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: it_IT, Name: Italian (Italy)
+default charset: windows-1252
+
+OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ja_JP, Name: Japanese (Japan)
+default charset: windows-1252
+
+OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ko_KR, Name: Korean (South Korea)
+default charset: windows-1252
+
+OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nl_NL, Name: Dutch (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokm…l) (Norway) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: no_NO, Name: Norwegian (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pl_PL, Name: Polish (Poland)
+default charset: windows-1252
+
+OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pt_BR, Name: Portuguese (Brazil)
+default charset: windows-1252
+
+OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+default charset: windows-1252
+
+OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ro_RO, Name: Romanian (Romania)
+default charset: windows-1252
+
+OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ru_RU, Name: Russian (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hr_HR, Name: Croatian (Croatia)
+default charset: windows-1252
+
+OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sk_SK, Name: Slovak (Slovakia)
+default charset: windows-1252
+
+OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sq_AL, Name: Albanian (Albania)
+default charset: windows-1252
+
+OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sv_SE, Name: Swedish (Sweden)
+default charset: windows-1252
+
+OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: th_TH, Name: Thai (Thailand)
+default charset: windows-1252
+
+OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tr_TR, Name: Turkish (Turkey)
+default charset: windows-1252
+
+OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ur_PK, Name: Urdu (Pakistan)
+default charset: windows-1252
+
+OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: in_ID, Name: Indonesian (Indonesia)
+default charset: windows-1252
+
+OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+default charset: windows-1252
+
+OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: be_BY, Name: Belarusian (Belarus)
+default charset: windows-1252
+
+OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sl_SI, Name: Slovenian (Slovenia)
+default charset: windows-1252
+
+OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: et_EE, Name: Estonian (Estonia)
+default charset: windows-1252
+
+OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lv_LV, Name: Latvian (Latvia)
+default charset: windows-1252
+
+OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+default charset: windows-1252
+
+OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1252
+
+OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1252
+
+OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fa_IR, Name: Persian (Iran)
+default charset: windows-1252
+
+OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+default charset: windows-1252
+
+OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hy_AM, Name: Armenian (Armenia)
+default charset: windows-1252
+
+OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1252
+
+OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1252
+
+OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: eu_ES, Name: Basque (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mk_MK, Name: Macedonian (Macedonia)
+default charset: windows-1252
+
+OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tn_ZA, Name: Tswana (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: xh_ZA, Name: Xhosa (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: zu_ZA, Name: Zulu (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+
+OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: af_ZA, Name: Afrikaans (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ka_GE, Name: Georgian (Georgia)
+default charset: windows-1252
+
+OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+default charset: windows-1252
+
+OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hi_IN, Name: Hindi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mt_MT, Name: Maltese (Malta)
+default charset: windows-1252
+
+OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: se_NO, Name: Northern Sami (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ms_MY, Name: Malay (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+default charset: windows-1252
+
+OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+default charset: windows-1252
+
+OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sw_KE, Name: Swahili (Kenya)
+default charset: windows-1252
+
+OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+default charset: windows-1252
+
+OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1252
+
+OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1252
+
+OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tt_RU, Name: Tatar (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: bn_IN, Name: Bengali (India)
+default charset: windows-1252
+
+OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pa_IN, Name: Panjabi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gu_IN, Name: Gujarati (India)
+default charset: windows-1252
+
+OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: or_IN, Name: Oriya (India)
+default charset: windows-1252
+
+OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ta_IN, Name: Tamil (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: te_IN, Name: Telugu (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kn_IN, Name: Kannada (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ml_IN, Name: Malayalam (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: as_IN, Name: Assamese (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mr_IN, Name: Marathi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sa_IN, Name: Sanskrit (India)
+default charset: windows-1252
+
+OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1252
+
+OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1252
+
+OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: bo_CN, Name: Tibetan (China)
+default charset: windows-1252
+
+OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+
+OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: km_KH, Name: Khmer (Cambodia)
+default charset: windows-1252
+
+OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lo_LA, Name: Lao (Laos)
+default charset: windows-1252
+
+OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok): Konkani (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: windows-1252
+
+OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+default charset: windows-1252
+
+OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: am_ET, Name: Amharic (Ethiopia)
+default charset: windows-1252
+
+OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ne_NP, Name: Nepali (Nepal)
+default charset: windows-1252
+
+OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fy_NL, Name: Frisian (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ps_AF, Name: Pushto (Afghanistan)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: dv_MV, Name: Divehi (Maldives)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: yo_NG, Name: Yoruba (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ba_RU, Name: Bashkir (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+default charset: windows-1252
+
+OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kl_GL, Name: Greenlandic (Greenland)
+default charset: windows-1252
+
+OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ig_NG, Name: Igbo (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ii_CN, Name: Sichuan Yi (China)
 default charset: windows-1252
-
-OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
+
+OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: br_FR, Name: Breton (France)
+default charset: windows-1252
+
+OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ug_CN, Name: Uighur (China)
+default charset: windows-1252
+
+OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mi_NZ, Name: Maori (New Zealand)
+default charset: windows-1252
+
+OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: oc_FR, Name: Occitan (France)
+default charset: windows-1252
+
+OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: co_FR, Name: Corsican (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 default charset: windows-1252
-
-OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
+
+OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: wo_SN, Name: Wolof (Senegal)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
+
+OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
+
+OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1252
-
-OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
+
+OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
+
+OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_IQ, Name: Arabic (Iraq)
 default charset: windows-1252
-
-OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: windows-1252
-
-OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: windows-1252
-
-OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
+
+OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_CH, Name: German (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
+
+OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_GB, Name: English (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
+
+OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_MX, Name: Spanish (Mexico)
 default charset: windows-1252
-
-OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
+
+OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_BE, Name: French (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
+
+OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: it_CH, Name: Italian (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
+
+OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: nl_BE, Name: Dutch (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
+
+OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: windows-1252
-
-OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
+
+OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: pt_PT, Name: Portuguese (Portugal)
 default charset: windows-1252
-
-OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
+
+OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 default charset: windows-1252
-
-OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
+
+OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: sv_FI, Name: Swedish (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
+
+OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
+
+OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
+
+OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
+
+OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
+
+OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_SE, Name: Northern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
+
+OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ga_IE, Name: Irish (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
+
+OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ms_BN, Name: Malay (Brunei)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
+
+OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
+
+OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1252
-
-OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
+
+OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 default charset: windows-1252
-
-OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+
+OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: windows-1252
-
-OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+
+OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
+
+OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
+
+OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
+
+OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_EC, Name: quz (Ecuador)
 default charset: windows-1252
-
-OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
+
+OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_EG, Name: Arabic (Egypt)
 default charset: windows-1252
-
-OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-MS950-HKSCS
-
-OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: windows-1252
-
-OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
+
+OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_AT, Name: German (Austria)
 default charset: windows-1252
-
-OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
+
+OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_AU, Name: English (Australia)
 default charset: windows-1252
-
-OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
+
+OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_ES, Name: Spanish (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
+
+OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CA, Name: French (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
+
+OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 default charset: windows-1252
-
-OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
+
+OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_FI, Name: Northern Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
+
+OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_PE, Name: quz (Peru)
 default charset: windows-1252
-
-OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
+
+OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_LY, Name: Arabic (Libya)
 default charset: windows-1252
-
-OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
+
+OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_SG, Name: Chinese (Singapore)
 default charset: windows-1252
-
-OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
+
+OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LU, Name: German (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
+
+OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_CA, Name: English (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
+
+OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_GT, Name: Spanish (Guatemala)
 default charset: windows-1252
-
-OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
+
+OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CH, Name: French (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
+
+OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_NO, Name: Lule Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
+
+OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_DZ, Name: Arabic (Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
+
+OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_MO, Name: Chinese (Macao)
 default charset: windows-1252
-
-OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
+
+OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LI, Name: German (Liechtenstein)
 default charset: windows-1252
-
-OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
+
+OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_NZ, Name: English (New Zealand)
 default charset: windows-1252
-
-OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
+
+OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CR, Name: Spanish (Costa Rica)
 default charset: windows-1252
-
-OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
+
+OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_LU, Name: French (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
+
+OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
+
+OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
+
+OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_MA, Name: Arabic (Morocco)
 default charset: windows-1252
-
-OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
+
+OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IE, Name: English (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
+
+OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_PA, Name: Spanish (Panama)
 default charset: windows-1252
-
-OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
+
+OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_MC, Name: French (Monaco)
 default charset: windows-1252
-
-OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
+
+OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_NO, Name: Southern Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
+
+OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_TN, Name: Arabic (Tunisia)
 default charset: windows-1252
-
-OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
+
+OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZA, Name: English (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
+
+OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_DO, Name: Spanish (Dominican Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
+
+OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
+
+OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
+
+OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_OM, Name: Arabic (Oman)
 default charset: windows-1252
-
-OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
+
+OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_JM, Name: English (Jamaica)
 default charset: windows-1252
-
-OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
+
+OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_VE, Name: Spanish (Venezuela)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
+
+OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
+
+OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
+
+OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_YE, Name: Arabic (Yemen)
 default charset: windows-1252
-
-OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
+
+OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_029, Name: English (Caribbean)
 default charset: windows-1252
-
-OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
+
+OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CO, Name: Spanish (Colombia)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+
+OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_SY, Name: Arabic (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_BZ, Name: English (Belize)
+default charset: windows-1252
+
+OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PE, Name: Spanish (Peru)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_JO, Name: Arabic (Jordan)
+default charset: windows-1252
+
+OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_TT, Name: English (Trinidad and Tobago)
+default charset: windows-1252
+
+OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_AR, Name: Spanish (Argentina)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+
+OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
+default charset: windows-1252
+
+OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_LB, Name: Arabic (Lebanon)
+default charset: windows-1252
+
+OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZW, Name: English (Zimbabwe)
+default charset: windows-1252
+
+OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_EC, Name: Spanish (Ecuador)
+default charset: windows-1252
+
+OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
+default charset: windows-1252
+
+OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_KW, Name: Arabic (Kuwait)
+default charset: windows-1252
+
+OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_PH, Name: English (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_CL, Name: Spanish (Chile)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+default charset: windows-1252
+
+OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_UY, Name: Spanish (Uruguay)
+default charset: windows-1252
+
+OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_BH, Name: Arabic (Bahrain)
+default charset: windows-1252
+
+OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PY, Name: Spanish (Paraguay)
+default charset: windows-1252
+
+OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_QA, Name: Arabic (Qatar)
+default charset: windows-1252
+
+OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IN, Name: English (India)
+default charset: windows-1252
+
+OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_BO, Name: Spanish (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_MY, Name: English (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_SV, Name: Spanish (El Salvador)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_SG, Name: English (Singapore)
+default charset: windows-1252
+
+OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_HN, Name: Spanish (Honduras)
+default charset: windows-1252
+
+OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_NI, Name: Spanish (Nicaragua)
+default charset: windows-1252
+
+OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PR, Name: Spanish (Puerto Rico)
+default charset: windows-1252
+
+OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_US, Name: Spanish (United States)
+default charset: windows-1252
+
+OS UI Language (name: en-US)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SY, Name: Arabic (Syria)
-default charset: windows-1252
-
-OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PE, Name: Spanish (Peru)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1252
-
-OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_JO, Name: Arabic (Jordan)
-default charset: windows-1252
-
-OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_AR, Name: Spanish (Argentina)
-default charset: windows-1252
-
-OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1252
-
-OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_LB, Name: Arabic (Lebanon)
-default charset: windows-1252
-
-OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_EC, Name: Spanish (Ecuador)
-default charset: windows-1252
-
-OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1252
-
-OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_KW, Name: Arabic (Kuwait)
-default charset: windows-1252
-
-OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_CL, Name: Spanish (Chile)
-default charset: windows-1252
-
-OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-default charset: windows-1252
-
-OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_UY, Name: Spanish (Uruguay)
-default charset: windows-1252
-
-OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_BH, Name: Arabic (Bahrain)
-default charset: windows-1252
-
-OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PY, Name: Spanish (Paraguay)
-default charset: windows-1252
-
-OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_QA, Name: Arabic (Qatar)
-default charset: windows-1252
-
-OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_BO, Name: Spanish (Bolivia)
-default charset: windows-1252
-
-OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_SV, Name: Spanish (El Salvador)
-default charset: windows-1252
-
-OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_HN, Name: Spanish (Honduras)
-default charset: windows-1252
-
-OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_NI, Name: Spanish (Nicaragua)
-default charset: windows-1252
-
-OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PR, Name: Spanish (Puerto Rico)
-default charset: windows-1252
-
-OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es, Name: Spanish
-default charset: windows-1252
-
-OS UI Language (name: en-US)
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS UI Language (name: ja-JP)
+
+OS UI Language (name: ja-JP)
 default locale: ID: ja_JP, Name: Japanese (Japan)
 display locale: ID: ja_JP, Name: Japanese (Japan)
 format locale: ID: en_US, Name: English (United States)
--- a/jdk/test/java/util/Locale/data/deflocale.win7.fmtasdefault	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/Locale/data/deflocale.win7.fmtasdefault	Tue Nov 09 22:53:18 2010 -0800
@@ -1,1493 +1,1493 @@
-# OSVersionInfo
-# MajorVersion: 6
-# MinorVersion: 1
-# BuildNumber: 7600
-# CSDVersion: 
-
-
-OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
-default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-default charset: windows-1256
-
-OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
-default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-default charset: windows-1251
-
-OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
-default locale: ID: ca_ES, Name: Catalan (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ca_ES, Name: Catalan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
-default locale: ID: zh_TW, Name: Chinese (Taiwan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zh_TW, Name: Chinese (Taiwan)
-default charset: x-windows-950
-
-OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
-default locale: ID: cs_CZ, Name: Czech (Czech Republic)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cs_CZ, Name: Czech (Czech Republic)
-default charset: windows-1250
-
-OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
-default locale: ID: da_DK, Name: Danish (Denmark)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: da_DK, Name: Danish (Denmark)
-default charset: windows-1252
-
-OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
-default locale: ID: de_DE, Name: German (Germany)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: de_DE, Name: German (Germany)
-default charset: windows-1252
-
-OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
-default locale: ID: el_GR, Name: Greek (Greece)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: el_GR, Name: Greek (Greece)
-default charset: windows-1253
-
-OS Locale (lcid: 409, name: en-US): English (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
-default locale: ID: fi_FI, Name: Finnish (Finland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fi_FI, Name: Finnish (Finland)
-default charset: windows-1252
-
-OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
-default locale: ID: fr_FR, Name: French (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fr_FR, Name: French (France)
-default charset: windows-1252
-
-OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
-default locale: ID: iw_IL, Name: Hebrew (Israel)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iw_IL, Name: Hebrew (Israel)
-default charset: windows-1255
-
-OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
-default locale: ID: hu_HU, Name: Hungarian (Hungary)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hu_HU, Name: Hungarian (Hungary)
-default charset: windows-1250
-
-OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
-default locale: ID: is_IS, Name: Icelandic (Iceland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: is_IS, Name: Icelandic (Iceland)
-default charset: windows-1252
-
-OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
-default locale: ID: it_IT, Name: Italian (Italy)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: it_IT, Name: Italian (Italy)
-default charset: windows-1252
-
-OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
-default locale: ID: ja_JP, Name: Japanese (Japan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ja_JP, Name: Japanese (Japan)
-default charset: windows-31j
-
-OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
-default locale: ID: ko_KR, Name: Korean (South Korea)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ko_KR, Name: Korean (South Korea)
-default charset: x-windows-949
-
-OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
-default locale: ID: nl_NL, Name: Dutch (Netherlands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: nl_NL, Name: Dutch (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
-default locale: ID: no_NO, Name: Norwegian (Norway)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: no_NO, Name: Norwegian (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
-default locale: ID: pl_PL, Name: Polish (Poland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pl_PL, Name: Polish (Poland)
-default charset: windows-1250
-
-OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
-default locale: ID: pt_BR, Name: Portuguese (Brazil)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pt_BR, Name: Portuguese (Brazil)
-default charset: windows-1252
-
-OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
-default locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-default charset: windows-1252
-
-OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
-default locale: ID: ro_RO, Name: Romanian (Romania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ro_RO, Name: Romanian (Romania)
-default charset: windows-1250
-
-OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
-default locale: ID: ru_RU, Name: Russian (Russia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ru_RU, Name: Russian (Russia)
-default charset: windows-1251
-
-OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
-default locale: ID: hr_HR, Name: Croatian (Croatia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hr_HR, Name: Croatian (Croatia)
-default charset: windows-1250
-
-OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
-default locale: ID: sk_SK, Name: Slovak (Slovakia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sk_SK, Name: Slovak (Slovakia)
-default charset: windows-1250
-
-OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
-default locale: ID: sq_AL, Name: Albanian (Albania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sq_AL, Name: Albanian (Albania)
-default charset: windows-1250
-
-OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
-default locale: ID: sv_SE, Name: Swedish (Sweden)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sv_SE, Name: Swedish (Sweden)
-default charset: windows-1252
-
-OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
-default locale: ID: th_TH, Name: Thai (Thailand)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: th_TH, Name: Thai (Thailand)
-default charset: x-windows-874
-
-OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
-default locale: ID: tr_TR, Name: Turkish (Turkey)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tr_TR, Name: Turkish (Turkey)
-default charset: windows-1254
-
-OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
-default locale: ID: ur_PK, Name: Urdu (Pakistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ur_PK, Name: Urdu (Pakistan)
-default charset: windows-1256
-
-OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
-default locale: ID: in_ID, Name: Indonesian (Indonesia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: in_ID, Name: Indonesian (Indonesia)
-default charset: windows-1252
-
-OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
-default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-default charset: windows-1251
-
-OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
-default charset: windows-1251
-
-OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
-default locale: ID: sl_SI, Name: Slovenian (Slovenia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sl_SI, Name: Slovenian (Slovenia)
-default charset: windows-1250
-
-OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
-default locale: ID: et_EE, Name: Estonian (Estonia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: et_EE, Name: Estonian (Estonia)
-default charset: windows-1257
-
-OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
-default locale: ID: lv_LV, Name: Latvian (Latvia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lv_LV, Name: Latvian (Latvia)
-default charset: windows-1257
-
-OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
-default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-default charset: windows-1257
-
-OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1251
-
-OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1251
-
-OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
-default locale: ID: fa_IR, Name: Persian (Iran)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fa_IR, Name: Persian (Iran)
-default charset: windows-1256
-
-OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
-default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-default charset: windows-1258
-
-OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
-default locale: ID: hy_AM, Name: Armenian (Armenia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hy_AM, Name: Armenian (Armenia)
-default charset: UTF-8
-
-OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1254
-
-OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1254
-
-OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
-default locale: ID: eu_ES, Name: Basque (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: eu_ES, Name: Basque (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+# OSVersionInfo
+# MajorVersion: 6
+# MinorVersion: 1
+# BuildNumber: 7600
+# CSDVersion: 
+
+
+OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
-default locale: ID: mk_MK, Name: Macedonian (Macedonia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mk_MK, Name: Macedonian (Macedonia)
-default charset: windows-1251
-
-OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
-default locale: ID: tn_ZA, Name: Tswana (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tn_ZA, Name: Tswana (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
-default locale: ID: xh_ZA, Name: Xhosa (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: xh_ZA, Name: Xhosa (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
-default locale: ID: zu_ZA, Name: Zulu (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zu_ZA, Name: Zulu (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
-default locale: ID: af_ZA, Name: Afrikaans (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: af_ZA, Name: Afrikaans (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
-default locale: ID: ka_GE, Name: Georgian (Georgia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ka_GE, Name: Georgian (Georgia)
-default charset: UTF-8
-
-OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
-default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-default charset: windows-1252
-
-OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
-default locale: ID: hi_IN, Name: Hindi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hi_IN, Name: Hindi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
-default locale: ID: mt_MT, Name: Maltese (Malta)
+
+OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
+default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mt_MT, Name: Maltese (Malta)
-default charset: UTF-8
-
-OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
-default locale: ID: se_NO, Name: Northern Sami (Norway)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: se_NO, Name: Northern Sami (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
-default locale: ID: ms_MY, Name: Malay (Malaysia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ms_MY, Name: Malay (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
-default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-default charset: UTF-8
-
-OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
-default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
+default charset: windows-1256
+
+OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
+default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
-default charset: windows-1251
-
-OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
-default locale: ID: sw_KE, Name: Swahili (Kenya)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sw_KE, Name: Swahili (Kenya)
-default charset: windows-1252
-
-OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
-default locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-default charset: windows-1250
-
-OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1254
-
-OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1254
-
-OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
-default locale: ID: tt_RU, Name: Tatar (Russia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tt_RU, Name: Tatar (Russia)
+format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 default charset: windows-1251
-
-OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
-default locale: ID: bn_IN, Name: Bengali (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bn_IN, Name: Bengali (India)
-default charset: UTF-8
-
-OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
-default locale: ID: pa_IN, Name: Panjabi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pa_IN, Name: Panjabi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
-default locale: ID: gu_IN, Name: Gujarati (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gu_IN, Name: Gujarati (India)
-default charset: UTF-8
-
-OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
-default locale: ID: or_IN, Name: Oriya (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: or_IN, Name: Oriya (India)
-default charset: UTF-8
-
-OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
-default locale: ID: ta_IN, Name: Tamil (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ta_IN, Name: Tamil (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
-default locale: ID: te_IN, Name: Telugu (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: te_IN, Name: Telugu (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
-default locale: ID: kn_IN, Name: Kannada (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kn_IN, Name: Kannada (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
-default locale: ID: ml_IN, Name: Malayalam (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ml_IN, Name: Malayalam (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
-default locale: ID: as_IN, Name: Assamese (India)
+
+OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
+default locale: ID: ca_ES, Name: Catalan (Spain)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: as_IN, Name: Assamese (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
-default locale: ID: mr_IN, Name: Marathi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mr_IN, Name: Marathi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
-default locale: ID: sa_IN, Name: Sanskrit (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sa_IN, Name: Sanskrit (India)
-default charset: UTF-8
-
-OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: mn_MN, Name: Mongolian (Mongolia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1251
-
-OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: mn_MN, Name: Mongolian (Mongolia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1251
-
-OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
-default locale: ID: bo_CN, Name: Tibetan (China)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bo_CN, Name: Tibetan (China)
-default charset: UTF-8
-
-OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
-default locale: ID: cy_GB, Name: Welsh (United Kingdom)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cy_GB, Name: Welsh (United Kingdom)
-default charset: windows-1252
-
-OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
-default locale: ID: km_KH, Name: Khmer (Cambodia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: km_KH, Name: Khmer (Cambodia)
-default charset: UTF-8
-
-OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
-default locale: ID: lo_LA, Name: Lao (Laos)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lo_LA, Name: Lao (Laos)
-default charset: UTF-8
-
-OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
-default locale: ID: gl_ES, Name: Gallegan (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: ca_ES, Name: Catalan (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 457, name: kok): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
-default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-default charset: UTF-8
-
-OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: UTF-8
-
-OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: UTF-8
-
-OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
-default locale: ID: am_ET, Name: Amharic (Ethiopia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: am_ET, Name: Amharic (Ethiopia)
-default charset: UTF-8
-
-OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
-default locale: ID: ne_NP, Name: Nepali (Nepal)
+
+OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
+default locale: ID: zh_TW, Name: Chinese (Taiwan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ne_NP, Name: Nepali (Nepal)
-default charset: UTF-8
-
-OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
-default locale: ID: fy_NL, Name: Frisian (Netherlands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fy_NL, Name: Frisian (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
-default locale: ID: ps_AF, Name: Pushto (Afghanistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ps_AF, Name: Pushto (Afghanistan)
-default charset: UTF-8
-
-OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
+format locale: ID: zh_TW, Name: Chinese (Taiwan)
+default charset: x-windows-950
+
+OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
+default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
-default locale: ID: dv_MV, Name: Divehi (Maldives)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: dv_MV, Name: Divehi (Maldives)
-default charset: UTF-8
-
-OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: ha_NG, Name: Hausa (Nigeria)
+format locale: ID: cs_CZ, Name: Czech (Czech Republic)
+default charset: windows-1250
+
+OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
+default locale: ID: da_DK, Name: Danish (Denmark)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: ha_NG, Name: Hausa (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
-default locale: ID: yo_NG, Name: Yoruba (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: yo_NG, Name: Yoruba (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: da_DK, Name: Danish (Denmark)
 default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
-default locale: ID: ba_RU, Name: Bashkir (Russia)
+
+OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
+default locale: ID: de_DE, Name: German (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ba_RU, Name: Bashkir (Russia)
-default charset: windows-1251
-
-OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
-default locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
-default charset: windows-1252
-
-OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
-default locale: ID: kl_GL, Name: Greenlandic (Greenland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kl_GL, Name: Greenlandic (Greenland)
-default charset: windows-1252
-
-OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
-default locale: ID: ig_NG, Name: Igbo (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ig_NG, Name: Igbo (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
-default locale: ID: ii_CN, Name: Sichuan Yi (China)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ii_CN, Name: Sichuan Yi (China)
-default charset: UTF-8
-
-OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: de_DE, Name: German (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
-default locale: ID: br_FR, Name: Breton (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: br_FR, Name: Breton (France)
-default charset: windows-1252
-
-OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
-default locale: ID: ug_CN, Name: Uighur (China)
+
+OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
+default locale: ID: el_GR, Name: Greek (Greece)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ug_CN, Name: Uighur (China)
-default charset: windows-1256
-
-OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
-default locale: ID: mi_NZ, Name: Maori (New Zealand)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mi_NZ, Name: Maori (New Zealand)
-default charset: UTF-8
-
-OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
-default locale: ID: oc_FR, Name: Occitan (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: oc_FR, Name: Occitan (France)
-default charset: windows-1252
-
-OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
-default locale: ID: co_FR, Name: Corsican (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: co_FR, Name: Corsican (France)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+format locale: ID: el_GR, Name: Greek (Greece)
+default charset: windows-1253
+
+OS Locale (lcid: 409, name: en-US): English (United States) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
+default locale: ID: fi_FI, Name: Finnish (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fi_FI, Name: Finnish (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
+default locale: ID: fr_FR, Name: French (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fr_FR, Name: French (France)
+default charset: windows-1252
+
+OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
+default locale: ID: iw_IL, Name: Hebrew (Israel)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iw_IL, Name: Hebrew (Israel)
+default charset: windows-1255
+
+OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
+default locale: ID: hu_HU, Name: Hungarian (Hungary)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hu_HU, Name: Hungarian (Hungary)
+default charset: windows-1250
+
+OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
+default locale: ID: is_IS, Name: Icelandic (Iceland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: is_IS, Name: Icelandic (Iceland)
+default charset: windows-1252
+
+OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
+default locale: ID: it_IT, Name: Italian (Italy)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: it_IT, Name: Italian (Italy)
+default charset: windows-1252
+
+OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
+default locale: ID: ja_JP, Name: Japanese (Japan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ja_JP, Name: Japanese (Japan)
+default charset: windows-31j
+
+OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ko_KR, Name: Korean (South Korea)
+default charset: x-windows-949
+
+OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
+default locale: ID: nl_NL, Name: Dutch (Netherlands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nl_NL, Name: Dutch (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokm…l) (Norway) - 1252
+default locale: ID: no_NO, Name: Norwegian (Norway)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: no_NO, Name: Norwegian (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
+default locale: ID: pl_PL, Name: Polish (Poland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pl_PL, Name: Polish (Poland)
+default charset: windows-1250
+
+OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
+default locale: ID: pt_BR, Name: Portuguese (Brazil)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: pt_BR, Name: Portuguese (Brazil)
+default charset: windows-1252
+
+OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
+default locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+default charset: windows-1252
+
+OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
+default locale: ID: ro_RO, Name: Romanian (Romania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ro_RO, Name: Romanian (Romania)
+default charset: windows-1250
+
+OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
+default locale: ID: ru_RU, Name: Russian (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ru_RU, Name: Russian (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
+default locale: ID: hr_HR, Name: Croatian (Croatia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hr_HR, Name: Croatian (Croatia)
+default charset: windows-1250
+
+OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
+default locale: ID: sk_SK, Name: Slovak (Slovakia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sk_SK, Name: Slovak (Slovakia)
+default charset: windows-1250
+
+OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
+default locale: ID: sq_AL, Name: Albanian (Albania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sq_AL, Name: Albanian (Albania)
+default charset: windows-1250
+
+OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
+default locale: ID: sv_SE, Name: Swedish (Sweden)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sv_SE, Name: Swedish (Sweden)
+default charset: windows-1252
+
+OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: th_TH, Name: Thai (Thailand)
+default charset: x-windows-874
+
+OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
+default locale: ID: tr_TR, Name: Turkish (Turkey)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tr_TR, Name: Turkish (Turkey)
+default charset: windows-1254
+
+OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
+default locale: ID: ur_PK, Name: Urdu (Pakistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ur_PK, Name: Urdu (Pakistan)
+default charset: windows-1256
+
+OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
+default locale: ID: in_ID, Name: Indonesian (Indonesia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: in_ID, Name: Indonesian (Indonesia)
+default charset: windows-1252
+
+OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
+default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+default charset: windows-1251
+
+OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
+default locale: ID: be_BY, Name: Belarusian (Belarus)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: be_BY, Name: Belarusian (Belarus)
 default charset: windows-1251
-
-OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
+default locale: ID: sl_SI, Name: Slovenian (Slovenia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sl_SI, Name: Slovenian (Slovenia)
+default charset: windows-1250
+
+OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: et_EE, Name: Estonian (Estonia)
+default charset: windows-1257
+
+OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
+default locale: ID: lv_LV, Name: Latvian (Latvia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lv_LV, Name: Latvian (Latvia)
+default charset: windows-1257
+
+OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+default charset: windows-1257
+
+OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1251
+
+OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1251
+
+OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
+default locale: ID: fa_IR, Name: Persian (Iran)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fa_IR, Name: Persian (Iran)
+default charset: windows-1256
+
+OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
+default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+default charset: windows-1258
+
+OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
+default locale: ID: hy_AM, Name: Armenian (Armenia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hy_AM, Name: Armenian (Armenia)
+default charset: UTF-8
+
+OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1254
+
+OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1254
+
+OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
+default locale: ID: eu_ES, Name: Basque (Spain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: eu_ES, Name: Basque (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
+default locale: ID: mk_MK, Name: Macedonian (Macedonia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mk_MK, Name: Macedonian (Macedonia)
+default charset: windows-1251
+
+OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
+default locale: ID: tn_ZA, Name: Tswana (South Africa)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tn_ZA, Name: Tswana (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
+default locale: ID: xh_ZA, Name: Xhosa (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: xh_ZA, Name: Xhosa (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
+default locale: ID: zu_ZA, Name: Zulu (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: zu_ZA, Name: Zulu (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
+default locale: ID: af_ZA, Name: Afrikaans (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: af_ZA, Name: Afrikaans (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
+default locale: ID: ka_GE, Name: Georgian (Georgia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ka_GE, Name: Georgian (Georgia)
+default charset: UTF-8
+
+OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
+default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+default charset: windows-1252
+
+OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
+default locale: ID: hi_IN, Name: Hindi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hi_IN, Name: Hindi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+default locale: ID: mt_MT, Name: Maltese (Malta)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mt_MT, Name: Maltese (Malta)
+default charset: UTF-8
+
+OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
+default locale: ID: se_NO, Name: Northern Sami (Norway)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: se_NO, Name: Northern Sami (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
+default locale: ID: ms_MY, Name: Malay (Malaysia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ms_MY, Name: Malay (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
+default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+default charset: UTF-8
+
+OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
+default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+default charset: windows-1251
+
+OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
+default locale: ID: sw_KE, Name: Swahili (Kenya)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sw_KE, Name: Swahili (Kenya)
+default charset: windows-1252
+
+OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
+default locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+default charset: windows-1250
+
+OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1254
+
+OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1254
+
+OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+default locale: ID: tt_RU, Name: Tatar (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tt_RU, Name: Tatar (Russia)
 default charset: windows-1251
-
-OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
+default locale: ID: bn_IN, Name: Bengali (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: bn_IN, Name: Bengali (India)
+default charset: UTF-8
+
+OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
+default locale: ID: pa_IN, Name: Panjabi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pa_IN, Name: Panjabi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
+default locale: ID: gu_IN, Name: Gujarati (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gu_IN, Name: Gujarati (India)
+default charset: UTF-8
+
+OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
+default locale: ID: or_IN, Name: Oriya (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: or_IN, Name: Oriya (India)
+default charset: UTF-8
+
+OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
+default locale: ID: ta_IN, Name: Tamil (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ta_IN, Name: Tamil (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
+default locale: ID: te_IN, Name: Telugu (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: te_IN, Name: Telugu (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
+default locale: ID: kn_IN, Name: Kannada (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kn_IN, Name: Kannada (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
+default locale: ID: ml_IN, Name: Malayalam (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ml_IN, Name: Malayalam (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+default locale: ID: as_IN, Name: Assamese (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: as_IN, Name: Assamese (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
+default locale: ID: mr_IN, Name: Marathi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mr_IN, Name: Marathi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
+default locale: ID: sa_IN, Name: Sanskrit (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sa_IN, Name: Sanskrit (India)
+default charset: UTF-8
+
+OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: mn_MN, Name: Mongolian (Mongolia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1251
+
+OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: mn_MN, Name: Mongolian (Mongolia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1251
+
+OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
+default locale: ID: bo_CN, Name: Tibetan (China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: bo_CN, Name: Tibetan (China)
+default charset: UTF-8
+
+OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
+default locale: ID: cy_GB, Name: Welsh (United Kingdom)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: cy_GB, Name: Welsh (United Kingdom)
+default charset: windows-1252
+
+OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
+default locale: ID: km_KH, Name: Khmer (Cambodia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: km_KH, Name: Khmer (Cambodia)
+default charset: UTF-8
+
+OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
+default locale: ID: lo_LA, Name: Lao (Laos)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lo_LA, Name: Lao (Laos)
+default charset: UTF-8
+
+OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+default locale: ID: kok_IN, Name: Konkani (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: UTF-8
+
+OS Locale (lcid: 457, name: kok): Konkani (India) - 0
+default locale: ID: kok_IN, Name: Konkani (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: UTF-8
+
+OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
+default locale: ID: syr_SY, Name: Syriac (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: UTF-8
+
+OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
+default locale: ID: syr_SY, Name: Syriac (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: UTF-8
+
+OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
+default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+default charset: UTF-8
+
+OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: UTF-8
+
+OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: UTF-8
+
+OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
+default locale: ID: am_ET, Name: Amharic (Ethiopia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: am_ET, Name: Amharic (Ethiopia)
+default charset: UTF-8
+
+OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+default locale: ID: ne_NP, Name: Nepali (Nepal)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ne_NP, Name: Nepali (Nepal)
+default charset: UTF-8
+
+OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
+default locale: ID: fy_NL, Name: Frisian (Netherlands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fy_NL, Name: Frisian (Netherlands)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
+default locale: ID: ps_AF, Name: Pushto (Afghanistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ps_AF, Name: Pushto (Afghanistan)
+default charset: UTF-8
+
+OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
+default locale: ID: fil_PH, Name: Filipino (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
+default locale: ID: fil_PH, Name: Filipino (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
+default locale: ID: dv_MV, Name: Divehi (Maldives)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: dv_MV, Name: Divehi (Maldives)
+default charset: UTF-8
+
+OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
+default locale: ID: yo_NG, Name: Yoruba (Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: yo_NG, Name: Yoruba (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
+default locale: ID: quz_BO, Name: quz (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+default locale: ID: quz_BO, Name: quz (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
+default locale: ID: ba_RU, Name: Bashkir (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ba_RU, Name: Bashkir (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
+default locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+default charset: windows-1252
+
+OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
+default locale: ID: kl_GL, Name: Greenlandic (Greenland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kl_GL, Name: Greenlandic (Greenland)
+default charset: windows-1252
+
+OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
+default locale: ID: ig_NG, Name: Igbo (Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ig_NG, Name: Igbo (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
+default locale: ID: ii_CN, Name: Sichuan Yi (China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ii_CN, Name: Sichuan Yi (China)
+default charset: UTF-8
+
+OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
+default locale: ID: arn_CL, Name: Mapudungun (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+default locale: ID: arn_CL, Name: Mapudungun (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
+default locale: ID: moh_CA, Name: Mohawk (Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
+default locale: ID: moh_CA, Name: Mohawk (Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
+default locale: ID: br_FR, Name: Breton (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: br_FR, Name: Breton (France)
 default charset: windows-1252
-
-OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
+
+OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+default locale: ID: ug_CN, Name: Uighur (China)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ug_CN, Name: Uighur (China)
+default charset: windows-1256
+
+OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
+default locale: ID: mi_NZ, Name: Maori (New Zealand)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mi_NZ, Name: Maori (New Zealand)
+default charset: UTF-8
+
+OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
+default locale: ID: oc_FR, Name: Occitan (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: oc_FR, Name: Occitan (France)
+default charset: windows-1252
+
+OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
+default locale: ID: co_FR, Name: Corsican (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: co_FR, Name: Corsican (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
+default locale: ID: gsw_FR, Name: Swiss German (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+default locale: ID: gsw_FR, Name: Swiss German (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+default locale: ID: sah_RU, Name: Yakut (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+default locale: ID: sah_RU, Name: Yakut (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+default locale: ID: qut_GT, Name: qut (Guatemala)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+default locale: ID: qut_GT, Name: qut (Guatemala)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 default charset: windows-1252
-
-OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
+
+OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 default locale: ID: wo_SN, Name: Wolof (Senegal)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: wo_SN, Name: Wolof (Senegal)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
+default locale: ID: prs_AF, Name: prs (Afghanistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1256
-
-OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
+default locale: ID: prs_AF, Name: prs (Afghanistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1256
-
-OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
+
+OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
+
+OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 default locale: ID: ar_IQ, Name: Arabic (Iraq)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_IQ, Name: Arabic (Iraq)
 default charset: windows-1256
-
-OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: GBK
-
-OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: GBK
-
-OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
+
+OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 default locale: ID: de_CH, Name: German (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_CH, Name: German (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
+
+OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 default locale: ID: en_GB, Name: English (United Kingdom)
-display locale: ID: en_GB, Name: English (United Kingdom)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_GB, Name: English (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
+
+OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 default locale: ID: es_MX, Name: Spanish (Mexico)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_MX, Name: Spanish (Mexico)
 default charset: windows-1252
-
-OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
+
+OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 default locale: ID: fr_BE, Name: French (Belgium)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_BE, Name: French (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
+
+OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 default locale: ID: it_CH, Name: Italian (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: it_CH, Name: Italian (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
+
+OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 default locale: ID: nl_BE, Name: Dutch (Belgium)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: nl_BE, Name: Dutch (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
+
+OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: windows-1252
-
-OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
+
+OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 default locale: ID: pt_PT, Name: Portuguese (Portugal)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: pt_PT, Name: Portuguese (Portugal)
 default charset: windows-1252
-
-OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
-default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+
+OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
+default locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 default charset: windows-1250
-
-OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
+
+OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 default locale: ID: sv_FI, Name: Swedish (Finland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: sv_FI, Name: Swedish (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+
+OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
+default locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1251
-
-OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+
+OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
+default locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1251
-
-OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
+default locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
+default locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
+
+OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 default locale: ID: se_SE, Name: Northern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_SE, Name: Northern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
+
+OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 default locale: ID: ga_IE, Name: Irish (Ireland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ga_IE, Name: Irish (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
+
+OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 default locale: ID: ms_BN, Name: Malay (Brunei)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ms_BN, Name: Malay (Brunei)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+
+OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1251
-
-OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+
+OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1251
-
-OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
+
+OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 default charset: UTF-8
-
-OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
-default locale: ID: mn_CN, Name: Mongolian (China)
+
+OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+default locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: UTF-8
-
-OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
-default locale: ID: mn_CN, Name: Mongolian (China)
+
+OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+default locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: UTF-8
-
-OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
+
+OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
+default locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
+
+OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
+default locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
+default locale: ID: quz_EC, Name: quz (Ecuador)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_EC, Name: quz (Ecuador)
 default charset: windows-1252
-
-OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
+
+OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 default locale: ID: ar_EG, Name: Arabic (Egypt)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_EG, Name: Arabic (Egypt)
 default charset: windows-1256
-
-OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-MS950-HKSCS
-
-OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-windows-950
-
-OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
+
+OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
 default locale: ID: de_AT, Name: German (Austria)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_AT, Name: German (Austria)
 default charset: windows-1252
-
-OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
+
+OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
 default locale: ID: en_AU, Name: English (Australia)
-display locale: ID: en_AU, Name: English (Australia)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_AU, Name: English (Australia)
 default charset: windows-1252
-
-OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
+
+OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
 default locale: ID: es_ES, Name: Spanish (Spain)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_ES, Name: Spanish (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
+
+OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
 default locale: ID: fr_CA, Name: French (Canada)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CA, Name: French (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
-default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+
+OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
+default locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 default charset: windows-1251
-
-OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
+
+OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
 default locale: ID: se_FI, Name: Northern Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_FI, Name: Northern Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
+default locale: ID: quz_PE, Name: quz (Peru)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_PE, Name: quz (Peru)
 default charset: windows-1252
-
-OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
+
+OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
 default locale: ID: ar_LY, Name: Arabic (Libya)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_LY, Name: Arabic (Libya)
 default charset: windows-1256
-
-OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
+
+OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
 default locale: ID: zh_SG, Name: Chinese (Singapore)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_SG, Name: Chinese (Singapore)
 default charset: GBK
-
-OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
+
+OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
 default locale: ID: de_LU, Name: German (Luxembourg)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LU, Name: German (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
+
+OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
 default locale: ID: en_CA, Name: English (Canada)
-display locale: ID: en_CA, Name: English (Canada)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_CA, Name: English (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
+
+OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
 default locale: ID: es_GT, Name: Spanish (Guatemala)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_GT, Name: Spanish (Guatemala)
 default charset: windows-1252
-
-OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
+
+OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
 default locale: ID: fr_CH, Name: French (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CH, Name: French (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
+default locale: ID: smj_NO, Name: Lule Sami (Norway)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_NO, Name: Lule Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
+
+OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
 default locale: ID: ar_DZ, Name: Arabic (Algeria)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_DZ, Name: Arabic (Algeria)
 default charset: windows-1256
-
-OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
+
+OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
 default locale: ID: zh_MO, Name: Chinese (Macao)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_MO, Name: Chinese (Macao)
 default charset: x-windows-950
-
-OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
+
+OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
 default locale: ID: de_LI, Name: German (Liechtenstein)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LI, Name: German (Liechtenstein)
 default charset: windows-1252
-
-OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
+
+OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
 default locale: ID: en_NZ, Name: English (New Zealand)
-display locale: ID: en_NZ, Name: English (New Zealand)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_NZ, Name: English (New Zealand)
 default charset: windows-1252
-
-OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
+
+OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
 default locale: ID: es_CR, Name: Spanish (Costa Rica)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CR, Name: Spanish (Costa Rica)
 default charset: windows-1252
-
-OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
+
+OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
 default locale: ID: fr_LU, Name: French (Luxembourg)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_LU, Name: French (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
+default locale: ID: smj_SE, Name: Lule Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
+default locale: ID: smj_SE, Name: Lule Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
+
+OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
 default locale: ID: ar_MA, Name: Arabic (Morocco)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_MA, Name: Arabic (Morocco)
 default charset: windows-1256
-
-OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
+
+OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
 default locale: ID: en_IE, Name: English (Ireland)
-display locale: ID: en_IE, Name: English (Ireland)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_IE, Name: English (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
+
+OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
 default locale: ID: es_PA, Name: Spanish (Panama)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_PA, Name: Spanish (Panama)
 default charset: windows-1252
-
-OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
+
+OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
 default locale: ID: fr_MC, Name: French (Monaco)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_MC, Name: French (Monaco)
 default charset: windows-1252
-
-OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
+default locale: ID: sma_NO, Name: Southern Sami (Norway)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_NO, Name: Southern Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
+
+OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
 default locale: ID: ar_TN, Name: Arabic (Tunisia)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_TN, Name: Arabic (Tunisia)
 default charset: windows-1256
-
-OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
+
+OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
 default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_ZA, Name: English (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
+
+OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
 default locale: ID: es_DO, Name: Spanish (Dominican Republic)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_DO, Name: Spanish (Dominican Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
+default locale: ID: sma_SE, Name: Southern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
+default locale: ID: sma_SE, Name: Southern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
+
+OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
 default locale: ID: ar_OM, Name: Arabic (Oman)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_OM, Name: Arabic (Oman)
 default charset: windows-1256
-
-OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
+
+OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
 default locale: ID: en_JM, Name: English (Jamaica)
-display locale: ID: en_JM, Name: English (Jamaica)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_JM, Name: English (Jamaica)
 default charset: windows-1252
-
-OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
+
+OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
 default locale: ID: es_VE, Name: Spanish (Venezuela)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_VE, Name: Spanish (Venezuela)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
+default locale: ID: sms_FI, Name: Skolt Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
+default locale: ID: sms_FI, Name: Skolt Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
+
+OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
 default locale: ID: ar_YE, Name: Arabic (Yemen)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_YE, Name: Arabic (Yemen)
 default charset: windows-1256
-
-OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+
+OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
+default locale: ID: en_029, Name: English (Caribbean)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_029, Name: English (Caribbean)
 default charset: windows-1252
-
-OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
+
+OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
 default locale: ID: es_CO, Name: Spanish (Colombia)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CO, Name: Spanish (Colombia)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
-default locale: ID: sr_RS, Name: Serbian (Serbia)
+
+OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1250
+
+OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1250
+
+OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+default locale: ID: smn_FI, Name: Inari Sami (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+default locale: ID: smn_FI, Name: Inari Sami (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
+default locale: ID: ar_SY, Name: Arabic (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_SY, Name: Arabic (Syria)
+default charset: windows-1256
+
+OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
+default locale: ID: en_BZ, Name: English (Belize)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_BZ, Name: English (Belize)
+default charset: windows-1252
+
+OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
+default locale: ID: es_PE, Name: Spanish (Peru)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PE, Name: Spanish (Peru)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1251
+
+OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1251
+
+OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
+default locale: ID: ar_JO, Name: Arabic (Jordan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_JO, Name: Arabic (Jordan)
+default charset: windows-1256
+
+OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
+default locale: ID: en_TT, Name: English (Trinidad and Tobago)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_TT, Name: English (Trinidad and Tobago)
+default charset: windows-1252
+
+OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
+default locale: ID: es_AR, Name: Spanish (Argentina)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_AR, Name: Spanish (Argentina)
+default charset: windows-1252
+
+OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
+default locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
 default charset: windows-1250
-
-OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
-default locale: ID: sr_RS, Name: Serbian (Serbia)
+
+OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
+default locale: ID: ar_LB, Name: Arabic (Lebanon)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_LB, Name: Arabic (Lebanon)
+default charset: windows-1256
+
+OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
+default locale: ID: en_ZW, Name: English (Zimbabwe)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZW, Name: English (Zimbabwe)
+default charset: windows-1252
+
+OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
+default locale: ID: es_EC, Name: Spanish (Ecuador)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_EC, Name: Spanish (Ecuador)
+default charset: windows-1252
+
+OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
+default locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1250
-
-OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
+default charset: windows-1251
+
+OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
+default locale: ID: ar_KW, Name: Arabic (Kuwait)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_KW, Name: Arabic (Kuwait)
+default charset: windows-1256
+
+OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
+default locale: ID: en_PH, Name: English (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_PH, Name: English (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
+default locale: ID: es_CL, Name: Spanish (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_CL, Name: Spanish (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
+default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+default charset: windows-1256
+
+OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
+default locale: ID: es_UY, Name: Spanish (Uruguay)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_UY, Name: Spanish (Uruguay)
+default charset: windows-1252
+
+OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
+default locale: ID: ar_BH, Name: Arabic (Bahrain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_BH, Name: Arabic (Bahrain)
+default charset: windows-1256
+
+OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
+default locale: ID: es_PY, Name: Spanish (Paraguay)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PY, Name: Spanish (Paraguay)
+default charset: windows-1252
+
+OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
+default locale: ID: ar_QA, Name: Arabic (Qatar)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_QA, Name: Arabic (Qatar)
+default charset: windows-1256
+
+OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
+default locale: ID: en_IN, Name: English (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IN, Name: English (India)
+default charset: windows-1252
+
+OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
+default locale: ID: es_BO, Name: Spanish (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_BO, Name: Spanish (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
+default locale: ID: en_MY, Name: English (Malaysia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_MY, Name: English (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
+default locale: ID: es_SV, Name: Spanish (El Salvador)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_SV, Name: Spanish (El Salvador)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
+default locale: ID: en_SG, Name: English (Singapore)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_SG, Name: English (Singapore)
+default charset: windows-1252
+
+OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
+default locale: ID: es_HN, Name: Spanish (Honduras)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_HN, Name: Spanish (Honduras)
+default charset: windows-1252
+
+OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
+default locale: ID: es_NI, Name: Spanish (Nicaragua)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_NI, Name: Spanish (Nicaragua)
+default charset: windows-1252
+
+OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
+default locale: ID: es_PR, Name: Spanish (Puerto Rico)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PR, Name: Spanish (Puerto Rico)
+default charset: windows-1252
+
+OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
+default locale: ID: es_US, Name: Spanish (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_US, Name: Spanish (United States)
+default charset: windows-1252
+
+OS UI Language (name: en-US)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
-default locale: ID: ar_SY, Name: Arabic (Syria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SY, Name: Arabic (Syria)
-default charset: windows-1256
-
-OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
-default locale: ID: en_BZ, Name: English (Belize)
-display locale: ID: en_BZ, Name: English (Belize)
-format locale: ID: en_BZ, Name: English (Belize)
-default charset: windows-1252
-
-OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
-default locale: ID: es_PE, Name: Spanish (Peru)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PE, Name: Spanish (Peru)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: sr_RS, Name: Serbian (Serbia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1251
-
-OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: sr_RS, Name: Serbian (Serbia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1251
-
-OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
-default locale: ID: ar_JO, Name: Arabic (Jordan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_JO, Name: Arabic (Jordan)
-default charset: windows-1256
-
-OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
-default locale: ID: en_TT, Name: English (Trinidad and Tobago)
-display locale: ID: en_TT, Name: English (Trinidad and Tobago)
-format locale: ID: en_TT, Name: English (Trinidad and Tobago)
-default charset: windows-1252
-
-OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
-default locale: ID: es_AR, Name: Spanish (Argentina)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_AR, Name: Spanish (Argentina)
-default charset: windows-1252
-
-OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
-default locale: ID: sr_ME, Name: Serbian (Montenegro)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1250
-
-OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
-default locale: ID: ar_LB, Name: Arabic (Lebanon)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_LB, Name: Arabic (Lebanon)
-default charset: windows-1256
-
-OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
-default locale: ID: en_ZW, Name: English (Zimbabwe)
-display locale: ID: en_ZW, Name: English (Zimbabwe)
-format locale: ID: en_ZW, Name: English (Zimbabwe)
-default charset: windows-1252
-
-OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
-default locale: ID: es_EC, Name: Spanish (Ecuador)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_EC, Name: Spanish (Ecuador)
-default charset: windows-1252
-
-OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
-default locale: ID: sr_ME, Name: Serbian (Montenegro)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1251
-
-OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
-default locale: ID: ar_KW, Name: Arabic (Kuwait)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_KW, Name: Arabic (Kuwait)
-default charset: windows-1256
-
-OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
-default locale: ID: en_PH, Name: English (Philippines)
-display locale: ID: en_PH, Name: English (Philippines)
-format locale: ID: en_PH, Name: English (Philippines)
-default charset: windows-1252
-
-OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
-default locale: ID: es_CL, Name: Spanish (Chile)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_CL, Name: Spanish (Chile)
-default charset: windows-1252
-
-OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
-default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-default charset: windows-1256
-
-OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
-default locale: ID: es_UY, Name: Spanish (Uruguay)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_UY, Name: Spanish (Uruguay)
-default charset: windows-1252
-
-OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
-default locale: ID: ar_BH, Name: Arabic (Bahrain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_BH, Name: Arabic (Bahrain)
-default charset: windows-1256
-
-OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
-default locale: ID: es_PY, Name: Spanish (Paraguay)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PY, Name: Spanish (Paraguay)
-default charset: windows-1252
-
-OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
-default locale: ID: ar_QA, Name: Arabic (Qatar)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_QA, Name: Arabic (Qatar)
-default charset: windows-1256
-
-OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
-default charset: windows-1252
-
-OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
-default locale: ID: es_BO, Name: Spanish (Bolivia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_BO, Name: Spanish (Bolivia)
-default charset: windows-1252
-
-OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
-default locale: ID: en_MY, Name: English (Malaysia)
-display locale: ID: en_MY, Name: English (Malaysia)
-format locale: ID: en_MY, Name: English (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
-default locale: ID: es_SV, Name: Spanish (El Salvador)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_SV, Name: Spanish (El Salvador)
-default charset: windows-1252
-
-OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
-default locale: ID: en_SG, Name: English (Singapore)
-display locale: ID: en_SG, Name: English (Singapore)
-format locale: ID: en_SG, Name: English (Singapore)
-default charset: windows-1252
-
-OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
-default locale: ID: es_HN, Name: Spanish (Honduras)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_HN, Name: Spanish (Honduras)
-default charset: windows-1252
-
-OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
-default locale: ID: es_NI, Name: Spanish (Nicaragua)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_NI, Name: Spanish (Nicaragua)
-default charset: windows-1252
-
-OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
-default locale: ID: es_PR, Name: Spanish (Puerto Rico)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PR, Name: Spanish (Puerto Rico)
-default charset: windows-1252
-
-OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
-default locale: ID: es_US, Name: Spanish (United States)
-display locale: ID: en, Name: English
-format locale: ID: es_US, Name: Spanish (United States)
-default charset: windows-1252
-
-OS UI Language (name: en-US)
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS UI Language (name: ja-JP)
+
+OS UI Language (name: ja-JP)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: ja_JP, Name: Japanese (Japan)
 format locale: ID: en_US, Name: English (United States)
--- a/jdk/test/java/util/ResourceBundle/Bug4168625Test.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/java/util/ResourceBundle/Bug4168625Test.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,7 +25,7 @@
     @summary test Resource Bundle for bug 4168625
     @build Bug4168625Class Bug4168625Getter Bug4168625Resource Bug4168625Resource3 Bug4168625Resource3_en Bug4168625Resource3_en_CA Bug4168625Resource3_en_IE Bug4168625Resource3_en_US Bug4168625Resource2_en_US Bug4168625Resource2
     @run main/timeout=600 Bug4168625Test
-    @bug 4168625
+    @bug 4168625 6993339
 */
 /*
  *
@@ -50,9 +50,8 @@
 import java.io.*;
 
 /**
- *  This test tries to correct three efficiency problems with the caching
- *  mechanism of ResourceBundle.  All tests assume that none of the bundles
- *  have been previously loaded and cached.  It also allows concurrent loads
+ *  This test tries to correct two efficiency problems with the caching
+ *  mechanism of ResourceBundle.  It also allows concurrent loads
  *  of resource bundles to be performed if the bundles are unrelated (ex. a
  *  load of a local system resource by one thread while another thread is
  *  doing a slow load over a network).
@@ -230,83 +229,6 @@
         }
     }
 
-    /**
-     *  Previous versions of ResourceBundle exhibited the following caching behavior.
-     *  Assume the class Bug4168625Resource_en exists. Bug4168625Resource_en_US does
-     *  not.  Two threads, ThreadA and ThreadB both try to get the same bundle.
-     *  <P>
-     *  <pre>
-     *  ThreadA.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      A-->try to load Bug4168625Resource_en_US
-     *  ThreadB.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      B-->try to load Bug4168625Resource_en_US
-     *      B-->load Bug4168625Resource_en (#1)
-     *      A-->load Bug4168625Resource_en (#2)
-     *      A-->cache Bug4168625Resource_en (#2) as Bug4168625Resource_en
-     *      A-->cache Bug4168625Resource_en (#2) as Bug4168625Resource_en_US
-     *      A-->return Bug4168625Resource_en (#2)
-     *      B-->cache Bug4168625Resource_en (#1) as Bug4168625Resource_en
-     *      B-->cache Bug4168625Resource_en (#1) as Bug4168625Resource_en_US
-     *      B-->return Bug4168625Resource_en (#1)
-     *  </pre>
-     *  <P>
-     *  Both threads try and fail to load Bug4168625Resource_en_US.  Both
-     *  threads load Bug4168625Resource_en.  Both threads get their own copy
-     *  of the Bug4168625Resource_en resource.
-     *
-     *  The desired behavior is as follows:
-     *  <P>
-     *  <pre>
-     *  ThreadA.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      A-->try to load Bug4168625Resource_en_US
-     *  ThreadB.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      B-->try to load Bug4168625Resource_en_US
-     *      B-->load Bug4168625Resource_en
-     *      A-->load Bug4168625Resource_en (block in ResourceBundle.getBundle)
-     *      B-->cache Bug4168625Resource_en as Bug4168625Resource_en
-     *      B-->cache Bug4168625Resource_en as Bug4168625Resource_en_US
-     *      A-->return Bug4168625Resource_en
-     *      B-->return Bug4168625Resource_en
-     *  </pre>
-     *  <P>
-     *  Note that both threads return the same bundle object.
-     */
-    public void testConcurrentLoading1() throws Exception {
-        final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
-        final Class c = loader.loadClass("Bug4168625Class");
-        final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
-
-            //both threads want the same resource
-        ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, new Locale("en", "US"));
-        ConcurrentLoadingThread thread2 = new ConcurrentLoadingThread(loader, test, new Locale("en", "US"));
-
-        thread1.start();            //start thread 1
-        loader.waitForNotify(1);    //wait for thread1 to do getBundle & block in loader
-        thread2.start();            //start second thread
-        loader.waitForNotify(2, 1000);  //wait until thread2 blocks somewhere in getBundle
-        thread1.ping();             //continue both threads
-        thread2.ping();
-
-        thread1.join();             //wait unitl both threads complete
-        thread2.join();
-
-            //Now, examine the class loads that were done.
-        loader.logClasses("Classes loaded after completion of both threads:");
-
-        boolean dups = false;
-        for (int i = loader.loadedClasses.size() - 1; i >= 0 ; i--) {
-            final Object item = loader.loadedClasses.elementAt(i);
-            loader.loadedClasses.removeElementAt(i);
-            if (loader.loadedClasses.contains(item)) {
-                logln("Resource loaded more than once: "+item);
-                dups = true;
-            }
-        }
-        if (dups) {
-            errln("ResourceBundle loaded some classes multiple times");
-        }
-    }
-
     private class ConcurrentLoadingThread extends Thread {
         private Loader loader;
         public Object bundle;
@@ -355,7 +277,7 @@
      * This test ensures that multiple resources can be loading at the same
      * time as long as they don't depend on each other in some way.
      */
-    public void testConcurrentLoading2() throws Exception {
+    public void testConcurrentLoading() throws Exception {
         final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
         final Class c = loader.loadClass("Bug4168625Class");
         final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/6989617/bug6989617.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 6989617
+   @summary Enable JComponent to control repaintings of its children
+   @author Alexander Potochkin
+   @run main bug6989617
+*/
+
+import javax.swing.*;
+import java.awt.*;
+
+public class bug6989617 {
+
+    private boolean isPaintingOrigin;
+    private boolean innerPanelRepainted, outerPanelRepainted;
+
+    public bug6989617() {
+
+        final JButton button = new JButton("button");
+
+        JPanel innerPanel = new JPanel() {
+            protected boolean isPaintingOrigin() {
+                return isPaintingOrigin;
+            }
+
+            public void repaint(long tm, int x, int y, int width, int height) {
+                if (button.getParent() != null) {
+                    innerPanelRepainted = true;
+                    if (!button.getSize().equals(new Dimension(width, height))) {
+                        throw new RuntimeException("Wrong size of the dirty area");
+                    }
+                    if (!button.getLocation().equals(new Point(x, y))) {
+                        throw new RuntimeException("Wrong location of the dirty area");
+                    }
+                }
+                super.repaint(tm, x, y, width, height);
+            }
+        };
+
+        JPanel outerPanel = new JPanel() {
+            protected boolean isPaintingOrigin() {
+                return isPaintingOrigin;
+            }
+
+            public void repaint(long tm, int x, int y, int width, int height) {
+                if (button.getParent() != null) {
+                    outerPanelRepainted = true;
+                    if (!button.getSize().equals(new Dimension(width, height))) {
+                        throw new RuntimeException("Wrong size of the dirty area");
+                    }
+                }
+                super.repaint(tm, x, y, width, height);
+            }
+        };
+
+
+        outerPanel.add(innerPanel);
+        innerPanel.add(button);
+
+        outerPanel.setSize(100, 100);
+        innerPanel.setBounds(10, 10, 50, 50);
+        button.setBounds(10, 10, 20, 20);
+
+        if (innerPanelRepainted || outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly on");
+        }
+        button.repaint();
+        if (innerPanelRepainted || outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly on");
+        }
+        isPaintingOrigin = true;
+        button.repaint();
+        if (!innerPanelRepainted || !outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly off");
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        new bug6989617();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/6735286/bug6735286.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 6735286
+   @summary javax.swing.DefaultTableCellRender.getTableCellRendererComponent() doesn't allow passing null Tables
+   @author Pavel Porvatov
+*/
+
+import javax.swing.*;
+
+public class bug6735286 {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                new JTable().getDefaultRenderer(Object.class).getTableCellRendererComponent(null, "a value",
+                        true, true, 0, 0);
+
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/Test6632810.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6632810
+ * @summary javax.swing.plaf.basic.BasicScrollPaneUI.getBaseline(JComponent, int, int) doesn't throw NPE and IAE
+ * @author Pavel Porvatov
+ */
+
+import javax.swing.*;
+import javax.swing.plaf.basic.BasicScrollPaneUI;
+
+public class Test6632810 {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                BasicScrollPaneUI ui = new BasicScrollPaneUI();
+
+                ui.installUI(new JScrollPane());
+
+                try {
+                    ui.getBaseline(null, 1, 1);
+
+                    throw new RuntimeException("getBaseline(null, 1, 1) does not throw NPE");
+                } catch (NullPointerException e) {
+                    // Ok
+                }
+
+                int[][] illegelParams = new int[][]{
+                        {-1, 1,},
+                        {1, -1,},
+                        {-1, -1,},
+                };
+
+                for (int[] illegelParam : illegelParams) {
+                    try {
+                        int width = illegelParam[0];
+                        int height = illegelParam[1];
+
+                        ui.getBaseline(new JScrollPane(), width, height);
+
+                        throw new RuntimeException("getBaseline(new JScrollPane(), " + width + ", " + height +
+                                ") does not throw IAE");
+                    } catch (IllegalArgumentException e) {
+                        // Ok
+                    }
+                }
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/misc/Version/Version.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6994413
+ * @summary Check the JDK and JVM version returned by sun.misc.Version
+ *          matches the versions defined in the system properties
+ * @compile -XDignore.symbol.file Version.java
+ * @run main Version
+ */
+
+import static sun.misc.Version.*;
+public class Version {
+
+    public static void main(String[] args) throws Exception {
+        VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version"));
+        VersionInfo v1 = new VersionInfo(jdkMajorVersion(),
+                                         jdkMinorVersion(),
+                                         jdkMicroVersion(),
+                                         jdkUpdateVersion(),
+                                         jdkSpecialVersion(),
+                                         jdkBuildNumber());
+        System.out.println("JDK version = " + jdk + "  " + v1);
+        if (!jdk.equals(v1)) {
+            throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1);
+        }
+        VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version"));
+        VersionInfo v2 = new VersionInfo(jvmMajorVersion(),
+                                         jvmMinorVersion(),
+                                         jvmMicroVersion(),
+                                         jvmUpdateVersion(),
+                                         jvmSpecialVersion(),
+                                         jvmBuildNumber());
+        System.out.println("JVM version = " + jvm + " " + v2);
+        if (!jvm.equals(v2)) {
+            throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2);
+        }
+    }
+
+    static class VersionInfo {
+        final int major;
+        final int minor;
+        final int micro;
+        final int update;
+        final String special;
+        final int build;
+        VersionInfo(int major, int minor, int micro,
+                    int update, String special, int build) {
+            this.major = major;
+            this.minor = minor;
+            this.micro = micro;
+            this.update = update;
+            this.special = special;
+            this.build = build;
+        }
+
+        public boolean equals(VersionInfo v) {
+            return (this.major == v.major && this.minor == v.minor &&
+                    this.micro == v.micro && this.update == v.update &&
+                    this.special.equals(v.special) && this.build == v.build);
+        }
+
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(major + "." + minor + "." + micro);
+            if (update > 0) {
+                sb.append("_" + update);
+            }
+
+            if (!special.isEmpty()) {
+                sb.append(special);
+            }
+            sb.append("-b" + build);
+            return sb.toString();
+        }
+    }
+
+    private static VersionInfo newVersionInfo(String version) throws Exception {
+        // valid format of the version string is:
+        // n.n.n[_uu[c]][-<identifer>]-bxx
+        int major = 0;
+        int minor = 0;
+        int micro = 0;
+        int update = 0;
+        String special = "";
+        int build = 0;
+        CharSequence cs = version;
+        if (cs.length() >= 5) {
+            if (Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
+                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
+                Character.isDigit(cs.charAt(4))) {
+                major = Character.digit(cs.charAt(0), 10);
+                minor = Character.digit(cs.charAt(2), 10);
+                micro = Character.digit(cs.charAt(4), 10);
+                cs = cs.subSequence(5, cs.length());
+            } else if (Character.isDigit(cs.charAt(0)) &&
+                       Character.isDigit(cs.charAt(1)) && cs.charAt(2) == '.' &&
+                       Character.isDigit(cs.charAt(3))) {
+                // HSX has nn.n (major.minor) version
+                major = Integer.valueOf(version.substring(0, 2)).intValue();
+                minor = Character.digit(cs.charAt(3), 10);
+                cs = cs.subSequence(4, cs.length());
+            }
+            if (cs.charAt(0) == '_' && cs.length() >= 3 &&
+                Character.isDigit(cs.charAt(1)) &&
+                Character.isDigit(cs.charAt(2))) {
+                int nextChar = 3;
+                String uu = cs.subSequence(1, 3).toString();
+                update = Integer.valueOf(uu).intValue();
+                if (cs.length() >= 4) {
+                    char c = cs.charAt(3);
+                    if (c >= 'a' && c <= 'z') {
+                        special = Character.toString(c);
+                        nextChar++;
+                    }
+                }
+                cs = cs.subSequence(nextChar, cs.length());
+            }
+            if (cs.charAt(0) == '-') {
+                // skip the first character
+                // valid format: <identifier>-bxx or bxx
+                // non-product VM will have -debug|-release appended
+                cs = cs.subSequence(1, cs.length());
+                String[] res = cs.toString().split("-");
+                for (String s : res) {
+                    if (s.charAt(0) == 'b') {
+                        build =
+                            Integer.valueOf(s.substring(1, s.length())).intValue();
+                        break;
+                    }
+                }
+            }
+        }
+        return new VersionInfo(major, minor, micro, update, special, build);
+    }
+}
--- a/jdk/test/sun/net/www/http/HttpClient/B6726695.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/net/www/http/HttpClient/B6726695.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6726695
+ * @bug 6726695 6993490
  * @summary HttpURLConnection shoul support 'Expect: 100-contimue' headers for PUT
 */
 
@@ -184,7 +184,15 @@
         out.flush();
         // Then read the body
         char[] cbuf = new char[512];
-        int l = in.read(cbuf);
+        in.read(cbuf);
+
+        /* Force the server to not respond for more that the expect 100-Continue
+         * timeout set by the HTTP handler (5000 millis). This ensures the
+         * timeout is correctly resets the default read timeout, infinity.
+         * See 6993490. */
+        System.out.println("server sleeping...");
+        try {Thread.sleep(6000); } catch (InterruptedException e) {}
+
         // finally send the 200 OK
         out.print("HTTP/1.1 200 OK");
         out.print("Server: Sun-Java-System-Web-Server/7.0\r\n");
--- a/jdk/test/sun/net/www/http/KeepAliveCache/B5045306.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/net/www/http/KeepAliveCache/B5045306.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5045306 6356004
+ * @bug 5045306 6356004 6993490
  * @library ../../httptest/
  * @build HttpCallback HttpServer HttpTransaction
  * @run main/othervm B5045306
@@ -32,7 +32,6 @@
 
 import java.net.*;
 import java.io.*;
-import java.nio.channels.*;
 import java.lang.management.*;
 
 /* Part 1:
@@ -164,6 +163,14 @@
                     failed = true;
 
                 trans.setResponseHeader ("Content-length", Integer.toString(0));
+
+                 /* Force the server to not respond for more that the timeout
+                  * set by the keepalive cleaner (5000 millis). This ensures the
+                  * timeout is correctly resets the default read timeout,
+                  * infinity. See 6993490. */
+                System.out.println("server sleeping...");
+                try {Thread.sleep(6000); } catch (InterruptedException e) {}
+
                 trans.sendResponse(200, "OK");
             } else if(path.equals("/part2")) {
                 System.out.println("Call to /part2");
--- a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6488669 6595324
+ * @bug 6488669 6595324 6993490
  * @run main/othervm ChunkedErrorStream
  * @summary Chunked ErrorStream tests
  */
@@ -48,6 +48,18 @@
  * 2) Client sends request to server and tries to
  *    getErrorStream(). 4K + 10 bytes must be read from
  *    the errorStream.
+ *
+ * Part 3: 6993490
+ *    Reuse persistent connection from part 2, the error stream
+ *    buffering will have set a reduced timeout on the socket and
+ *    tried to reset it to the default, infinity. Client must not
+ *    throw a timeout exception. If it does, it indicates that the
+ *    default timeout was not reset correctly.
+ *    If no timeout exception is thrown, it does not guarantee that
+ *    the timeout was reset correctly, as there is a potential race
+ *    between the sleeping server and the client thread. Typically,
+ *    1000 millis has been enought to reliable reproduce this problem
+ *    since the error stream buffering sets the timeout to 60 millis.
  */
 
 public class ChunkedErrorStream
@@ -75,19 +87,18 @@
         }  finally {
             httpServer.stop(1);
         }
-
     }
 
     void doClient() {
-        for (int times=0; times<2; times++) {
+        for (int times=0; times<3; times++) {
             HttpURLConnection uc = null;
             try {
                 InetSocketAddress address = httpServer.getAddress();
                 String URLStr = "http://localhost:" + address.getPort() + "/test/";
                 if (times == 0) {
-                    URLStr += 6488669;
+                    URLStr += "first";
                 } else {
-                    URLStr += 6595324;
+                    URLStr += "second";
                 }
 
                 System.out.println("Trying " + URLStr);
@@ -97,6 +108,11 @@
 
                 throw new RuntimeException("Failed: getInputStream should throw and IOException");
             }  catch (IOException e) {
+                if (e instanceof SocketTimeoutException) {
+                    e.printStackTrace();
+                    throw new RuntimeException("Failed: SocketTimeoutException should not happen");
+                }
+
                 // This is what we expect to happen.
                 InputStream es = uc.getErrorStream();
                 byte[] ba = new byte[1024];
@@ -112,7 +128,7 @@
                 if (count == 0)
                     throw new RuntimeException("Failed: ErrorStream returning 0 bytes");
 
-                if (times == 1 && count != (4096+10))
+                if (times >= 1 && count != (4096+10))
                     throw new RuntimeException("Failed: ErrorStream returning " + count +
                                                  " bytes. Expecting " + (4096+10));
 
@@ -128,13 +144,13 @@
         httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
 
         // create HttpServer context
-        HttpContext ctx1 = httpServer.createContext("/test/6488669", new Handler6488669());
-        HttpContext ctx2 = httpServer.createContext("/test/6595324", new Handler6595324());
+        httpServer.createContext("/test/first", new FirstHandler());
+        httpServer.createContext("/test/second", new SecondHandler());
 
         httpServer.start();
     }
 
-    class Handler6488669 implements HttpHandler {
+    class FirstHandler implements HttpHandler {
         public void handle(HttpExchange t) throws IOException {
             InputStream is = t.getRequestBody();
             byte[] ba = new byte[1024];
@@ -156,13 +172,22 @@
         }
     }
 
-    class Handler6595324 implements HttpHandler {
+    static class SecondHandler implements HttpHandler {
+        /* count greater than 0, slow response */
+        static int count = 0;
+
         public void handle(HttpExchange t) throws IOException {
             InputStream is = t.getRequestBody();
             byte[] ba = new byte[1024];
             while (is.read(ba) != -1);
             is.close();
 
+            if (count > 0) {
+                System.out.println("server sleeping...");
+                try { Thread.sleep(1000); } catch(InterruptedException e) {}
+            }
+            count++;
+
             t.sendResponseHeaders(404, 0);
             OutputStream os = t.getResponseBody();
 
--- a/jdk/test/sun/security/ec/TestEC.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ec/TestEC.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,8 @@
  * @test
  * @bug 6840752
  * @summary  Provide out-of-the-box support for ECC algorithms
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @library ../pkcs11
  * @library ../pkcs11/ec
  * @library ../pkcs11/sslecc
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Tue Nov 09 22:53:18 2010 -0800
@@ -245,7 +245,7 @@
                         name.indexOf('/') < 0 ?
                             PrincipalName.KRB_NT_UNKNOWN :
                             PrincipalName.KRB_NT_SRV_HST),
-                            kdc.passwords.get(name));
+                            kdc.passwords.get(name), -1, true);
             }
         }
         ktab.save();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/KtabCheck.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.ktab.KeyTabEntry;
+
+/**
+ * This class is called by the test ktcheck.sh and is not meant to run
+ * by itself.
+ */
+public class KtabCheck {
+    /**
+     * Checks if a keytab contains exactly the keys (kvno and etype)
+     * @param args keytabname kvno etype...
+     */
+    public static void main(String[] args) throws Exception {
+        System.out.println("Checking " + Arrays.toString(args));
+        KeyTab ktab = KeyTab.getInstance(args[0]);
+        Set<String> expected = new HashSet<String>();
+        for (int i=1; i<args.length; i += 2) {
+            expected.add(args[i]+":"+args[i+1]);
+        }
+        for (KeyTabEntry e: ktab.getEntries()) {
+            // KVNO and etype
+            String vne = e.getKey().getKeyVersionNumber() + ":" +
+                    e.getKey().getEType();
+            if (!expected.contains(vne)) {
+                throw new Exception("No " + vne + " in expected");
+            }
+            expected.remove(vne);
+        }
+        if (!expected.isEmpty()) {
+            throw new Exception("Extra elements in expected");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/ktcheck.sh	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,94 @@
+#
+# Copyright (c) 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.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 6950546
+# @summary "ktab -d name etype" to "ktab -d name [-e etype] [kvno | all | old]"
+# @run shell ktcheck.sh
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+  JAVAC_CMD=`which javac`
+  TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+if [ "${TESTSRC}" = "" ] ; then
+  TESTSRC="."
+fi
+
+OS=`uname -s`
+case "$OS" in
+  CYGWIN* )
+    FS="/"
+    ;;
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    echo "Unsupported system!"
+    exit 0;
+    ;;
+esac
+
+KEYTAB=ktab.tmp
+
+rm $KEYTAB
+${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}KtabCheck.java
+
+EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf"
+KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f"
+CHECK="${TESTJAVA}${FS}bin${FS}java ${EXTRA_OPTIONS} KtabCheck $KEYTAB"
+
+echo ${EXTRA_OPTIONS}
+
+$KTAB -a me mine
+$CHECK 1 16 1 23 1 17 || exit 1
+$KTAB -a me mine -n 0
+$CHECK 0 16 0 23 0 17 || exit 1
+$KTAB -a me mine -n 1 -append
+$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 || exit 1
+$KTAB -a me mine -append
+$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 2 16 2 23 2 17 || exit 1
+$KTAB -a me mine
+$CHECK 3 16 3 23 3 17 || exit 1
+$KTAB -a me mine -n 4 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 || exit 1
+$KTAB -a me mine -n 5 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 || exit 1
+$KTAB -a me mine -n 6 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1
+$KTAB -d me 3
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1
+$KTAB -d me -e 16 6
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 6 17 || exit 1
+$KTAB -d me -e 17 6
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 || exit 1
+$KTAB -d me -e 16 5
+$CHECK 4 16 4 23 4 17 5 23 5 17 6 23 || exit 1
+$KTAB -d me old
+$CHECK 4 16 5 17 6 23 || exit 1
+$KTAB -d me old
+$CHECK 4 16 5 17 6 23 || exit 1
+$KTAB -d me
+$CHECK || exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/onlythree.conf	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,9 @@
+[libdefaults]
+default_realm = LOCAL.COM
+default_tkt_enctypes = des3-cbc-sha1 rc4-hmac aes128-cts
+
+[realms]
+LOCAL.COM = {
+    kdc = localhost
+}
+
--- a/jdk/test/sun/security/pkcs11/fips/CipherTest.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/fips/CipherTest.java	Tue Nov 09 22:53:18 2010 -0800
@@ -119,6 +119,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -149,18 +156,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -293,11 +296,12 @@
         return ks;
     }
 
-    public static void main(PeerFactory peerFactory, KeyStore keyStore, String[] args)
-            throws Exception {
+    public static void main(PeerFactory peerFactory, KeyStore keyStore,
+            String[] args) throws Exception {
+
         long time = System.currentTimeMillis();
         String relPath;
-        if ((args.length > 0) && args[0].equals("sh")) {
+        if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
             relPath = pathToStoresSH;
         } else {
             relPath = pathToStores;
@@ -345,7 +349,30 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
             return true;
         }
     }
--- a/jdk/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,8 @@
  * @test
  * @bug 6313675 6323647
  * @summary Verify that all ciphersuites work in FIPS mode
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Andreas Sterbenz
  * @library ..
  */
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Tue Nov 09 22:53:18 2010 -0800
@@ -119,6 +119,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -148,18 +155,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -275,7 +278,6 @@
 
     // for some reason, ${test.src} has a different value when the
     // test is called from the script and when it is called directly...
-//    static String pathToStores = "../../etc";
     static String pathToStores = ".";
     static String pathToStoresSH = ".";
     static String keyStoreFile = "keystore";
@@ -336,7 +338,30 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
             return true;
         }
     }
--- a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -125,16 +125,23 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
-                SecretKey masterKey = new SecretKeySpec(master, "TlsMasterSecret");
-                TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-                (masterKey, major, minor, clientRandom, serverRandom, cipherAlgorithm,
-                keyLength, expandedKeyLength, ivLength, macLength);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
+                SecretKey masterKey =
+                    new SecretKeySpec(master, "TlsMasterSecret");
+                TlsKeyMaterialParameterSpec spec =
+                    new TlsKeyMaterialParameterSpec(masterKey, major, minor,
+                    clientRandom, serverRandom, cipherAlgorithm,
+                    keyLength, expandedKeyLength, ivLength, macLength,
+                    null, -1, -1);
 
                 kg.init(spec);
-                TlsKeyMaterialSpec result = (TlsKeyMaterialSpec)kg.generateKey();
-                match(lineNumber, clientCipherBytes, result.getClientCipherKey(), cipherAlgorithm);
-                match(lineNumber, serverCipherBytes, result.getServerCipherKey(), cipherAlgorithm);
+                TlsKeyMaterialSpec result =
+                    (TlsKeyMaterialSpec)kg.generateKey();
+                match(lineNumber, clientCipherBytes,
+                    result.getClientCipherKey(), cipherAlgorithm);
+                match(lineNumber, serverCipherBytes,
+                    result.getServerCipherKey(), cipherAlgorithm);
                 match(lineNumber, clientIv, result.getClientIv(), "");
                 match(lineNumber, serverIv, result.getServerIv(), "");
                 match(lineNumber, clientMacBytes, result.getClientMacKey(), "");
@@ -158,7 +165,8 @@
         }
     }
 
-    private static void match(int lineNumber, byte[] out, Object res, String cipherAlgorithm) throws Exception {
+    private static void match(int lineNumber, byte[] out, Object res,
+            String cipherAlgorithm) throws Exception {
         if ((out == null) || (res == null)) {
             if (out != res) {
                 throw new Exception("null mismatch line " + lineNumber);
@@ -169,7 +177,8 @@
         byte[] b;
         if (res instanceof SecretKey) {
             b = ((SecretKey)res).getEncoded();
-            if (cipherAlgorithm.equalsIgnoreCase("DES") || cipherAlgorithm.equalsIgnoreCase("DESede")) {
+            if (cipherAlgorithm.equalsIgnoreCase("DES") ||
+                    cipherAlgorithm.equalsIgnoreCase("DESede")) {
                 // strip DES parity bits before comparision
                 stripParity(out);
                 stripParity(b);
--- a/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -104,17 +104,22 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsMasterSecret", provider);
-                SecretKey premasterKey = new SecretKeySpec(premaster, algorithm);
-                TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                    (premasterKey, protoMajor, protoMinor, clientRandom, serverRandom);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsMasterSecret", provider);
+                SecretKey premasterKey =
+                    new SecretKeySpec(premaster, algorithm);
+                TlsMasterSecretParameterSpec spec =
+                    new TlsMasterSecretParameterSpec(premasterKey,
+                        protoMajor, protoMinor, clientRandom, serverRandom,
+                        null, -1, -1);
                 kg.init(spec);
                 TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
                 byte[] enc = key.getEncoded();
                 if (Arrays.equals(master, enc) == false) {
                     throw new Exception("mismatch line: " + lineNumber);
                 }
-                if ((preMajor != key.getMajorVersion()) || (preMinor != key.getMinorVersion())) {
+                if ((preMajor != key.getMajorVersion()) ||
+                        (preMinor != key.getMinorVersion())) {
                     throw new Exception("version mismatch line: " + lineNumber);
                 }
             } else {
--- a/jdk/test/sun/security/pkcs11/tls/TestPRF.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/tls/TestPRF.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -93,14 +93,17 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsPrf", provider);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsPrf", provider);
                 SecretKey inKey;
                 if (secret == null) {
                     inKey = null;
                 } else {
                     inKey = new SecretKeySpec(secret, "Generic");
                 }
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(inKey, label, seed, length);
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        null, -1, -1);
                 SecretKey key;
                 try {
                     kg.init(spec);
@@ -109,7 +112,8 @@
                     if (secret == null) {
                         // This fails on Solaris, but since we never call this
                         // API for this case in JSSE, ignore the failure.
-                        // (SunJSSE uses the CKM_TLS_KEY_AND_MAC_DERIVE mechanism)
+                        // (SunJSSE uses the CKM_TLS_KEY_AND_MAC_DERIVE
+                        // mechanism)
                         System.out.print("X");
                         continue;
                     }
--- a/jdk/test/sun/security/pkcs11/tls/TestPremaster.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/pkcs11/tls/TestPremaster.java	Tue Nov 09 22:53:18 2010 -0800
@@ -44,7 +44,8 @@
     }
 
     public void main(Provider provider) throws Exception {
-        if (provider.getService("KeyGenerator", "SunTlsRsaPremasterSecret") == null) {
+        if (provider.getService(
+                "KeyGenerator", "SunTlsRsaPremasterSecret") == null) {
             System.out.println("Not supported by provider, skipping");
             return;
         }
@@ -66,7 +67,8 @@
         System.out.println("Done.");
     }
 
-    private static void test(KeyGenerator kg, int major, int minor) throws Exception {
+    private static void test(KeyGenerator kg, int major, int minor)
+            throws Exception {
 
         kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
         SecretKey key = kg.generateKey();
@@ -75,7 +77,8 @@
             throw new Exception("length: " + encoded.length);
         }
         if ((encoded[0] != major) || (encoded[1] != minor)) {
-            throw new Exception("version mismatch: "  + encoded[0] + "." + encoded[1]);
+            throw new Exception("version mismatch: "  + encoded[0] +
+                "." + encoded[1]);
         }
         System.out.println("OK: " + major + "." + minor);
     }
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java	Tue Nov 09 22:53:18 2010 -0800
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 4390659
+ * @run main/othervm -Djavax.net.debug=all ClientModeClientAuth
  * @summary setNeedClientAuth() isn't working after a handshaker is established
  * @author Brad Wetmore
  */
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,8 @@
  * @test
  * @bug 4717766
  * @summary 1.0.3 JsseX509TrustManager erroneously calls isClientTrusted()
+ * @ignore JSSE supports algorithm constraints with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Brad Wetmore
  *
  * This problem didn't exist in JSSE 1.4, only JSSE 1.0.3.  However,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @bug 6916074
+ * @summary Add support for TLS 1.2
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.math.BigInteger;
+
+
+/*
+ * Certificates and key used in the test.
+ *
+ * TLS server certificate:
+ * server private key:
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A
+ *
+ * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e
+ * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI
+ * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n
+ * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb
+ * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP
+ * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz
+ * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF
+ * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J
+ * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa
+ * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH
+ * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT
+ * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q
+ * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie
+ * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU
+ * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB
+ * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi
+ * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y
+ * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo
+ * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4
+ * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51
+ * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16
+ * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2
+ * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC
+ * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF
+ * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *     d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *     1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *     ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *     7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *     9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *     d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *     7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *     30:05:40:2c:4f:ab:d9:74:89
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90:
+ *     60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82:
+ *     e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62:
+ *     0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9:
+ *     4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77:
+ *     76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09:
+ *     6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b:
+ *     fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3:
+ *     37:6b:37:59:ed:db:6d:b1
+ * prime1:
+ *     00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a:
+ *     ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46:
+ *     89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33:
+ *     c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7:
+ *     d6:11:4c:99:c7
+ * prime2:
+ *     00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e:
+ *     97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7:
+ *     31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0:
+ *     3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc:
+ *     e0:e1:84:ff:2f
+ * exponent1:
+ *     7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8:
+ *     8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1:
+ *     32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c:
+ *     6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d:
+ *     12:b7:6e:91
+ * exponent2:
+ *     00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50:
+ *     d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b:
+ *     0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72:
+ *     98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4:
+ *     19:7b:b0:de:53
+ * coefficient:
+ *     71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35:
+ *     cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a:
+ *     90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df:
+ *     06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21:
+ *     12:d7:eb:4f
+ *
+ *
+ * server certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 8 (0x8)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:04 2008 GMT
+ *         Not After : Aug 25 03:43:04 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *                 d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *                 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *                 ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *                 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *                 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *                 d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *                 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *                 30:05:40:2c:4f:ab:d9:74:89
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption0
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3
+ * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6
+ * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS
+ * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac
+ * PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi
+ * nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn
+ * JqCpf5uZGOo=
+ * -----END CERTIFICATE-----
+ *
+ *
+ * TLS client certificate:
+ * client private key:
+ * ----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390
+ *
+ * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4
+ * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf
+ * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak
+ * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH
+ * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat
+ * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46
+ * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++
+ * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+
+ * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN
+ * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U
+ * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO
+ * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig
+ * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4
+ * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z
+ * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB
+ * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW
+ * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf
+ * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6
+ * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3
+ * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX
+ * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM
+ * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1
+ * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j
+ * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY
+ * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *     21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *     12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *     01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *     7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *     35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *     ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *     28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *     75:8d:f5:82:ac:43:92:44:1b
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b:
+ *     25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05:
+ *     fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96:
+ *     b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0:
+ *     26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51:
+ *     2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef:
+ *     47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94:
+ *     4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1:
+ *     e5:28:9b:f9:4c:94:c6:b1
+ * prime1:
+ *     00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38:
+ *     2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f:
+ *     a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f:
+ *     1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14:
+ *     e2:a0:4d:ab:b5
+ * prime2:
+ *     00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d:
+ *     96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3:
+ *     3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4:
+ *     bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4:
+ *     76:7d:ce:32:8f
+ * exponent1:
+ *     2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f:
+ *     33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b:
+ *     9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa:
+ *     28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2:
+ *     4c:de:38:95
+ * exponent2:
+ *     0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3:
+ *     ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce:
+ *     69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3:
+ *     eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b:
+ *     0d:78:df:fd
+ * coefficient:
+ *     01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31:
+ *     de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18:
+ *     aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56:
+ *     93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da:
+ *     35:92:f2:e3
+ *
+ * client certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 9 (0x9)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:24 2008 GMT
+ *         Not After : Aug 25 03:43:24 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *                 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *                 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *                 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *                 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *                 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *                 ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *                 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *                 75:8d:f5:82:ac:43:92:44:1b
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas
+ * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV
+ * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq
+ * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F
+ * HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj
+ * XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN
+ * cl/epUcHL7E=
+ * -----END CERTIFICATE-----
+ *
+ *
+ *
+ * Trusted CA certificate:
+ * Certificate:
+ *   Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 0 (0x0)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 02:43:36 2008 GMT
+ *         Not After : Aug 25 02:43:36 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d:
+ *                 d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53:
+ *                 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9:
+ *                 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f:
+ *                 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7:
+ *                 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee:
+ *                 f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee:
+ *                 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97:
+ *                 89:2a:95:12:4c:d8:09:2a:e9
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Subject Key Identifier:
+ *             FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *             DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org
+ *             serial:00
+ *
+ *         X509v3 Basic Constraints:
+ *             CA:TRUE
+ *  Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+ * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX
+ * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj
+ * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G
+ * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ
+ * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt
+ * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw
+ * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA
+ * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ
+ * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P
+ * 6Mvf0r1PNTY2hwTJLJmKtg==
+ * -----END CERTIFICATE---
+ */
+
+
+public class PKIXExtendedTM {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String trusedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+        "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" +
+        "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" +
+        "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" +
+        "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" +
+        "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" +
+        "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" +
+        "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" +
+        "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" +
+        "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" +
+        "6Mvf0r1PNTY2hwTJLJmKtg==\n" +
+        "-----END CERTIFICATE-----";
+
+    static String serverCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" +
+        "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" +
+        "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" +
+        "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac\n" +
+        "PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi\n" +
+        "nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn\n" +
+        "JqCpf5uZGOo=\n" +
+        "-----END CERTIFICATE-----";
+
+    static String clientCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" +
+        "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" +
+        "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" +
+        "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F\n" +
+        "HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj\n" +
+        "XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN\n" +
+        "cl/epUcHL7E=\n" +
+        "-----END CERTIFICATE-----";
+
+    static byte serverPrivateExponent[] = {
+        (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83,
+        (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44,
+        (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89,
+        (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60,
+        (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21,
+        (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc,
+        (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e,
+        (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3,
+        (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54,
+        (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf,
+        (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0,
+        (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9,
+        (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29,
+        (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c,
+        (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9,
+        (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6,
+        (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72,
+        (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4,
+        (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76,
+        (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f,
+        (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5,
+        (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71,
+        (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e,
+        (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4,
+        (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a,
+        (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4,
+        (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a,
+        (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18,
+        (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba,
+        (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3,
+        (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59,
+        (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1
+    };
+
+    static byte serverModulus[] = {
+        (byte)0x00,
+        (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c,
+        (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99,
+        (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79,
+        (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48,
+        (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84,
+        (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c,
+        (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9,
+        (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39,
+        (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72,
+        (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44,
+        (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc,
+        (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6,
+        (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54,
+        (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc,
+        (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f,
+        (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f,
+        (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2,
+        (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88,
+        (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f,
+        (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53,
+        (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33,
+        (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47,
+        (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea,
+        (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75,
+        (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc,
+        (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9,
+        (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2,
+        (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24,
+        (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03,
+        (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30,
+        (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f,
+        (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89
+    };
+
+    static byte clientPrivateExponent[] = {
+        (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36,
+        (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce,
+        (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84,
+        (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25,
+        (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4,
+        (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a,
+        (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19,
+        (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2,
+        (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77,
+        (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84,
+        (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41,
+        (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8,
+        (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71,
+        (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a,
+        (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0,
+        (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6,
+        (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39,
+        (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e,
+        (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a,
+        (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88,
+        (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89,
+        (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d,
+        (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a,
+        (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69,
+        (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37,
+        (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7,
+        (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27,
+        (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8,
+        (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8,
+        (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1,
+        (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9,
+        (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1
+    };
+
+    static byte clientModulus[] = {
+        (byte)0x00,
+        (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36,
+        (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e,
+        (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00,
+        (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f,
+        (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93,
+        (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1,
+        (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8,
+        (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99,
+        (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f,
+        (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24,
+        (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7,
+        (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44,
+        (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2,
+        (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c,
+        (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d,
+        (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a,
+        (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6,
+        (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f,
+        (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97,
+        (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05,
+        (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf,
+        (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3,
+        (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c,
+        (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf,
+        (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56,
+        (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9,
+        (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf,
+        (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab,
+        (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1,
+        (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75,
+        (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac,
+        (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b
+    };
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = getSSLContext(trusedCertStr, serverCertStr,
+            serverModulus, serverPrivateExponent, passphrase);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = getSSLContext(trusedCertStr, clientCertStr,
+            clientModulus, clientPrivateExponent, passphrase);
+
+        SSLSocketFactory sslsf = context.getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+    }
+
+    // get the ssl context
+    private static SSLContext getSSLContext(String trusedCertStr,
+            String keyCertStr, byte[] modulus,
+            byte[] privateExponent, char[] passphrase) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trusedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        ks.setCertificateEntry("RSA Export Signer", trusedCert);
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
+                                            new BigInteger(modulus),
+                                            new BigInteger(privateExponent));
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            RSAPrivateKey priKey =
+                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = keyCert;
+            chain[1] = trusedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+        tmf.init(ks);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+               throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        if (keyCertStr != null) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String args[]) throws Exception {
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new PKIXExtendedTM();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    PKIXExtendedTM() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            doServerSide();
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            doClientSide();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,884 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6916074
+ * @run main/othervm -Djavax.net.debug=all SunX509ExtendedTM
+ * @summary Add support for TLS 1.2
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.math.BigInteger;
+
+
+/*
+ * Certificates and key used in the test.
+ *
+ * TLS server certificate:
+ * server private key:
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A
+ *
+ * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e
+ * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI
+ * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n
+ * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb
+ * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP
+ * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz
+ * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF
+ * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J
+ * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa
+ * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH
+ * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT
+ * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q
+ * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie
+ * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU
+ * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB
+ * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi
+ * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y
+ * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo
+ * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4
+ * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51
+ * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16
+ * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2
+ * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC
+ * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF
+ * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *     d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *     1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *     ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *     7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *     9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *     d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *     7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *     30:05:40:2c:4f:ab:d9:74:89
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90:
+ *     60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82:
+ *     e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62:
+ *     0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9:
+ *     4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77:
+ *     76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09:
+ *     6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b:
+ *     fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3:
+ *     37:6b:37:59:ed:db:6d:b1
+ * prime1:
+ *     00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a:
+ *     ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46:
+ *     89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33:
+ *     c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7:
+ *     d6:11:4c:99:c7
+ * prime2:
+ *     00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e:
+ *     97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7:
+ *     31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0:
+ *     3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc:
+ *     e0:e1:84:ff:2f
+ * exponent1:
+ *     7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8:
+ *     8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1:
+ *     32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c:
+ *     6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d:
+ *     12:b7:6e:91
+ * exponent2:
+ *     00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50:
+ *     d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b:
+ *     0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72:
+ *     98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4:
+ *     19:7b:b0:de:53
+ * coefficient:
+ *     71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35:
+ *     cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a:
+ *     90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df:
+ *     06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21:
+ *     12:d7:eb:4f
+ *
+ *
+ * server certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 8 (0x8)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:04 2008 GMT
+ *         Not After : Aug 25 03:43:04 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *                 d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *                 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *                 ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *                 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *                 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *                 d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *                 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *                 30:05:40:2c:4f:ab:d9:74:89
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption0
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3
+ * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6
+ * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS
+ * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac
+ * PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi
+ * nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn
+ * JqCpf5uZGOo=
+ * -----END CERTIFICATE-----
+ *
+ *
+ * TLS client certificate:
+ * client private key:
+ * ----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390
+ *
+ * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4
+ * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf
+ * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak
+ * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH
+ * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat
+ * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46
+ * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++
+ * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+
+ * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN
+ * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U
+ * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO
+ * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig
+ * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4
+ * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z
+ * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB
+ * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW
+ * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf
+ * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6
+ * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3
+ * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX
+ * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM
+ * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1
+ * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j
+ * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY
+ * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *     21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *     12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *     01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *     7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *     35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *     ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *     28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *     75:8d:f5:82:ac:43:92:44:1b
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b:
+ *     25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05:
+ *     fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96:
+ *     b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0:
+ *     26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51:
+ *     2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef:
+ *     47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94:
+ *     4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1:
+ *     e5:28:9b:f9:4c:94:c6:b1
+ * prime1:
+ *     00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38:
+ *     2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f:
+ *     a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f:
+ *     1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14:
+ *     e2:a0:4d:ab:b5
+ * prime2:
+ *     00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d:
+ *     96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3:
+ *     3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4:
+ *     bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4:
+ *     76:7d:ce:32:8f
+ * exponent1:
+ *     2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f:
+ *     33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b:
+ *     9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa:
+ *     28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2:
+ *     4c:de:38:95
+ * exponent2:
+ *     0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3:
+ *     ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce:
+ *     69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3:
+ *     eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b:
+ *     0d:78:df:fd
+ * coefficient:
+ *     01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31:
+ *     de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18:
+ *     aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56:
+ *     93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da:
+ *     35:92:f2:e3
+ *
+ * client certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 9 (0x9)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:24 2008 GMT
+ *         Not After : Aug 25 03:43:24 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *                 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *                 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *                 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *                 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *                 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *                 ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *                 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *                 75:8d:f5:82:ac:43:92:44:1b
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas
+ * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV
+ * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq
+ * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F
+ * HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj
+ * XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN
+ * cl/epUcHL7E=
+ * -----END CERTIFICATE-----
+ *
+ *
+ *
+ * Trusted CA certificate:
+ * Certificate:
+ *   Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 0 (0x0)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 02:43:36 2008 GMT
+ *         Not After : Aug 25 02:43:36 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d:
+ *                 d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53:
+ *                 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9:
+ *                 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f:
+ *                 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7:
+ *                 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee:
+ *                 f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee:
+ *                 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97:
+ *                 89:2a:95:12:4c:d8:09:2a:e9
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Subject Key Identifier:
+ *             FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *             DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org
+ *             serial:00
+ *
+ *         X509v3 Basic Constraints:
+ *             CA:TRUE
+ *  Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+ * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX
+ * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj
+ * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G
+ * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ
+ * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt
+ * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw
+ * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA
+ * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ
+ * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P
+ * 6Mvf0r1PNTY2hwTJLJmKtg==
+ * -----END CERTIFICATE---
+ */
+
+
+public class SunX509ExtendedTM {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String trusedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+        "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" +
+        "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" +
+        "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" +
+        "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" +
+        "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" +
+        "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" +
+        "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" +
+        "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" +
+        "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" +
+        "6Mvf0r1PNTY2hwTJLJmKtg==\n" +
+        "-----END CERTIFICATE-----";
+
+    static String serverCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" +
+        "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" +
+        "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" +
+        "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac\n" +
+        "PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi\n" +
+        "nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn\n" +
+        "JqCpf5uZGOo=\n" +
+        "-----END CERTIFICATE-----";
+
+    static String clientCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" +
+        "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" +
+        "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" +
+        "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F\n" +
+        "HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj\n" +
+        "XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN\n" +
+        "cl/epUcHL7E=\n" +
+        "-----END CERTIFICATE-----";
+
+    static byte serverPrivateExponent[] = {
+        (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83,
+        (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44,
+        (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89,
+        (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60,
+        (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21,
+        (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc,
+        (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e,
+        (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3,
+        (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54,
+        (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf,
+        (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0,
+        (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9,
+        (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29,
+        (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c,
+        (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9,
+        (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6,
+        (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72,
+        (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4,
+        (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76,
+        (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f,
+        (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5,
+        (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71,
+        (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e,
+        (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4,
+        (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a,
+        (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4,
+        (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a,
+        (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18,
+        (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba,
+        (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3,
+        (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59,
+        (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1
+    };
+
+    static byte serverModulus[] = {
+        (byte)0x00,
+        (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c,
+        (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99,
+        (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79,
+        (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48,
+        (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84,
+        (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c,
+        (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9,
+        (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39,
+        (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72,
+        (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44,
+        (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc,
+        (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6,
+        (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54,
+        (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc,
+        (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f,
+        (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f,
+        (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2,
+        (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88,
+        (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f,
+        (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53,
+        (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33,
+        (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47,
+        (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea,
+        (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75,
+        (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc,
+        (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9,
+        (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2,
+        (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24,
+        (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03,
+        (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30,
+        (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f,
+        (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89
+    };
+
+    static byte clientPrivateExponent[] = {
+        (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36,
+        (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce,
+        (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84,
+        (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25,
+        (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4,
+        (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a,
+        (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19,
+        (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2,
+        (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77,
+        (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84,
+        (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41,
+        (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8,
+        (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71,
+        (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a,
+        (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0,
+        (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6,
+        (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39,
+        (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e,
+        (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a,
+        (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88,
+        (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89,
+        (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d,
+        (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a,
+        (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69,
+        (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37,
+        (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7,
+        (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27,
+        (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8,
+        (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8,
+        (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1,
+        (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9,
+        (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1
+    };
+
+    static byte clientModulus[] = {
+        (byte)0x00,
+        (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36,
+        (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e,
+        (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00,
+        (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f,
+        (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93,
+        (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1,
+        (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8,
+        (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99,
+        (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f,
+        (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24,
+        (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7,
+        (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44,
+        (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2,
+        (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c,
+        (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d,
+        (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a,
+        (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6,
+        (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f,
+        (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97,
+        (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05,
+        (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf,
+        (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3,
+        (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c,
+        (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf,
+        (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56,
+        (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9,
+        (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf,
+        (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab,
+        (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1,
+        (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75,
+        (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac,
+        (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b
+    };
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = getSSLContext(trusedCertStr, serverCertStr,
+            serverModulus, serverPrivateExponent, passphrase);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = getSSLContext(trusedCertStr, clientCertStr,
+            clientModulus, clientPrivateExponent, passphrase);
+
+        SSLSocketFactory sslsf = context.getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+    }
+
+    // get the ssl context
+    private static SSLContext getSSLContext(String trusedCertStr,
+            String keyCertStr, byte[] modulus,
+            byte[] privateExponent, char[] passphrase) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trusedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        ks.setCertificateEntry("RSA Export Signer", trusedCert);
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
+                                            new BigInteger(modulus),
+                                            new BigInteger(privateExponent));
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            RSAPrivateKey priKey =
+                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = keyCert;
+            chain[1] = trusedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf =
+                TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ks);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+            throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        if (keyCertStr != null) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String args[]) throws Exception {
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new SunX509ExtendedTM();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    SunX509ExtendedTM() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            doServerSide();
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            doClientSide();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6916074
+ * @summary Add support for TLS 1.2
+ *
+ * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager.
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.security.*;
+
+public class X509ExtendedTMEnabled {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "../../../../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+    private final static char[] cpasswd = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf =
+                                getContext(true).getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+
+        if (!serverTM.wasServerChecked() && serverTM.wasClientChecked()) {
+            System.out.println("SERVER TEST PASSED!");
+        } else {
+            throw new Exception("SERVER TEST FAILED!  " +
+                !serverTM.wasServerChecked() + " " +
+                serverTM.wasClientChecked());
+        }
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf = getContext(false).getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+        if (clientTM.wasServerChecked() && !clientTM.wasClientChecked()) {
+            System.out.println("CLIENT TEST PASSED!");
+        } else {
+            throw new Exception("CLIENT TEST FAILED!  " +
+                clientTM.wasServerChecked() + " " +
+                !clientTM.wasClientChecked());
+        }
+    }
+
+    MyExtendedX509TM serverTM;
+    MyExtendedX509TM clientTM;
+
+    private SSLContext getContext(boolean server) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", "./") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", "./") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(new FileInputStream(keyFilename), cpasswd);
+        kmf.init(ks, cpasswd);
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        KeyStore ts = KeyStore.getInstance("JKS");
+        ts.load(new FileInputStream(trustFilename), cpasswd);
+        tmf.init(ts);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509TrustManager)) {
+            throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+        if (server) {
+            serverTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+            tms = new TrustManager[] {serverTM};
+        } else {
+            clientTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+            tms = new TrustManager[] {clientTM};
+        }
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        ctx.init(kmf.getKeyManagers(), tms, null);
+
+        return ctx;
+    }
+
+    static class MyExtendedX509TM extends X509ExtendedTrustManager
+            implements X509TrustManager {
+
+        X509TrustManager tm;
+
+        boolean clientChecked;
+        boolean serverChecked;
+
+        MyExtendedX509TM(X509TrustManager tm) {
+            clientChecked = false;
+            serverChecked = false;
+
+            this.tm = tm;
+        }
+
+        public boolean wasClientChecked() {
+            return clientChecked;
+        }
+
+        public boolean wasServerChecked() {
+            return serverChecked;
+        }
+
+
+        public void checkClientTrusted(X509Certificate chain[], String authType)
+                throws CertificateException {
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate chain[], String authType)
+                throws CertificateException {
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return tm.getAcceptedIssuers();
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+            clientChecked = true;
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+            serverChecked = true;
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+            clientChecked = true;
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+            serverChecked = true;
+            tm.checkServerTrusted(chain, authType);
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new X509ExtendedTMEnabled();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    X509ExtendedTMEnabled() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            doServerSide();
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+              * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            doClientSide();
+        }
+    }
+}
+
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,6 +26,8 @@
  * @bug 4329114
  * @summary Need better way of reflecting the reason when a chain is
  *      rejected as untrusted.
+ * @ignore JSSE supports algorithm constraints with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * This is a serious hack job!
  * @author Brad Wetmore
  */
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,6 +26,8 @@
  * @bug 4495742
  * @summary Add non-blocking SSL/TLS functionality, usable with any
  *      I/O abstraction
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  *
  * This is intended to test many of the basic API calls to the SSLEngine
  * interface.  This doesn't really exercise much of the SSL code.
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java	Tue Nov 09 22:53:18 2010 -0800
@@ -24,6 +24,8 @@
 /*
  * @test
  * @bug 4495742
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @run main/timeout=180 TestAllSuites
  * @summary Add non-blocking SSL/TLS functionality, usable with any
  *      I/O abstraction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all EmptyCertificateAuthorities
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
+import javax.net.ssl.*;
+
+public class EmptyCertificateAuthorities {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf = getSSLServerSF();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        // require client authentication.
+        sslServerSocket.setNeedClientAuth(true);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    private SSLServerSocketFactory getSSLServerSF() throws Exception {
+
+        char [] password =
+            System.getProperty("javax.net.ssl.keyStorePassword").toCharArray();
+        String keyFilename = System.getProperty("javax.net.ssl.keyStore");
+
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(new FileInputStream(keyFilename), password);
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+        kmf.init(ks, password);
+
+        KeyManager[] kms = kmf.getKeyManagers();
+        TrustManager[] tms = new MyX509TM[] {new MyX509TM()};
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        ctx.init(kms, tms, null);
+
+        return ctx.getServerSocketFactory();
+    }
+
+
+    static class MyX509TM implements X509TrustManager {
+        X509TrustManager tm;
+
+        public void checkClientTrusted(X509Certificate[] chain,
+            String authType) throws CertificateException {
+            if (tm == null) {
+                initialize();
+            }
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+            String authType) throws CertificateException {
+            if (tm == null) {
+                initialize();
+            }
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            // always return empty array
+            return new X509Certificate[0];
+        }
+
+        private void initialize() throws CertificateException {
+            String passwd =
+                System.getProperty("javax.net.ssl.trustStorePassword");
+            char [] password = passwd.toCharArray();
+            String trustFilename =
+                System.getProperty("javax.net.ssl.trustStore");
+
+            try {
+                KeyStore ks = KeyStore.getInstance("JKS");
+                ks.load(new FileInputStream(trustFilename), password);
+
+                TrustManagerFactory tmf =
+                        TrustManagerFactory.getInstance("PKIX");
+                tmf.init(ks);
+                tm = (X509TrustManager)tmf.getTrustManagers()[0];
+            } catch (Exception e) {
+                throw new CertificateException("Unable to initialize TM");
+            }
+
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new EmptyCertificateAuthorities();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    EmptyCertificateAuthorities() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableBlockCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all ExportableBlockCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class ExportableBlockCipher {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslIS.read();
+            sslOS.write('A');
+            sslOS.flush();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a exportable block cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslOS.write('B');
+            sslOS.flush();
+            sslIS.read();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new ExportableBlockCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ExportableBlockCipher() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableStreamCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all ExportableStreamCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class ExportableStreamCipher {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslIS.read();
+            sslOS.write('A');
+            sslOS.flush();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a exportable stream cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_EXPORT_WITH_RC4_40_MD5"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslOS.write('B');
+            sslOS.flush();
+            sslIS.read();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new ExportableStreamCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ExportableStreamCipher() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericBlockCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all GenericBlockCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class GenericBlockCipher {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a block cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new GenericBlockCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    GenericBlockCipher() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericStreamCipher.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all GenericStreamCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class GenericStreamCipher {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a stream cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_WITH_RC4_128_MD5"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new GenericStreamCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    GenericStreamCipher() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- a/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java	Tue Nov 09 22:53:18 2010 -0800
@@ -25,6 +25,8 @@
  * @test
  * @bug 4750141 4895631
  * @summary Check enabled and supported ciphersuites are correct
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  */
 
 import java.util.*;
--- a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java	Tue Nov 09 22:53:18 2010 -0800
@@ -120,6 +120,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -149,18 +156,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -297,7 +300,7 @@
             throws Exception {
         long time = System.currentTimeMillis();
         String relPath;
-        if ((args.length > 0) && args[0].equals("sh")) {
+        if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
             relPath = pathToStoresSH;
         } else {
             relPath = pathToStores;
@@ -336,7 +339,36 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
+            // ignore obsoleted cipher suite for the specified protocol
+            // TODO
+
+            // ignore unsupported cipher suite for the specified protocol
+            // TODO
+
             return true;
         }
     }
--- a/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java	Tue Nov 09 22:53:18 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,8 @@
  * @test
  * @bug 4496785
  * @summary Verify that all ciphersuites work in all configurations
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Andreas Sterbenz
  * @run main/othervm/timeout=300 ClientJSSEServerJSSE
  */
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java	Tue Nov 09 22:53:18 2010 -0800
@@ -713,13 +713,16 @@
             http = (HttpsURLConnection)url.openConnection();
 
             int respCode = http.getResponseCode();
-            System.out.println("respCode = "+respCode);
+            System.out.println("respCode = " + respCode);
 
             throw new Exception("Unexpectly found subject alternative name " +
                                 "matching IP address");
         } catch (SSLHandshakeException sslhe) {
             // no subject alternative names matching IP address 127.0.0.1 found
             // that's the expected exception, ignore it.
+        } catch (IOException ioe) {
+            // HttpsClient may throw IOE during checking URL spoofing,
+            // that's the expected exception, ignore it.
         } finally {
             if (http != null) {
                 http.disconnect();
--- a/jdk/test/sun/util/logging/PlatformLoggerTest.java	Tue Nov 09 11:45:00 2010 -0800
+++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java	Tue Nov 09 22:53:18 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     6882376
+ * @bug     6882376 6985460
  * @summary Test if java.util.logging.Logger is created before and after
  *          logging is enabled.  Also validate some basic PlatformLogger
  *          operations.
@@ -43,6 +43,8 @@
         final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo";
         final String BAR_LOGGER = "test.logger.bar";
         PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
+        // test the PlatformLogger methods
+        testLogMethods(goo);
 
         // Create a platform logger using the default
         PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
@@ -56,6 +58,10 @@
         PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
         checkPlatformLogger(bar, BAR_PLATFORM_LOGGER);
 
+        // test the PlatformLogger methods
+        testLogMethods(goo);
+        testLogMethods(bar);
+
         checkLogger(FOO_PLATFORM_LOGGER, Level.FINER);
         checkLogger(BAR_PLATFORM_LOGGER, Level.FINER);
 
@@ -64,6 +70,7 @@
 
         foo.setLevel(PlatformLogger.SEVERE);
         checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE);
+
     }
 
     private static void checkPlatformLogger(PlatformLogger logger, String name) {
@@ -108,4 +115,33 @@
                 logger.getName() + " " + logger.getLevel());
         }
     }
+
+    private static void testLogMethods(PlatformLogger logger) {
+        logger.severe("Test severe(String, Object...) {0} {1}", new Long(1), "string");
+        // test Object[]
+        logger.severe("Test severe(String, Object...) {0}", (Object[]) getPoints());
+        logger.warning("Test warning(String, Throwable)", new Throwable("Testing"));
+        logger.info("Test info(String)");
+    }
+
+    static Point[] getPoints() {
+        Point[] res = new Point[3];
+        res[0] = new Point(0,0);
+        res[1] = new Point(1,1);
+        res[2] = new Point(2,2);
+        return res;
+    }
+
+    static class Point {
+        final int x;
+        final int y;
+        public Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+        public String toString() {
+            return "{x="+x + ", y=" + y + "}";
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/logging/SourceClassName.java	Tue Nov 09 22:53:18 2010 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     6985460
+ * @summary Test the source class name and method output by the platform
+ *          logger.
+ *
+ * @compile -XDignore.symbol.file SourceClassName.java
+ * @run main/othervm SourceClassName
+ */
+
+import java.util.logging.*;
+import java.io.*;
+import sun.util.logging.PlatformLogger;
+
+public class SourceClassName {
+    public static void main(String[] args) throws Exception {
+        File dir = new File(System.getProperty("user.dir", "."));
+        File log = new File(dir, "testlog.txt");
+        PrintStream logps = new PrintStream(log);
+        writeLogRecords(logps);
+        checkLogRecords(log);
+    }
+
+    private static void writeLogRecords(PrintStream logps) throws Exception {
+        PrintStream err = System.err;
+        try {
+            System.setErr(logps);
+
+            Object[] params = new Object[] { new Long(1), "string"};
+            PlatformLogger plog = PlatformLogger.getLogger("test.log.foo");
+            plog.severe("Log message {0} {1}", (Object[]) params);
+
+            // create a java.util.logging.Logger
+            // now java.util.logging.Logger should be created for each platform logger
+            Logger logger = Logger.getLogger("test.log.bar");
+            logger.log(Level.SEVERE, "Log message {0} {1}", params);
+
+            plog.severe("Log message {0} {1}", (Object[]) params);
+        } finally {
+            logps.flush();
+            logps.close();
+            System.setErr(err);
+        }
+    }
+
+    private static void checkLogRecords(File log) throws Exception {
+        System.out.println("Checking log records in file: " + log);
+        FileInputStream in = new FileInputStream(log);
+        String EXPECTED_LOG = "SEVERE: Log message 1 string";
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            String[] record = new String[2];
+            int count = 0;
+            int i = 0;
+            while ((line = reader.readLine()) != null) {
+                line = line.trim();
+                System.out.println(line);
+                record[i++] = line;
+                if (i == 2) {
+                    i = 0;
+                    count++;
+                    // check source class name and method
+                    String[] ss = record[0].split("\\s+");
+                    int len = ss.length;
+                    if (!ss[len-2].equals("SourceClassName") ||
+                        !ss[len-1].equals("writeLogRecords")) {
+                        throw new RuntimeException("Unexpected source: " +
+                            ss[len-2] + " " + ss[len-1]);
+                    }
+
+                    // check log message
+                    if (!record[1].equals(EXPECTED_LOG)) {
+                        throw new RuntimeException("Unexpected log: " + record[1]);
+                    }
+                }
+            }
+            if (count != 3) {
+                throw new RuntimeException("Unexpected number of records: " + count);
+            }
+        } finally {
+            in.close();
+        }
+    }
+}