changeset 1748:93da8a843f32

Merge
author andrew
date Sat, 03 Oct 2009 01:22:26 +0100
parents c2cd86f82ed7 f708138c9aca
children fe5499a7eeff
files make/java/java/FILES_java.gmk make/sun/net/FILES_java.gmk src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java src/share/native/sun/security/ec/ec.c
diffstat 150 files changed, 24512 insertions(+), 3042 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Sep 29 14:24:18 2009 +0100
+++ b/.hgtags	Sat Oct 03 01:22:26 2009 +0100
@@ -46,3 +46,4 @@
 226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69
 893bcca951b747ddcf6986362b877f0e1dbb835b jdk7-b70
 b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71
+460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
--- a/make/java/java/FILES_java.gmk	Tue Sep 29 14:24:18 2009 +0100
+++ b/make/java/java/FILES_java.gmk	Sat Oct 03 01:22:26 2009 +0100
@@ -454,6 +454,8 @@
     sun/misc/JavaLangAccess.java \
     sun/misc/JavaIOAccess.java \
     sun/misc/JavaIOFileDescriptorAccess.java \
-    sun/misc/JavaNioAccess.java
+    sun/misc/JavaNioAccess.java \
+    sun/misc/Perf.java \
+    sun/misc/PerfCounter.java
 
 FILES_java = $(JAVA_JAVA_java)
--- a/make/java/logging/Makefile	Tue Sep 29 14:24:18 2009 +0100
+++ b/make/java/logging/Makefile	Sat Oct 03 01:22:26 2009 +0100
@@ -31,7 +31,7 @@
 #
 # Files to compile.
 #
-AUTO_FILES_JAVA_DIRS = java/util/logging
+AUTO_FILES_JAVA_DIRS = java/util/logging sun/util/logging
 
 #
 # Resources
@@ -46,7 +46,6 @@
 include $(BUILDDIR)/common/Classes.gmk
 
 properties: $(LIBDIR)/logging.properties
-
 $(LIBDIR)/logging.properties: $(SHARE_SRC)/lib/logging.properties
 	$(install-file)
 
--- a/make/sun/net/FILES_java.gmk	Tue Sep 29 14:24:18 2009 +0100
+++ b/make/sun/net/FILES_java.gmk	Sat Oct 03 01:22:26 2009 +0100
@@ -87,9 +87,11 @@
 	sun/net/www/protocol/http/AuthCache.java \
 	sun/net/www/protocol/http/AuthCacheImpl.java \
 	sun/net/www/protocol/http/AuthCacheValue.java \
+	sun/net/www/protocol/http/AuthScheme.java \
 	sun/net/www/protocol/http/BasicAuthentication.java \
 	sun/net/www/protocol/http/DigestAuthentication.java \
 	sun/net/www/protocol/http/NTLMAuthentication.java \
+	sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
 	sun/net/www/protocol/http/NegotiateAuthentication.java \
 	sun/net/www/protocol/http/NegotiatorImpl.java \
 	sun/net/www/protocol/http/NegotiateCallbackHandler.java \
@@ -124,8 +126,7 @@
 	sun/net/idn/UCharacterEnums.java \
 	sun/net/idn/UCharacterDirection.java \
 	sun/net/idn/StringPrepDataReader.java \
-	sun/net/idn/StringPrep.java \
-	sun/net/www/protocol/http/InMemoryCookieStore.java
+	sun/net/idn/StringPrep.java
 
 ifeq ($(PLATFORM), windows)
     FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java 
--- a/make/sun/security/ec/Makefile	Tue Sep 29 14:24:18 2009 +0100
+++ b/make/sun/security/ec/Makefile	Sat Oct 03 01:22:26 2009 +0100
@@ -24,7 +24,7 @@
 #
 
 #
-# Makefile for building sunec.jar and sunecc native library.
+# Makefile for building sunec.jar and sunec native library.
 #
 # This file was derived from make/com/sun/crypto/provider/Makefile.
 #
@@ -121,7 +121,15 @@
 #
 AUTO_FILES_JAVA_DIRS = $(PKGDIR)
 
-include $(BUILDDIR)/common/Classes.gmk
+#
+# Exclude the sources that get built by ../other/Makefile
+#
+AUTO_JAVA_PRUNE = \
+    ECKeyFactory.java \
+    ECParameters.java \
+    ECPrivateKeyImpl.java \
+    ECPublicKeyImpl.java \
+    NamedCurve.java
 
 #
 # Some licensees do not get the native ECC sources, but we still need to
@@ -130,7 +138,7 @@
 #
 
 NATIVE_ECC_AVAILABLE := $(shell \
-    if [ -d $(SHARE_SRC)/native/$(PKGDIR) ] ; then \
+    if [ -d $(SHARE_SRC)/native/$(PKGDIR)/impl ] ; then \
 	$(ECHO) true; \
     else \
 	$(ECHO) false; \
@@ -138,7 +146,7 @@
 
 ifeq ($(NATIVE_ECC_AVAILABLE), true)
 
-  LIBRARY = sunecc
+  LIBRARY = sunec
 
   #
   # Java files that define native methods
@@ -166,12 +174,12 @@
   #
   vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)
 
-  vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
+  vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/impl
 
   #
   # Find include files
   #
-  OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)
+  OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)/impl
 
   #
   # Compiler flags
@@ -191,6 +199,10 @@
 
   include $(BUILDDIR)/common/Library.gmk
 
+else # NATIVE_ECC_AVAILABLE
+
+  include $(BUILDDIR)/common/Classes.gmk
+
 endif # NATIVE_ECC_AVAILABLE
 
 #
--- a/make/sun/security/other/Makefile	Tue Sep 29 14:24:18 2009 +0100
+++ b/make/sun/security/other/Makefile	Sat Oct 03 01:22:26 2009 +0100
@@ -45,6 +45,16 @@
     com/sun/net/ssl/internal/ssl
 
 #
+# EC classes used by the packages above
+#
+FILES_java += \
+    sun/security/ec/ECKeyFactory.java \
+    sun/security/ec/ECParameters.java \
+    sun/security/ec/ECPrivateKeyImpl.java \
+    sun/security/ec/ECPublicKeyImpl.java \
+    sun/security/ec/NamedCurve.java
+
+#
 # Rules
 #
 include $(BUILDDIR)/common/Classes.gmk
--- a/src/share/bin/java.h	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/bin/java.h	Sat Oct 03 01:22:26 2009 +0100
@@ -187,9 +187,6 @@
  *
  */
 typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
-                                                const char *name,
-                                                jboolean init,
-                                                jobject loader,
-                                                jboolean throwError));
+                                                  const char *name));
 jclass FindBootStrapClass(JNIEnv *env, const char *classname);
 #endif /* _JAVA_H_ */
--- a/src/share/bin/parse_manifest.c	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/bin/parse_manifest.c	Sat Oct 03 01:22:26 2009 +0100
@@ -59,7 +59,7 @@
     char        *out;
     z_stream    zs;
 
-    if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+    if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
         return (NULL);
     if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
         return (NULL);
--- a/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Sat Oct 03 01:22:26 2009 +0100
@@ -133,7 +133,7 @@
      * This method returns an enumerated handle of the keys
      * which correspond to values translated to various locales.
      *
-     * @returns an enumerated keys which have messages tranlated to
+     * @return an enumeration of keys which have messages tranlated to
      * corresponding locales.
      */
     public Enumeration getKeys() {
@@ -146,7 +146,7 @@
      * returns the corresponding value reading it
      * from the Resource Bundle loaded earlier.
      *
-     * @returns value in locale specific language
+     * @return value in locale specific language
      * according to the key passed.
      */
     public Object handleGetObject(String key) {
--- a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Sat Oct 03 01:22:26 2009 +0100
@@ -3737,7 +3737,6 @@
     * Returns a result set containing the original value of the current
     * row only.
     *
-    * @return the original result set of the row
     * @throws SQLException if there is no current row
     * @see #setOriginalRow
     */
--- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Sat Oct 03 01:22:26 2009 +0100
@@ -46,6 +46,17 @@
  */
 public class WebRowSetXmlReader implements XmlReader, Serializable {
 
+
+    private JdbcRowSetResourceBundle resBundle;
+
+    public WebRowSetXmlReader(){
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
     /**
      * Parses the given <code>WebRowSet</code> object, getting its input from
      * the given <code>java.io.Reader</code> object.  The parser will send
@@ -69,17 +80,6 @@
      *            reader for the given rowset
      * @see XmlReaderContentHandler
      */
-
-    private JdbcRowSetResourceBundle resBundle;
-
-    public WebRowSetXmlReader(){
-        try {
-           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
-        } catch(IOException ioe) {
-            throw new RuntimeException(ioe);
-        }
-    }
-
     public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException {
         try {
             // Crimson Parser(as in J2SE 1.4.1 is NOT able to handle
--- a/src/share/classes/java/lang/Class.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/lang/Class.java	Sat Oct 03 01:22:26 2009 +0100
@@ -565,8 +565,9 @@
      *          represented by this object.
      */
     public String getName() {
+        String name = this.name;
         if (name == null)
-            name = getName0();
+            this.name = name = getName0();
         return name;
     }
 
--- a/src/share/classes/java/lang/ClassLoader.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/lang/ClassLoader.java	Sat Oct 03 01:22:26 2009 +0100
@@ -380,16 +380,28 @@
             // First, check if the class has already been loaded
             Class c = findLoadedClass(name);
             if (c == null) {
+                long t0 = System.nanoTime();
                 try {
                     if (parent != null) {
                         c = parent.loadClass(name, false);
                     } else {
-                        c = findBootstrapClass0(name);
+                        c = findBootstrapClassOrNull(name);
                     }
                 } catch (ClassNotFoundException e) {
+                    // ClassNotFoundException thrown if class not found
+                    // from the non-null parent class loader
+                }
+
+                if (c == null) {
                     // If still not found, then invoke findClass in order
                     // to find the class.
+                    long t1 = System.nanoTime();
                     c = findClass(name);
+
+                    // this is the defining class loader; record the stats
+                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+                    sun.misc.PerfCounter.getFindClasses().increment();
                 }
             }
             if (resolve) {
@@ -1008,22 +1020,29 @@
         if (system == null) {
             if (!checkName(name))
                 throw new ClassNotFoundException(name);
-            return findBootstrapClass(name);
+            Class cls = findBootstrapClass(name);
+            if (cls == null) {
+                throw new ClassNotFoundException(name);
+            }
+            return cls;
         }
         return system.loadClass(name);
     }
 
-    private Class findBootstrapClass0(String name)
-        throws ClassNotFoundException
+    /**
+     * Returns a class loaded by the bootstrap class loader;
+     * or return null if not found.
+     */
+    private Class findBootstrapClassOrNull(String name)
     {
         check();
-        if (!checkName(name))
-            throw new ClassNotFoundException(name);
+        if (!checkName(name)) return null;
+
         return findBootstrapClass(name);
     }
 
-    private native Class findBootstrapClass(String name)
-        throws ClassNotFoundException;
+    // return null if not found
+    private native Class findBootstrapClass(String name);
 
     // Check to make sure the class loader has been initialized.
     private void check() {
--- a/src/share/classes/java/net/CookieManager.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/net/CookieManager.java	Sat Oct 03 01:22:26 2009 +0100
@@ -157,7 +157,7 @@
 
         // if not specify CookieStore to use, use default one
         if (store == null) {
-            cookieJar = new sun.net.www.protocol.http.InMemoryCookieStore();
+            cookieJar = new InMemoryCookieStore();
         } else {
             cookieJar = store;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/net/InMemoryCookieStore.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.net;
+
+import java.net.URI;
+import java.net.CookieStore;
+import java.net.HttpCookie;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A simple in-memory java.net.CookieStore implementation
+ *
+ * @author Edward Wang
+ * @since 1.6
+ */
+class InMemoryCookieStore implements CookieStore {
+    // the in-memory representation of cookies
+    private List<HttpCookie> cookieJar = null;
+
+    // the cookies are indexed by its domain and associated uri (if present)
+    // CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
+    //          it won't be cleared in domainIndex & uriIndex. Double-check the
+    //          presence of cookie when retrieve one form index store.
+    private Map<String, List<HttpCookie>> domainIndex = null;
+    private Map<URI, List<HttpCookie>> uriIndex = null;
+
+    // use ReentrantLock instead of syncronized for scalability
+    private ReentrantLock lock = null;
+
+
+    /**
+     * The default ctor
+     */
+    public InMemoryCookieStore() {
+        cookieJar = new ArrayList<HttpCookie>();
+        domainIndex = new HashMap<String, List<HttpCookie>>();
+        uriIndex = new HashMap<URI, List<HttpCookie>>();
+
+        lock = new ReentrantLock(false);
+    }
+
+    /**
+     * Add one cookie into cookie store.
+     */
+    public void add(URI uri, HttpCookie cookie) {
+        // pre-condition : argument can't be null
+        if (cookie == null) {
+            throw new NullPointerException("cookie is null");
+        }
+
+
+        lock.lock();
+        try {
+            // remove the ole cookie if there has had one
+            cookieJar.remove(cookie);
+
+            // add new cookie if it has a non-zero max-age
+            if (cookie.getMaxAge() != 0) {
+                cookieJar.add(cookie);
+                // and add it to domain index
+                if (cookie.getDomain() != null) {
+                    addIndex(domainIndex, cookie.getDomain(), cookie);
+                }
+                // add it to uri index, too
+                addIndex(uriIndex, getEffectiveURI(uri), cookie);
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    /**
+     * Get all cookies, which:
+     *  1) given uri domain-matches with, or, associated with
+     *     given uri when added to the cookie store.
+     *  3) not expired.
+     * See RFC 2965 sec. 3.3.4 for more detail.
+     */
+    public List<HttpCookie> get(URI uri) {
+        // argument can't be null
+        if (uri == null) {
+            throw new NullPointerException("uri is null");
+        }
+
+        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
+        boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
+        lock.lock();
+        try {
+            // check domainIndex first
+            getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
+            // check uriIndex then
+            getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
+        } finally {
+            lock.unlock();
+        }
+
+        return cookies;
+    }
+
+    /**
+     * Get all cookies in cookie store, except those have expired
+     */
+    public List<HttpCookie> getCookies() {
+        List<HttpCookie> rt;
+
+        lock.lock();
+        try {
+            Iterator<HttpCookie> it = cookieJar.iterator();
+            while (it.hasNext()) {
+                if (it.next().hasExpired()) {
+                    it.remove();
+                }
+            }
+        } finally {
+            rt = Collections.unmodifiableList(cookieJar);
+            lock.unlock();
+        }
+
+        return rt;
+    }
+
+    /**
+     * Get all URIs, which are associated with at least one cookie
+     * of this cookie store.
+     */
+    public List<URI> getURIs() {
+        List<URI> uris = new ArrayList<URI>();
+
+        lock.lock();
+        try {
+            Iterator<URI> it = uriIndex.keySet().iterator();
+            while (it.hasNext()) {
+                URI uri = it.next();
+                List<HttpCookie> cookies = uriIndex.get(uri);
+                if (cookies == null || cookies.size() == 0) {
+                    // no cookies list or an empty list associated with
+                    // this uri entry, delete it
+                    it.remove();
+                }
+            }
+        } finally {
+            uris.addAll(uriIndex.keySet());
+            lock.unlock();
+        }
+
+        return uris;
+    }
+
+
+    /**
+     * Remove a cookie from store
+     */
+    public boolean remove(URI uri, HttpCookie ck) {
+        // argument can't be null
+        if (ck == null) {
+            throw new NullPointerException("cookie is null");
+        }
+
+        boolean modified = false;
+        lock.lock();
+        try {
+            modified = cookieJar.remove(ck);
+        } finally {
+            lock.unlock();
+        }
+
+        return modified;
+    }
+
+
+    /**
+     * Remove all cookies in this cookie store.
+     */
+    public boolean removeAll() {
+        lock.lock();
+        try {
+            cookieJar.clear();
+            domainIndex.clear();
+            uriIndex.clear();
+        } finally {
+            lock.unlock();
+        }
+
+        return true;
+    }
+
+
+    /* ---------------- Private operations -------------- */
+
+
+    /*
+     * This is almost the same as HttpCookie.domainMatches except for
+     * one difference: It won't reject cookies when the 'H' part of the
+     * domain contains a dot ('.').
+     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
+     * and the cookie domain is .domain.com, then it should be rejected.
+     * However that's not how the real world works. Browsers don't reject and
+     * some sites, like yahoo.com do actually expect these cookies to be
+     * passed along.
+     * And should be used for 'old' style cookies (aka Netscape type of cookies)
+     */
+    private boolean netscapeDomainMatches(String domain, String host)
+    {
+        if (domain == null || host == null) {
+            return false;
+        }
+
+        // if there's no embedded dot in domain and domain is not .local
+        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
+        int embeddedDotInDomain = domain.indexOf('.');
+        if (embeddedDotInDomain == 0) {
+            embeddedDotInDomain = domain.indexOf('.', 1);
+        }
+        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
+            return false;
+        }
+
+        // if the host name contains no dot and the domain name is .local
+        int firstDotInHost = host.indexOf('.');
+        if (firstDotInHost == -1 && isLocalDomain) {
+            return true;
+        }
+
+        int domainLength = domain.length();
+        int lengthDiff = host.length() - domainLength;
+        if (lengthDiff == 0) {
+            // if the host name and the domain name are just string-compare euqal
+            return host.equalsIgnoreCase(domain);
+        } else if (lengthDiff > 0) {
+            // need to check H & D component
+            String H = host.substring(0, lengthDiff);
+            String D = host.substring(lengthDiff);
+
+            return (D.equalsIgnoreCase(domain));
+        } else if (lengthDiff == -1) {
+            // if domain is actually .host
+            return (domain.charAt(0) == '.' &&
+                    host.equalsIgnoreCase(domain.substring(1)));
+        }
+
+        return false;
+    }
+
+    private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
+            String host, boolean secureLink) {
+        // Use a separate list to handle cookies that need to be removed so
+        // that there is no conflict with iterators.
+        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
+        for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
+            String domain = entry.getKey();
+            List<HttpCookie> lst = entry.getValue();
+            for (HttpCookie c : lst) {
+                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
+                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
+                    if ((cookieJar.indexOf(c) != -1)) {
+                        // the cookie still in main cookie store
+                        if (!c.hasExpired()) {
+                            // don't add twice and make sure it's the proper
+                            // security level
+                            if ((secureLink || !c.getSecure()) &&
+                                    !cookies.contains(c)) {
+                                cookies.add(c);
+                            }
+                        } else {
+                            toRemove.add(c);
+                        }
+                    } else {
+                        // the cookie has beed removed from main store,
+                        // so also remove it from domain indexed store
+                        toRemove.add(c);
+                    }
+                }
+            }
+            // Clear up the cookies that need to be removed
+            for (HttpCookie c : toRemove) {
+                lst.remove(c);
+                cookieJar.remove(c);
+
+            }
+            toRemove.clear();
+        }
+    }
+
+    // @param cookies           [OUT] contains the found cookies
+    // @param cookieIndex       the index
+    // @param comparator        the prediction to decide whether or not
+    //                          a cookie in index should be returned
+    private <T> void getInternal2(List<HttpCookie> cookies,
+                                Map<T, List<HttpCookie>> cookieIndex,
+                                Comparable<T> comparator, boolean secureLink)
+    {
+        for (T index : cookieIndex.keySet()) {
+            if (comparator.compareTo(index) == 0) {
+                List<HttpCookie> indexedCookies = cookieIndex.get(index);
+                // check the list of cookies associated with this domain
+                if (indexedCookies != null) {
+                    Iterator<HttpCookie> it = indexedCookies.iterator();
+                    while (it.hasNext()) {
+                        HttpCookie ck = it.next();
+                        if (cookieJar.indexOf(ck) != -1) {
+                            // the cookie still in main cookie store
+                            if (!ck.hasExpired()) {
+                                // don't add twice
+                                if ((secureLink || !ck.getSecure()) &&
+                                        !cookies.contains(ck))
+                                    cookies.add(ck);
+                            } else {
+                                it.remove();
+                                cookieJar.remove(ck);
+                            }
+                        } else {
+                            // the cookie has beed removed from main store,
+                            // so also remove it from domain indexed store
+                            it.remove();
+                        }
+                    }
+                } // end of indexedCookies != null
+            } // end of comparator.compareTo(index) == 0
+        } // end of cookieIndex iteration
+    }
+
+    // add 'cookie' indexed by 'index' into 'indexStore'
+    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
+                              T index,
+                              HttpCookie cookie)
+    {
+        if (index != null) {
+            List<HttpCookie> cookies = indexStore.get(index);
+            if (cookies != null) {
+                // there may already have the same cookie, so remove it first
+                cookies.remove(cookie);
+
+                cookies.add(cookie);
+            } else {
+                cookies = new ArrayList<HttpCookie>();
+                cookies.add(cookie);
+                indexStore.put(index, cookies);
+            }
+        }
+    }
+
+
+    //
+    // for cookie purpose, the effective uri should only be http://host
+    // the path will be taken into account when path-match algorithm applied
+    //
+    private URI getEffectiveURI(URI uri) {
+        URI effectiveURI = null;
+        try {
+            effectiveURI = new URI("http",
+                                   uri.getHost(),
+                                   null,  // path component
+                                   null,  // query component
+                                   null   // fragment component
+                                  );
+        } catch (URISyntaxException ignored) {
+            effectiveURI = uri;
+        }
+
+        return effectiveURI;
+    }
+}
--- a/src/share/classes/java/net/URLClassLoader.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/net/URLClassLoader.java	Sat Oct 03 01:22:26 2009 +0100
@@ -340,6 +340,7 @@
      * used.
      */
     private Class defineClass(String name, Resource res) throws IOException {
+        long t0 = System.nanoTime();
         int i = name.lastIndexOf('.');
         URL url = res.getCodeSourceURL();
         if (i != -1) {
@@ -370,12 +371,14 @@
             // Use (direct) ByteBuffer:
             CodeSigner[] signers = res.getCodeSigners();
             CodeSource cs = new CodeSource(url, signers);
+            sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
             return defineClass(name, bb, cs);
         } else {
             byte[] b = res.getBytes();
             // must read certificates AFTER reading bytes.
             CodeSigner[] signers = res.getCodeSigners();
             CodeSource cs = new CodeSource(url, signers);
+            sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
             return defineClass(name, b, 0, b.length, cs);
         }
     }
--- a/src/share/classes/java/net/doc-files/net-properties.html	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/net/doc-files/net-properties.html	Sat Oct 03 01:22:26 2009 +0100
@@ -71,12 +71,12 @@
 	<LI><P>HTTP</P>
 	<P>The following proxy settings are used by the HTTP protocol handler.</P>
 	<UL>
-		<LI><P><B>http.proxyHost</FONT></B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>http.proxyHost</B> (default: &lt;none&gt;)<BR>
 	        The hostname, or address, of the proxy server 
 		</P>
 		<LI><P><B>http.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
-		<LI><P><B>http.nonProxyHosts</B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>http.nonProxyHosts</B> (default:  localhost|127.*|[::1])<BR>
 	        Indicates the hosts that should be accessed without going
 	        through the proxy. Typically this defines internal hosts.
 	        The value of this property is a list of hosts,
@@ -86,7 +86,8 @@
 		will indicate that every hosts in the foo.com domain and the
 		localhost should be accessed directly even if a proxy server is
 		specified.</P>
-	</UL>
+                <P>The default value excludes all common variations of the loopback address.</P>
+        </UL>
 	<LI><P>HTTPS<BR>This is HTTP over SSL, a secure version of HTTP
 	mainly used when confidentiality (like on payment sites) is needed.</P>
 	<P>The following proxy settings are used by the HTTPS protocol handler.</P>
@@ -107,7 +108,7 @@
 		</P>
 		<LI><P><B>ftp.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
-		<LI><P><B>ftp.nonProxyHosts</B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>ftp.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
 	        Indicates the hosts that should be accessed without going
 	        through the proxy. Typically this defines internal hosts.
 	        The value of this property is a list of hosts, separated by
@@ -117,6 +118,7 @@
 		will indicate that every hosts in the foo.com domain and the
 		localhost should be accessed directly even if a proxy server is
 		specified.</P>
+                <P>The default value excludes all common variations of the loopback address.</P>
 	</UL>
 	<LI><P>SOCKS<BR>This is another type of proxy. It allows for lower
 	level type of tunneling since it works at the TCP level. In effect,
--- a/src/share/classes/java/nio/file/FileTreeWalker.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/nio/file/FileTreeWalker.java	Sat Oct 03 01:22:26 2009 +0100
@@ -41,8 +41,12 @@
     private final boolean detectCycles;
     private final LinkOption[] linkOptions;
     private final FileVisitor<? super Path> visitor;
+    private final int maxDepth;
 
-    FileTreeWalker(Set<FileVisitOption> options, FileVisitor<? super Path> visitor) {
+    FileTreeWalker(Set<FileVisitOption> options,
+                   FileVisitor<? super Path> visitor,
+                   int maxDepth)
+    {
         boolean fl = false;
         boolean dc = false;
         for (FileVisitOption option: options) {
@@ -58,18 +62,15 @@
         this.linkOptions = (fl) ? new LinkOption[0] :
             new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
         this.visitor = visitor;
+        this.maxDepth = maxDepth;
     }
 
     /**
      * Walk file tree starting at the given file
      */
-    void walk(Path start, int maxDepth) {
-        // don't use attributes of starting file as they may be stale
-        if (start instanceof BasicFileAttributesHolder) {
-            ((BasicFileAttributesHolder)start).invalidate();
-        }
+    void walk(Path start) {
         FileVisitResult result = walk(start,
-                                      maxDepth,
+                                      0,
                                       new ArrayList<AncestorDirectory>());
         if (result == null) {
             throw new NullPointerException("Visitor returned 'null'");
@@ -89,12 +90,15 @@
                                  List<AncestorDirectory> ancestors)
     {
         // depth check
-        if (depth-- < 0)
+        if (depth > maxDepth)
             return FileVisitResult.CONTINUE;
 
         // if attributes are cached then use them if possible
         BasicFileAttributes attrs = null;
-        if (file instanceof BasicFileAttributesHolder) {
+        if ((depth > 0) &&
+            (file instanceof BasicFileAttributesHolder) &&
+            (System.getSecurityManager() == null))
+        {
             BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
             if (!followLinks || !cached.isSymbolicLink())
                 attrs = cached;
@@ -120,6 +124,10 @@
                     }
                 }
             } catch (SecurityException x) {
+                // If access to starting file is denied then SecurityException
+                // is thrown, otherwise the file is ignored.
+                if (depth == 0)
+                    throw x;
                 return FileVisitResult.CONTINUE;
             }
         }
@@ -196,7 +204,7 @@
                 try {
                     for (Path entry: stream) {
                         inAction = true;
-                        result = walk(entry, depth, ancestors);
+                        result = walk(entry, depth+1, ancestors);
                         inAction = false;
 
                         // returning null will cause NPE to be thrown
--- a/src/share/classes/java/nio/file/Files.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/nio/file/Files.java	Sat Oct 03 01:22:26 2009 +0100
@@ -223,7 +223,7 @@
     {
         if (maxDepth < 0)
             throw new IllegalArgumentException("'maxDepth' is negative");
-        new FileTreeWalker(options, visitor).walk(start, maxDepth);
+        new FileTreeWalker(options, visitor, maxDepth).walk(start);
     }
 
     /**
--- a/src/share/classes/java/util/Currency.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/Currency.java	Sat Oct 03 01:22:26 2009 +0100
@@ -35,12 +35,12 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import sun.util.LocaleServiceProviderPool;
+import sun.util.logging.PlatformLogger;
 import sun.util.resources.LocaleData;
 import sun.util.resources.OpenListResourceBundle;
 
@@ -244,7 +244,7 @@
                         }
                     }
                 } catch (IOException e) {
-                    log(Level.INFO, "currency.properties is ignored because of an IOException", e);
+                    info("currency.properties is ignored because of an IOException", e);
                 }
                 return null;
             }
@@ -686,7 +686,7 @@
                 .append("The entry in currency.properties for ")
                 .append(ctry).append(" is ignored because of the invalid country code.")
                 .toString();
-            log(Level.INFO, message, null);
+            info(message, null);
             return;
         }
 
@@ -698,7 +698,7 @@
                 .append(ctry)
                 .append(" is ignored because the value format is not recognized.")
                 .toString();
-            log(Level.INFO, message, null);
+            info(message, null);
             return;
         }
 
@@ -726,13 +726,13 @@
         setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
     }
 
-    private static void log(Level level, String message, Throwable t) {
-        Logger logger = Logger.getLogger("java.util.Currency");
-        if (logger.isLoggable(level)) {
+    private static void info(String message, Throwable t) {
+        PlatformLogger logger = PlatformLogger.getLogger("java.util.Currency");
+        if (logger.isLoggable(PlatformLogger.INFO)) {
             if (t != null) {
-                logger.log(level, message, t);
+                logger.info(message, t);
             } else {
-                logger.log(level, message);
+                logger.info(message);
             }
         }
     }
--- a/src/share/classes/java/util/jar/Attributes.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/jar/Attributes.java	Sat Oct 03 01:22:26 2009 +0100
@@ -34,7 +34,7 @@
 import java.util.Collection;
 import java.util.AbstractSet;
 import java.util.Iterator;
-import java.util.logging.Logger;
+import sun.util.logging.PlatformLogger;
 import java.util.Comparator;
 import sun.misc.ASCIICaseInsensitiveComparator;
 
@@ -419,7 +419,7 @@
             }
             try {
                 if ((putValue(name, value) != null) && (!lineContinued)) {
-                    Logger.getLogger("java.util.jar").warning(
+                    PlatformLogger.getLogger("java.util.jar").warning(
                                      "Duplicate name in Manifest: " + name
                                      + ".\n"
                                      + "Ensure that the manifest does not "
--- a/src/share/classes/java/util/logging/ErrorManager.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/ErrorManager.java	Sat Oct 03 01:22:26 2009 +0100
@@ -28,7 +28,7 @@
 
 /**
  * ErrorManager objects can be attached to Handlers to process
- * any error that occur on a Handler during Logging.
+ * any error that occurs on a Handler during Logging.
  * <p>
  * When processing logging output, if a Handler encounters problems
  * then rather than throwing an Exception back to the issuer of
@@ -72,7 +72,7 @@
     /**
      * The error method is called when a Handler failure occurs.
      * <p>
-     * This method may be overriden in subclasses.  The default
+     * This method may be overridden in subclasses.  The default
      * behavior in this base class is that the first call is
      * reported to System.err, and subsequent calls are ignored.
      *
--- a/src/share/classes/java/util/logging/FileHandler.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/FileHandler.java	Sat Oct 03 01:22:26 2009 +0100
@@ -39,7 +39,7 @@
  * For a rotating set of files, as each file reaches a given size
  * limit, it is closed, rotated out, and a new file opened.
  * Successively older files are named by adding "0", "1", "2",
- * etc into the base filename.
+ * etc. into the base filename.
  * <p>
  * By default buffering is enabled in the IO libraries but each log
  * record is flushed out when it is complete.
@@ -391,7 +391,7 @@
             // Generate a lock file name from the "unique" int.
             lockFileName = generate(pattern, 0, unique).toString() + ".lck";
             // Now try to lock that filename.
-            // Because some systems (e.g. Solaris) can only do file locks
+            // Because some systems (e.g., Solaris) can only do file locks
             // between processes (and not within a process), we first check
             // if we ourself already have the file locked.
             synchronized(locks) {
--- a/src/share/classes/java/util/logging/Formatter.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/Formatter.java	Sat Oct 03 01:22:26 2009 +0100
@@ -52,7 +52,7 @@
      * Format the given log record and return the formatted string.
      * <p>
      * The resulting formatted String will normally include a
-     * localized and formated version of the LogRecord's message field.
+     * localized and formatted version of the LogRecord's message field.
      * It is recommended to use the {@link Formatter#formatMessage}
      * convenience method to localize and format the message field.
      *
@@ -66,7 +66,7 @@
      * Return the header string for a set of formatted records.
      * <p>
      * This base class returns an empty string, but this may be
-     * overriden by subclasses.
+     * overridden by subclasses.
      *
      * @param   h  The target handler (can be null)
      * @return  header string
@@ -79,7 +79,7 @@
      * Return the tail string for a set of formatted records.
      * <p>
      * This base class returns an empty string, but this may be
-     * overriden by subclasses.
+     * overridden by subclasses.
      *
      * @param   h  The target handler (can be null)
      * @return  tail string
--- a/src/share/classes/java/util/logging/Handler.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/Handler.java	Sat Oct 03 01:22:26 2009 +0100
@@ -274,7 +274,7 @@
      * <tt>Level</tt> and  whether it satisfies any <tt>Filter</tt>.  It also
      * may make other <tt>Handler</tt> specific checks that might prevent a
      * handler from logging the <tt>LogRecord</tt>. It will return false if
-     * the <tt>LogRecord</tt> is Null.
+     * the <tt>LogRecord</tt> is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/src/share/classes/java/util/logging/Level.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/Level.java	Sat Oct 03 01:22:26 2009 +0100
@@ -110,7 +110,7 @@
      * Typically INFO messages will be written to the console
      * or its equivalent.  So the INFO level should only be
      * used for reasonably significant messages that will
-     * make sense to end users and system admins.
+     * make sense to end users and system administrators.
      * This level is initialized to <CODE>800</CODE>.
      */
     public static final Level INFO = new Level("INFO", 800, defaultBundle);
@@ -245,6 +245,8 @@
     }
 
     /**
+     * Returns a string representation of this Level.
+     *
      * @return the non-localized name of the Level, for example "INFO".
      */
     public final String toString() {
@@ -299,14 +301,14 @@
      * @throws IllegalArgumentException if the value is not valid.
      * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
      * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
-     * Known names are the levels defined by this class (i.e. <CODE>FINE</CODE>,
+     * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
      * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
      * appropriate package access, or new levels defined or created
      * by subclasses.
      *
      * @return The parsed value. Passing an integer that corresponds to a known name
-     * (eg 700) will return the associated name (eg <CODE>CONFIG</CODE>).
-     * Passing an integer that does not (eg 1) will return a new level name
+     * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
+     * Passing an integer that does not (e.g., 1) will return a new level name
      * initialized to that value.
      */
     public static synchronized Level parse(String name) throws IllegalArgumentException {
--- a/src/share/classes/java/util/logging/LogManager.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/LogManager.java	Sat Oct 03 01:22:26 2009 +0100
@@ -283,6 +283,10 @@
                         AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                                 public Object run() throws Exception {
                                     readConfiguration();
+
+                                    // Platform loggers begin to delegate to java.util.logging.Logger
+                                    sun.util.logging.PlatformLogger.redirectPlatformLoggers();
+
                                     return null;
                                 }
                             });
--- a/src/share/classes/java/util/logging/LogRecord.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/LogRecord.java	Sat Oct 03 01:22:26 2009 +0100
@@ -188,7 +188,7 @@
    }
 
     /**
-     * Get the source Logger name's
+     * Get the source Logger's name.
      *
      * @return source logger name (may be null)
      */
@@ -197,7 +197,7 @@
     }
 
     /**
-     * Set the source Logger name.
+     * Set the source Logger's name.
      *
      * @param name   the source logger name (may be null)
      */
@@ -530,6 +530,7 @@
         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
@@ -539,15 +540,18 @@
             String cname = frame.getClassName();
             if (lookingForLogger) {
                 // Skip all frames until we have found the first logger frame.
-                if (cname.equals(logClassName)) {
+                if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
                     lookingForLogger = false;
                 }
             } else {
-                if (!cname.equals(logClassName)) {
-                    // We've found the relevant frame.
-                    setSourceClassName(cname);
-                    setSourceMethodName(frame.getMethodName());
-                    return;
+                if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
+                    // skip reflection call
+                    if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
+                       // We've found the relevant frame.
+                       setSourceClassName(cname);
+                       setSourceMethodName(frame.getMethodName());
+                       return;
+                    }
                 }
             }
         }
--- a/src/share/classes/java/util/logging/Logger.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/Logger.java	Sat Oct 03 01:22:26 2009 +0100
@@ -66,7 +66,7 @@
  * effective level from its parent.
  * <p>
  * On each logging call the Logger initially performs a cheap
- * check of the request level (e.g. SEVERE or FINE) against the
+ * check of the request level (e.g., SEVERE or FINE) against the
  * effective log level of the logger.  If the request level is
  * lower than the log level, the logging call returns immediately.
  * <p>
@@ -230,7 +230,7 @@
      * Protected method to construct a logger for a named subsystem.
      * <p>
      * The logger will be initially configured with a null Level
-     * and with useParentHandlers true.
+     * and with useParentHandlers set to true.
      *
      * @param   name    A name for the logger.  This should
      *                          be a dot-separated name and should normally
@@ -240,7 +240,7 @@
      * @param   resourceBundleName  name of ResourceBundle to be used for localizing
      *                          messages for this logger.  May be null if none
      *                          of the messages require localization.
-     * @throws MissingResourceException if the ResourceBundleName is non-null and
+     * @throws MissingResourceException if the resourceBundleName is non-null and
      *             no corresponding resource can be found.
      */
     protected Logger(String name, String resourceBundleName) {
@@ -285,7 +285,7 @@
      * <p>
      * If a new logger is created its log level will be configured
      * based on the LogManager configuration and it will configured
-     * to also send logging output to its parent's handlers.  It will
+     * to also send logging output to its parent's Handlers.  It will
      * be registered in the LogManager global namespace.
      *
      * @param   name            A name for the logger.  This should
@@ -308,7 +308,7 @@
      * <p>
      * If a new logger is created its log level will be configured
      * based on the LogManager and it will configured to also send logging
-     * output to its parent loggers Handlers.  It will be registered in
+     * output to its parent's Handlers.  It will be registered in
      * the LogManager global namespace.
      * <p>
      * If the named Logger already exists and does not yet have a
@@ -326,7 +326,8 @@
      *                          messages for this logger. May be <CODE>null</CODE> if none of
      *                          the messages require localization.
      * @return a suitable Logger
-     * @throws MissingResourceException if the named ResourceBundle cannot be found.
+     * @throws MissingResourceException if the resourceBundleName is non-null and
+     *             no corresponding resource can be found.
      * @throws IllegalArgumentException if the Logger already exists and uses
      *             a different resource bundle name.
      * @throws NullPointerException if the name is null.
@@ -395,7 +396,8 @@
      *                          messages for this logger.
      *          May be null if none of the messages require localization.
      * @return a newly created private Logger
-     * @throws MissingResourceException if the named ResourceBundle cannot be found.
+     * @throws MissingResourceException if the resourceBundleName is non-null and
+     *             no corresponding resource can be found.
      */
     public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
         LogManager manager = LogManager.getLogManager();
@@ -514,7 +516,7 @@
      * level then the given message is forwarded to all the
      * registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      */
     public void log(Level level, String msg) {
@@ -532,7 +534,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   param1  parameter to the message
      */
@@ -553,7 +555,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   params  array of parameters to the message
      */
@@ -578,7 +580,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   thrown  Throwable associated with log message.
      */
@@ -603,7 +605,7 @@
      * level then the given message is forwarded to all the
      * registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -626,7 +628,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg      The string message (or a key in the message catalog)
@@ -653,7 +655,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -684,7 +686,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -731,7 +733,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -762,7 +764,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -795,7 +797,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -832,7 +834,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -1214,7 +1216,7 @@
 
     /**
      * Specify whether or not this logger should send its output
-     * to it's parent Logger.  This means that any LogRecords will
+     * to its parent Logger.  This means that any LogRecords will
      * also be written to the parent's Handlers, and potentially
      * to its parent, recursively up the namespace.
      *
--- a/src/share/classes/java/util/logging/LoggingMXBean.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/LoggingMXBean.java	Sat Oct 03 01:22:26 2009 +0100
@@ -105,8 +105,8 @@
      *
      * @param loggerName The name of the <tt>Logger</tt> to be set.
      *                   Must be non-null.
-     * @param levelName The name of the level to set the specified logger to,
-     *                 or <tt>null</tt> if to set the level to inherit
+     * @param levelName The name of the level to set on the specified logger,
+     *                 or <tt>null</tt> if setting the level to inherit
      *                 from its nearest ancestor.
      *
      * @throws IllegalArgumentException if the specified logger
--- a/src/share/classes/java/util/logging/MemoryHandler.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/MemoryHandler.java	Sat Oct 03 01:22:26 2009 +0100
@@ -136,7 +136,7 @@
      * @param size    the number of log records to buffer (must be greater than zero)
      * @param pushLevel  message level to push on
      *
-     * @throws IllegalArgumentException is size is <= 0
+     * @throws IllegalArgumentException if size is <= 0
      */
     public MemoryHandler(Handler target, int size, Level pushLevel) {
         if (target == null || pushLevel == null) {
@@ -258,7 +258,7 @@
      * This method checks if the <tt>LogRecord</tt> has an appropriate level and
      * whether it satisfies any <tt>Filter</tt>.  However it does <b>not</b>
      * check whether the <tt>LogRecord</tt> would result in a "push" of the
-     * buffer contents. It will return false if the <tt>LogRecord</tt> is Null.
+     * buffer contents. It will return false if the <tt>LogRecord</tt> is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/src/share/classes/java/util/logging/StreamHandler.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/logging/StreamHandler.java	Sat Oct 03 01:22:26 2009 +0100
@@ -220,7 +220,7 @@
      * <p>
      * This method checks if the <tt>LogRecord</tt> has an appropriate level and
      * whether it satisfies any <tt>Filter</tt>.  It will also return false if
-     * no output stream has been assigned yet or the LogRecord is Null.
+     * no output stream has been assigned yet or the LogRecord is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/src/share/classes/java/util/zip/ZipEntry.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/zip/ZipEntry.java	Sat Oct 03 01:22:26 2009 +0100
@@ -253,14 +253,10 @@
      * the first 0xFFFF bytes are output to the ZIP file entry.
      *
      * @param comment the comment string
-     * @exception IllegalArgumentException if the length of the specified
-     *            comment string is greater than 0xFFFF bytes
+     *
      * @see #getComment()
      */
     public void setComment(String comment) {
-        if (comment != null && comment.length() > 0xffff) {
-            throw new IllegalArgumentException("invalid entry comment length");
-        }
         this.comment = comment;
     }
 
--- a/src/share/classes/java/util/zip/ZipFile.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/java/util/zip/ZipFile.java	Sat Oct 03 01:22:26 2009 +0100
@@ -195,7 +195,10 @@
         if (charset == null)
             throw new NullPointerException("charset is null");
         this.zc = ZipCoder.get(charset);
+        long t0 = System.nanoTime();
         jzfile = open(name, mode, file.lastModified());
+        sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
+        sun.misc.PerfCounter.getZipFileCount().increment();
         this.name = name;
         this.total = getTotal(jzfile);
     }
--- a/src/share/classes/javax/sql/rowset/BaseRowSet.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/javax/sql/rowset/BaseRowSet.java	Sat Oct 03 01:22:26 2009 +0100
@@ -168,8 +168,8 @@
  * The majority of methods for setting placeholder parameters take two parameters,
  *  with the first parameter
  * indicating which placeholder parameter is to be set, and the second parameter
- * giving the value to be set.  Methods such as <code>getInt</code>,
- * <code>getString</code>, <code>getBoolean</code>, and <code>getLong</code> fall into
+ * giving the value to be set.  Methods such as <code>setInt</code>,
+ * <code>setString</code>, <code>setBoolean</code>, and <code>setLong</code> fall into
  * this category.  After these methods have been called, a call to the method
  * <code>getParams</code> will return an array with the values that have been set. Each
  * element in the array is an <code>Object</code> instance representing the
@@ -3259,9 +3259,9 @@
     * @param x the parameter value
     * @exception SQLException if a database access error occurs or
     * this method is called on a closed <code>CallableStatement</code>
-    * @see #getBoolean
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
+    * @see #getParams
     * @since 1.4
     */
    public void setBoolean(String parameterName, boolean x) throws SQLException{
@@ -3281,7 +3281,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getByte
+    * @see #getParams
     * @since 1.4
     */
    public void setByte(String parameterName, byte x) throws SQLException{
@@ -3301,7 +3301,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getShort
+    * @see #getParams
     * @since 1.4
     */
    public void setShort(String parameterName, short x) throws SQLException{
@@ -3320,7 +3320,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getInt
+    * @see #getParams
     * @since 1.4
     */
    public void setInt(String parameterName, int x) throws SQLException{
@@ -3339,7 +3339,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getLong
+    * @see #getParams
     * @since 1.4
     */
    public void setLong(String parameterName, long x) throws SQLException{
@@ -3358,7 +3358,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getFloat
+    * @see #getParams
     * @since 1.4
     */
    public void setFloat(String parameterName, float x) throws SQLException{
@@ -3377,7 +3377,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDouble
+    * @see #getParams
     * @since 1.4
     */
    public void setDouble(String parameterName, double x) throws SQLException{
@@ -3398,7 +3398,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getBigDecimal
+    * @see #getParams
     * @since 1.4
     */
    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
@@ -3421,7 +3421,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getString
+    * @see #getParams
     * @since 1.4
     */
    public void setString(String parameterName, String x) throws SQLException{
@@ -3443,7 +3443,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getBytes
+    * @see #getParams
     * @since 1.4
     */
    public void setBytes(String parameterName, byte x[]) throws SQLException{
@@ -3464,7 +3464,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTimestamp
+    * @see #getParams
     * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x)
@@ -3712,7 +3712,7 @@
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
     * @see Types
-    * @see #getObject
+    * @see #getParams
     * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType, int scale)
@@ -3740,7 +3740,7 @@
     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
-    * @see #getObject
+    * @see #getParams
     * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType)
@@ -3782,7 +3782,7 @@
    *            <code>Object</code> parameter is ambiguous
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
-   * @see #getObject
+   * @see #getParams
    * @since 1.4
    */
   public void setObject(String parameterName, Object x) throws SQLException{
@@ -4064,7 +4064,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDate
+    * @see #getParams
     * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x)
@@ -4091,7 +4091,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDate
+    * @see #getParams
     * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
@@ -4111,7 +4111,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTime
+    * @see #getParams
     * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x)
@@ -4138,7 +4138,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTime
+    * @see #getParams
     * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
@@ -4165,7 +4165,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTimestamp
+    * @see #getParams
     * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/PerfCounter.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.LongBuffer;
+import java.security.AccessController;
+
+/**
+ * Performance counter support for internal JRE classes.
+ * This class defines a fixed list of counters for the platform
+ * to use as an interim solution until RFE# 6209222 is implemented.
+ * The perf counters will be created in the jvmstat perf buffer
+ * that the HotSpot VM creates. The default size is 32K and thus
+ * the number of counters is bounded.  You can alter the size
+ * with -XX:PerfDataMemorySize=<bytes> option. If there is
+ * insufficient memory in the jvmstat perf buffer, the C heap memory
+ * will be used and thus the application will continue to run if
+ * the counters added exceeds the buffer size but the counters
+ * will be missing.
+ *
+ * See HotSpot jvmstat implementation for certain circumstances
+ * that the jvmstat perf buffer is not supported.
+ *
+ */
+public class PerfCounter {
+    private static final Perf perf =
+        AccessController.doPrivileged(new Perf.GetPerfAction());
+
+    // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp
+    private final static int V_Constant  = 1;
+    private final static int V_Monotonic = 2;
+    private final static int V_Variable  = 3;
+    private final static int U_None      = 1;
+
+    private final String name;
+    private final LongBuffer lb;
+
+    private PerfCounter(String name, int type) {
+        this.name = name;
+        ByteBuffer bb = perf.createLong(name, U_None, type, 0L);
+        bb.order(ByteOrder.nativeOrder());
+        this.lb = bb.asLongBuffer();
+    }
+
+    static PerfCounter newPerfCounter(String name) {
+        return new PerfCounter(name, V_Variable);
+    }
+
+    static PerfCounter newConstantPerfCounter(String name) {
+        PerfCounter c = new PerfCounter(name, V_Constant);
+        return c;
+    }
+
+    /**
+     * Returns the current value of the perf counter.
+     */
+    public synchronized long get() {
+        return lb.get(0);
+    }
+
+    /**
+     * Sets the value of the perf counter to the given newValue.
+     */
+    public synchronized void set(long newValue) {
+        lb.put(0, newValue);
+    }
+
+    /**
+     * Adds the given value to the perf counter.
+     */
+    public synchronized void add(long value) {
+        long res = get() + value;
+        lb.put(0, res);
+    }
+
+    /**
+     * Increments the perf counter with 1.
+     */
+    public void increment() {
+        add(1);
+    }
+
+    /**
+     * Adds the given interval to the perf counter.
+     */
+    public void addTime(long interval) {
+        add(interval);
+    }
+
+    /**
+     * Adds the elapsed time from the given start time (ns) to the perf counter.
+     */
+    public void addElapsedTimeFrom(long startTime) {
+        add(System.nanoTime() - startTime);
+    }
+
+    @Override
+    public String toString() {
+        return name + " = " + get();
+    }
+
+    static class CoreCounters {
+        static final PerfCounter pdt   = newPerfCounter("sun.classloader.parentDelegationTime");
+        static final PerfCounter lc    = newPerfCounter("sun.classloader.findClasses");
+        static final PerfCounter lct   = newPerfCounter("sun.classloader.findClassTime");
+        static final PerfCounter rcbt  = newPerfCounter("sun.urlClassLoader.readClassBytesTime");
+        static final PerfCounter zfc   = newPerfCounter("sun.zip.zipFiles");
+        static final PerfCounter zfot  = newPerfCounter("sun.zip.zipFile.openTime");
+    }
+
+    static class WindowsClientCounters {
+        static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
+    }
+
+    /**
+     * Number of findClass calls
+     */
+    public static PerfCounter getFindClasses() {
+        return CoreCounters.lc;
+    }
+
+    /**
+     * Time (ns) spent in finding classes that includes
+     * lookup and read class bytes and defineClass
+     */
+    public static PerfCounter getFindClassTime() {
+        return CoreCounters.lct;
+    }
+
+    /**
+     * Time (ns) spent in finding classes
+     */
+    public static PerfCounter getReadClassBytesTime() {
+        return CoreCounters.rcbt;
+    }
+
+    /**
+     * Time (ns) spent in the parent delegation to
+     * the parent of the defining class loader
+     */
+    public static PerfCounter getParentDelegationTime() {
+        return CoreCounters.pdt;
+    }
+
+    /**
+     * Number of zip files opened.
+     */
+    public static PerfCounter getZipFileCount() {
+        return CoreCounters.zfc;
+    }
+
+    /**
+     * Time (ns) spent in opening the zip files that
+     * includes building the entries hash table
+     */
+    public static PerfCounter getZipFileOpenTime() {
+        return CoreCounters.zfot;
+    }
+
+    /**
+     * D3D graphic pipeline available
+     */
+    public static PerfCounter getD3DAvailable() {
+        return WindowsClientCounters.d3dAvailable;
+    }
+}
--- a/src/share/classes/sun/net/spi/DefaultProxySelector.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/spi/DefaultProxySelector.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,11 +25,9 @@
 
 package sun.net.spi;
 
-import sun.net.www.http.*;
 import sun.net.NetProperties;
 import java.net.*;
 import java.util.*;
-import java.util.regex.*;
 import java.io.*;
 import sun.misc.RegexpPool;
 import java.security.AccessController;
@@ -102,17 +100,22 @@
      */
 
     static class NonProxyInfo {
+        // Default value for nonProxyHosts, this provides backward compatibility
+        // by excluding localhost and its litteral notations.
+        static final String defStringVal = "localhost|127.*|[::1]";
+
         String hostsSource;
         RegexpPool hostsPool;
-        String property;
+        final String property;
+        final String defaultVal;
+        static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
+        static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
 
-        static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
-        static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
-
-        NonProxyInfo(String p, String s, RegexpPool pool) {
+        NonProxyInfo(String p, String s, RegexpPool pool, String d) {
             property = p;
             hostsSource = s;
             hostsPool = pool;
+            defaultVal = d;
         }
     }
 
@@ -130,7 +133,6 @@
         }
         String protocol = uri.getScheme();
         String host = uri.getHost();
-        int port = uri.getPort();
 
         if (host == null) {
             // This is a hack to ensure backward compatibility in two
@@ -149,11 +151,6 @@
                 }
                 i = auth.lastIndexOf(':');
                 if (i >= 0) {
-                    try {
-                        port = Integer.parseInt(auth.substring(i+1));
-                    } catch (NumberFormatException e) {
-                        port = -1;
-                    }
                     auth = auth.substring(0,i);
                 }
                 host = auth;
@@ -165,13 +162,6 @@
         }
         List<Proxy> proxyl = new ArrayList<Proxy>(1);
 
-        // special case localhost and loopback addresses to
-        // not go through proxy
-        if (isLoopback(host)) {
-            proxyl.add(Proxy.NO_PROXY);
-            return proxyl;
-        }
-
         NonProxyInfo pinfo = null;
 
         if ("http".equalsIgnoreCase(protocol)) {
@@ -244,9 +234,14 @@
                                 nphosts = NetProperties.get(nprop.property);
                                 synchronized (nprop) {
                                     if (nphosts == null) {
-                                        nprop.hostsSource = null;
-                                        nprop.hostsPool = null;
-                                    } else {
+                                        if (nprop.defaultVal != null) {
+                                            nphosts = nprop.defaultVal;
+                                        } else {
+                                            nprop.hostsSource = null;
+                                            nprop.hostsPool = null;
+                                        }
+                                    }
+                                    if (nphosts != null) {
                                         if (!nphosts.equals(nprop.hostsSource)) {
                                             RegexpPool pool = new RegexpPool();
                                             StringTokenizer st = new StringTokenizer(nphosts, "|", false);
@@ -334,107 +329,6 @@
         }
     }
 
-    private boolean isLoopback(String host) {
-        if (host == null || host.length() == 0)
-            return false;
-
-        if (host.equalsIgnoreCase("localhost"))
-            return true;
-
-        /* The string could represent a numerical IP address.
-         * For IPv4 addresses, check whether it starts with 127.
-         * For IPv6 addresses, check whether it is ::1 or its equivalent.
-         * Don't check IPv4-mapped or IPv4-compatible addresses
-         */
-
-        if (host.startsWith("127.")) {
-            // possible IPv4 loopback address
-            int p = 4;
-            int q;
-            int n = host.length();
-            // Per RFC2732: At most three digits per byte
-            // Further constraint: Each element fits in a byte
-            if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
-            if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
-            if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
-            if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
-            if ((q = scanByte(host, p, n)) <= p) return false;
-            return q == n && number > 0;
-        }
-
-        if (host.endsWith(":1")) {
-            final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
-            return p6.matcher(host).matches();
-        }
-        return false;
-    }
-
-    // Character-class masks, in reverse order from RFC2396 because
-    // initializers for static fields cannot make forward references.
-
-    // Compute a low-order mask for the characters
-    // between first and last, inclusive
-    private static long lowMask(char first, char last) {
-        long m = 0;
-        int f = Math.max(Math.min(first, 63), 0);
-        int l = Math.max(Math.min(last, 63), 0);
-        for (int i = f; i <= l; i++)
-            m |= 1L << i;
-        return m;
-    }
-    // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
-    //            "8" | "9"
-    private static final long L_DIGIT = lowMask('0', '9');
-    private static final long H_DIGIT = 0L;
-
-    // Scan a string of decimal digits whose value fits in a byte
-    //
-    private int number;
-    private int scanByte(String input, int start, int n)
-    {
-        int p = start;
-        int q = scan(input, p, n, L_DIGIT, H_DIGIT);
-        if (q <= p) return q;
-        number = Integer.parseInt(input.substring(p, q));
-        if (number > 255) return p;
-        return q;
-    }
-
-    // Scan a specific char: If the char at the given start position is
-    // equal to c, return the index of the next char; otherwise, return the
-    // start position.
-    //
-    private int scan(String input, int start, int end, char c) {
-        if ((start < end) && (input.charAt(start) == c))
-            return start + 1;
-        return start;
-    }
-
-    // Scan chars that match the given mask pair
-    //
-    private int scan(String input, int start, int n, long lowMask, long highMask)
-    {
-        int p = start;
-        while (p < n) {
-            char c = input.charAt(p);
-            if (match(c, lowMask, highMask)) {
-                p++;
-                continue;
-            }
-            break;
-        }
-        return p;
-    }
-
-    // Tell whether the given character is permitted by the given mask pair
-    private boolean match(char c, long lowMask, long highMask) {
-        if (c < 64)
-            return ((1L << c) & lowMask) != 0;
-        if (c < 128)
-            return ((1L << (c - 64)) & highMask) != 0;
-        return false;
-    }
-
     private native static boolean init();
     private native Proxy getSystemProxy(String protocol, String host);
 }
--- a/src/share/classes/sun/net/www/http/HttpCapture.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/http/HttpCapture.java	Sat Oct 03 01:22:26 2009 +0100
@@ -24,14 +24,12 @@
  */
 
 package sun.net.www.http;
+
 import java.io.*;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.regex.*;
 import sun.net.NetProperties;
-import java.util.regex.*;
+import sun.util.logging.PlatformLogger;
 
 /**
  * Main class of the HTTP traffic capture tool.
@@ -62,76 +60,6 @@
     private static boolean initialized = false;
     private static volatile ArrayList<Pattern> patterns = null;
     private static volatile ArrayList<String> capFiles = null;
-    /* Logging is done in an ugly way so that it does not require the presence
-     * the java.util.logging package. If the Logger class is not available, then
-     * logging is turned off. This is for helping the modularization effort.
-     */
-    private static Object logger = null;
-    private static boolean logging = false;
-
-    static {
-        Class cl;
-        try {
-            cl = Class.forName("java.util.logging.Logger");
-        } catch (ClassNotFoundException ex) {
-            cl = null;
-        }
-        if (cl != null) {
-            try {
-                Method m = cl.getMethod("getLogger", String.class);
-                logger = m.invoke(null, "sun.net.www.protocol.http.HttpURLConnection");
-                logging = true;
-            } catch (NoSuchMethodException noSuchMethodException) {
-            } catch (SecurityException securityException) {
-            } catch (IllegalAccessException illegalAccessException) {
-            } catch (IllegalArgumentException illegalArgumentException) {
-            } catch (InvocationTargetException invocationTargetException) {
-            }
-        }
-    }
-
-    public static void fine(String s) {
-        if (logging) {
-            ((Logger)logger).fine(s);
-        }
-    }
-
-    public static void finer(String s) {
-        if (logging) {
-            ((Logger)logger).finer(s);
-        }
-    }
-
-    public static void finest(String s) {
-        if (logging) {
-            ((Logger)logger).finest(s);
-        }
-    }
-
-    public static void severe(String s) {
-        if (logging) {
-            ((Logger)logger).finest(s);
-        }
-    }
-
-    public static void info(String s) {
-        if (logging) {
-            ((Logger)logger).info(s);
-        }
-    }
-
-    public static void warning(String s) {
-        if (logging) {
-            ((Logger)logger).warning(s);
-        }
-    }
-
-    public static boolean isLoggable(String level) {
-        if (!logging) {
-            return false;
-        }
-        return ((Logger)logger).isLoggable(Level.parse(level));
-    }
 
     private static synchronized void init() {
         initialized = true;
@@ -187,7 +115,7 @@
             out = new BufferedWriter(new FileWriter(file, true));
             out.write("URL: " + url + "\n");
         } catch (IOException ex) {
-            Logger.getLogger(HttpCapture.class.getName()).log(Level.SEVERE, null, ex);
+            PlatformLogger.getLogger(HttpCapture.class.getName()).severe(null, ex);
         }
     }
 
--- a/src/share/classes/sun/net/www/http/HttpClient.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/http/HttpClient.java	Sat Oct 03 01:22:26 2009 +0100
@@ -35,6 +35,7 @@
 import sun.net.www.MeteredStream;
 import sun.net.www.ParseUtil;
 import sun.net.www.protocol.http.HttpURLConnection;
+import sun.util.logging.PlatformLogger;
 
 /**
  * @author Herb Jellinek
@@ -804,8 +805,9 @@
 
             if (isKeepingAlive())   {
                 // Wrap KeepAliveStream if keep alive is enabled.
-                if (HttpCapture.isLoggable("FINEST")) {
-                    HttpCapture.finest("KeepAlive stream used: " + url);
+                PlatformLogger logger = HttpURLConnection.getHttpLogger();
+                if (logger.isLoggable(PlatformLogger.FINEST)) {
+                    logger.finest("KeepAlive stream used: " + url);
                 }
                 serverInput = new KeepAliveStream(serverInput, pi, cl, this);
                 failedOnce = false;
--- a/src/share/classes/sun/net/www/http/KeepAliveCache.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/http/KeepAliveCache.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,12 +25,11 @@
 
 package sun.net.www.http;
 
-import java.io.InputStream;
 import java.io.IOException;
 import java.io.NotSerializableException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.net.URL;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A class that implements a cache of idle Http connections for keep-alive
@@ -39,7 +38,7 @@
  * @author Dave Brown
  */
 public class KeepAliveCache
-    extends ConcurrentHashMap<KeepAliveKey, ClientVector>
+    extends HashMap<KeepAliveKey, ClientVector>
     implements Runnable {
     private static final long serialVersionUID = -2937172892064557949L;
 
@@ -163,8 +162,8 @@
      * Errs on the side of caution (leave connections idle for a relatively
      * short time).
      */
+    @Override
     public void run() {
-        int total_cache;
         do {
             try {
                 Thread.sleep(LIFETIME);
@@ -311,6 +310,7 @@
     /**
      * Determine whether or not two objects of this type are equal
      */
+    @Override
     public boolean equals(Object obj) {
         if ((obj instanceof KeepAliveKey) == false)
             return false;
@@ -325,6 +325,7 @@
      * The hashCode() for this object is the string hashCode() of
      * concatenation of the protocol, host name and port.
      */
+    @Override
     public int hashCode() {
         String str = protocol+host+port;
         return this.obj == null? str.hashCode() :
--- a/src/share/classes/sun/net/www/http/KeepAliveStream.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/http/KeepAliveStream.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,10 +25,7 @@
 
 package sun.net.www.http;
 
-import java.net.URL;
-import java.net.HttpURLConnection;
 import java.io.*;
-import java.util.StringTokenizer;
 import sun.net.ProgressSource;
 import sun.net.www.MeteredStream;
 
@@ -50,9 +47,8 @@
     // has this KeepAliveStream been put on the queue for asynchronous cleanup.
     protected boolean queuedForCleanup = false;
 
-    private static KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner();
-    private static Thread cleanerThread = null;
-    private static boolean startCleanupThread;
+    private static final KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner();
+    private static Thread cleanerThread; // null
 
     /**
      * Constructor
@@ -155,43 +151,46 @@
         }
     }
 
-    private static synchronized void queueForCleanup(KeepAliveCleanerEntry kace) {
-        if(queue != null && !kace.getQueuedForCleanup()) {
-            if (!queue.offer(kace)) {
-                kace.getHttpClient().closeServer();
-                return;
+    private static void queueForCleanup(KeepAliveCleanerEntry kace) {
+        synchronized(queue) {
+            if(!kace.getQueuedForCleanup()) {
+                if (!queue.offer(kace)) {
+                    kace.getHttpClient().closeServer();
+                    return;
+                }
+
+                kace.setQueuedForCleanup();
+                queue.notifyAll();
             }
 
-            kace.setQueuedForCleanup();
-        }
+            boolean startCleanupThread = (cleanerThread == null);
+            if (!startCleanupThread) {
+                if (!cleanerThread.isAlive()) {
+                    startCleanupThread = true;
+                }
+            }
 
-        startCleanupThread = (cleanerThread == null);
-        if (!startCleanupThread) {
-            if (!cleanerThread.isAlive()) {
-                startCleanupThread = true;
+            if (startCleanupThread) {
+                java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        // We want to create the Keep-Alive-SocketCleaner in the
+                        // system threadgroup
+                        ThreadGroup grp = Thread.currentThread().getThreadGroup();
+                        ThreadGroup parent = null;
+                        while ((parent = grp.getParent()) != null) {
+                            grp = parent;
+                        }
+
+                        cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner");
+                        cleanerThread.setDaemon(true);
+                        cleanerThread.setPriority(Thread.MAX_PRIORITY - 2);
+                        cleanerThread.start();
+                        return null;
+                    }
+                });
             }
-        }
-
-        if (startCleanupThread) {
-            java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                    // We want to create the Keep-Alive-SocketCleaner in the
-                    // system threadgroup
-                    ThreadGroup grp = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parent = null;
-                    while ((parent = grp.getParent()) != null) {
-                        grp = parent;
-                    }
-
-                    cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner");
-                    cleanerThread.setDaemon(true);
-                    cleanerThread.setPriority(Thread.MAX_PRIORITY - 2);
-                    cleanerThread.start();
-                    return null;
-                }
-            });
-        }
+        } // queue
     }
 
     protected long remainingToRead() {
--- a/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,9 +25,8 @@
 
 package sun.net.www.http;
 
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
 import java.io.IOException;
+import java.util.LinkedList;
 import sun.net.NetProperties;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -44,7 +43,9 @@
  */
 
 @SuppressWarnings("serial")  // never serialized
-public class KeepAliveStreamCleaner extends LinkedBlockingQueue<KeepAliveCleanerEntry> implements Runnable
+class KeepAliveStreamCleaner
+    extends LinkedList<KeepAliveCleanerEntry>
+    implements Runnable
 {
     // maximum amount of remaining data that we will try to cleanup
     protected static int MAX_DATA_REMAINING = 512;
@@ -78,23 +79,39 @@
     }
 
 
-    public KeepAliveStreamCleaner()
-    {
-        super(MAX_CAPACITY);
+    @Override
+    public boolean offer(KeepAliveCleanerEntry e) {
+        if (size() >= MAX_CAPACITY)
+            return false;
+
+        return super.offer(e);
     }
 
-    public KeepAliveStreamCleaner(int capacity)
-    {
-        super(capacity);
-    }
-
+    @Override
     public void run()
     {
         KeepAliveCleanerEntry kace = null;
 
         do {
             try {
-                kace = poll((long)TIMEOUT, TimeUnit.MILLISECONDS);
+                synchronized(this) {
+                    long before = System.currentTimeMillis();
+                    long timeout = TIMEOUT;
+                    while ((kace = poll()) == null) {
+                        this.wait(timeout);
+
+                        long after = System.currentTimeMillis();
+                        long elapsed = after - before;
+                        if (elapsed > timeout) {
+                            /* one last try */
+                            kace = poll();
+                            break;
+                        }
+                        before = after;
+                        timeout -= elapsed;
+                    }
+                }
+
                 if(kace == null)
                     break;
 
--- a/src/share/classes/sun/net/www/protocol/http/AuthCache.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/AuthCache.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,14 +25,6 @@
 
 package sun.net.www.protocol.http;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Enumeration;
-import java.util.HashMap;
-
 /**
  * @author Michael McMahon
  *
@@ -49,7 +41,7 @@
      * A:[B:]C:D:E[:F]   Between 4 and 6 fields separated by ":"
      *          where the fields have the following meaning:
      * A is "s" or "p" for server or proxy authentication respectively
-     * B is optional and is "D", "B", or "N" for digest, basic or ntlm auth.
+     * B is optional and is the {@link AuthScheme}, e.g. BASIC, DIGEST, NTLM, etc
      * C is either "http" or "https"
      * D is the hostname
      * E is the port number
--- a/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,15 +25,8 @@
 
 package sun.net.www.protocol.http;
 
-import java.io.IOException;
 import java.io.Serializable;
-import java.net.*;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Enumeration;
-import java.util.HashMap;
-
+import java.net.PasswordAuthentication;
 
 /**
  * AuthCacheValue: interface to minimise exposure to authentication cache
@@ -62,8 +55,16 @@
 
     AuthCacheValue() {}
 
+    /**
+     * Proxy or Server
+     */
     abstract Type getAuthType ();
 
+    /**
+     * Authentication scheme
+     */
+    abstract AuthScheme getAuthScheme();
+
    /**
     * name of server/proxy
     */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/net/www/protocol/http/AuthScheme.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.net.www.protocol.http;
+
+/* Authentication schemes supported by the http implementation. New schemes, if
+ * supported, should be defined here.
+ */
+public enum AuthScheme {
+    BASIC,
+    DIGEST,
+    NTLM,
+    NEGOTIATE,
+    KERBEROS,
+    UNKNOWN;
+}
+
--- a/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java	Sat Oct 03 01:22:26 2009 +0100
@@ -85,6 +85,11 @@
             AuthCacheValue.Type.Server:
             AuthCacheValue.Type.Proxy;
     }
+
+    AuthScheme getAuthScheme() {
+        return authScheme;
+    }
+
     public String getHost() {
         return host;
     }
@@ -151,7 +156,7 @@
     }
 
     //public String toString () {
-        //return ("{"+type+":"+authType+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
+        //return ("{"+type+":"+authScheme+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
     //}
 
     // REMIND:  This cache just grows forever.  We should put in a bounded
@@ -160,8 +165,8 @@
     /** The type (server/proxy) of authentication this is.  Used for key lookup */
     char type;
 
-    /** The authentication type (basic/digest). Also used for key lookup */
-    char authType;
+    /** The authentication scheme (basic/digest). Also used for key lookup */
+    AuthScheme authScheme;
 
     /** The protocol/scheme (i.e. http or https ). Need to keep the caches
      *  logically separate for the two protocols. This field is only used
@@ -183,9 +188,9 @@
     String path;
 
     /** Use this constructor only for proxy entries */
-    AuthenticationInfo(char type, char authType, String host, int port, String realm) {
+    AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
         this.type = type;
-        this.authType = authType;
+        this.authScheme = authScheme;
         this.protocol = "";
         this.host = host.toLowerCase();
         this.port = port;
@@ -206,9 +211,9 @@
      * Constructor used to limit the authorization to the path within
      * the URL. Use this constructor for origin server entries.
      */
-    AuthenticationInfo(char type, char authType, URL url, String realm) {
+    AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
         this.type = type;
-        this.authType = authType;
+        this.authScheme = authScheme;
         this.protocol = url.getProtocol().toLowerCase();
         this.host = url.getHost().toLowerCase();
         this.port = url.getPort();
@@ -264,12 +269,12 @@
      * In this case we do not use the path because the protection space
      * is identified by the host:port:realm only
      */
-    static AuthenticationInfo getServerAuth(URL url, String realm, char atype) {
+    static AuthenticationInfo getServerAuth(URL url, String realm, AuthScheme scheme) {
         int port = url.getPort();
         if (port == -1) {
             port = url.getDefaultPort();
         }
-        String key = SERVER_AUTHENTICATION + ":" + atype + ":" + url.getProtocol().toLowerCase()
+        String key = SERVER_AUTHENTICATION + ":" + scheme + ":" + url.getProtocol().toLowerCase()
                      + ":" + url.getHost().toLowerCase() + ":" + port + ":" + realm;
         AuthenticationInfo cached = getAuth(key, null);
         if ((cached == null) && requestIsInProgress (key)) {
@@ -308,8 +313,8 @@
      * Used in response to a challenge. Note, the protocol field is always
      * blank for proxies.
      */
-    static AuthenticationInfo getProxyAuth(String host, int port, String realm, char atype) {
-        String key = PROXY_AUTHENTICATION + ":" + atype + "::" + host.toLowerCase()
+    static AuthenticationInfo getProxyAuth(String host, int port, String realm, AuthScheme scheme) {
+        String key = PROXY_AUTHENTICATION + ":" + scheme + "::" + host.toLowerCase()
                         + ":" + port + ":" + realm;
         AuthenticationInfo cached = (AuthenticationInfo) cache.get(key, null);
         if ((cached == null) && requestIsInProgress (key)) {
@@ -409,7 +414,7 @@
         // This must be kept in sync with the getXXXAuth() methods in this
         // class.
         if (includeRealm) {
-            return type + ":" + authType + ":" + protocol + ":"
+            return type + ":" + authScheme + ":" + protocol + ":"
                         + host + ":" + port + ":" + realm;
         } else {
             return type + ":" + protocol + ":" + host + ":" + port;
--- a/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java	Sat Oct 03 01:22:26 2009 +0100
@@ -44,8 +44,6 @@
 
     private static final long serialVersionUID = 100L;
 
-    static final char BASIC_AUTH = 'B';
-
     /** The authentication string for this host, port, and realm.  This is
         a simple BASE64 encoding of "login:password".    */
     String auth;
@@ -56,7 +54,7 @@
     public BasicAuthentication(boolean isProxy, String host, int port,
                                String realm, PasswordAuthentication pw) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, host, port, realm);
+              AuthScheme.BASIC, host, port, realm);
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -86,7 +84,7 @@
     public BasicAuthentication(boolean isProxy, String host, int port,
                                String realm, String auth) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, host, port, realm);
+              AuthScheme.BASIC, host, port, realm);
         this.auth = "Basic " + auth;
     }
 
@@ -96,7 +94,7 @@
     public BasicAuthentication(boolean isProxy, URL url, String realm,
                                    PasswordAuthentication pw) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, url, realm);
+              AuthScheme.BASIC, url, realm);
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -126,7 +124,7 @@
     public BasicAuthentication(boolean isProxy, URL url, String realm,
                                    String auth) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, url, realm);
+              AuthScheme.BASIC, url, realm);
         this.auth = "Basic " + auth;
     }
 
--- a/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java	Sat Oct 03 01:22:26 2009 +0100
@@ -38,7 +38,6 @@
 import java.security.NoSuchAlgorithmException;
 import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT;
 
-
 /**
  * DigestAuthentication: Encapsulate an http server authentication using
  * the "Digest" scheme, as described in RFC2069 and updated in RFC2617
@@ -50,8 +49,6 @@
 
     private static final long serialVersionUID = 100L;
 
-    static final char DIGEST_AUTH = 'D';
-
     private String authMethod;
 
     // Authentication parameters defined in RFC2617.
@@ -178,7 +175,10 @@
     public DigestAuthentication(boolean isProxy, URL url, String realm,
                                 String authMethod, PasswordAuthentication pw,
                                 Parameters params) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,url, realm);
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              AuthScheme.DIGEST,
+              url,
+              realm);
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
@@ -187,7 +187,11 @@
     public DigestAuthentication(boolean isProxy, String host, int port, String realm,
                                 String authMethod, PasswordAuthentication pw,
                                 Parameters params) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,host, port, realm);
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              AuthScheme.DIGEST,
+              host,
+              port,
+              realm);
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
--- a/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java	Sat Oct 03 01:22:26 2009 +0100
@@ -49,8 +49,10 @@
 
     @Override
     public String format(LogRecord record) {
-        if (!"sun.net.www.http.HttpCapture".equalsIgnoreCase(record.getSourceClassName())) {
-            // Don't change format for stuff that doesn't concern us
+        String sourceClassName = record.getSourceClassName();
+        if (sourceClassName == null ||
+            !(sourceClassName.startsWith("sun.net.www.protocol.http") ||
+              sourceClassName.startsWith("sun.net.www.http"))) {
             return super.format(record);
         }
         String src = record.getMessage();
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Sat Oct 03 01:22:26 2009 +0100
@@ -57,11 +57,17 @@
 import sun.net.www.http.PosterOutputStream;
 import sun.net.www.http.ChunkedInputStream;
 import sun.net.www.http.ChunkedOutputStream;
-import sun.net.www.http.HttpCapture;
+import sun.util.logging.PlatformLogger;
 import java.text.SimpleDateFormat;
 import java.util.TimeZone;
 import java.net.MalformedURLException;
 import java.nio.ByteBuffer;
+import static sun.net.www.protocol.http.AuthScheme.BASIC;
+import static sun.net.www.protocol.http.AuthScheme.DIGEST;
+import static sun.net.www.protocol.http.AuthScheme.NTLM;
+import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
+import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
+import static sun.net.www.protocol.http.AuthScheme.UNKNOWN;
 
 /**
  * A class to represent an HTTP connection to a remote object.
@@ -231,9 +237,11 @@
     boolean             needToCheck = true;
     private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */
     private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */
-    /* try auth without calling Authenticator */
-    private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();
-    private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth();
+
+    /* try auth without calling Authenticator. Used for transparent NTLM authentication */
+    private boolean tryTransparentNTLMServer = true;
+    private boolean tryTransparentNTLMProxy = true;
+
     /* Used by Windows specific code */
     Object authObj;
 
@@ -284,6 +292,10 @@
     private int connectTimeout = -1;
     private int readTimeout = -1;
 
+    /* Logging support */
+    private static final PlatformLogger logger =
+            PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
+
     /*
      * privileged request password authentication
      *
@@ -301,20 +313,25 @@
         return java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<PasswordAuthentication>() {
                 public PasswordAuthentication run() {
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Requesting Authentication: host =" + host + " url = " + url);
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Requesting Authentication: host =" + host + " url = " + url);
                     }
                     PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
                         host, addr, port, protocol,
                         prompt, scheme, url, authType);
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
                     }
                     return pass;
                 }
             });
     }
 
+    /* Logging support */
+    public static PlatformLogger getHttpLogger() {
+        return logger;
+    }
+
     /*
      * checks the validity of http message header and throws
      * IllegalArgumentException if invalid.
@@ -463,8 +480,8 @@
 
             setRequests=true;
         }
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine(requests.toString());
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine(requests.toString());
         }
         http.writeRequests(requests, poster);
         if (ps.checkError()) {
@@ -728,9 +745,9 @@
                         && !(cachedResponse instanceof SecureCacheResponse)) {
                         cachedResponse = null;
                     }
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Cache Request for " + uri + " / " + getRequestMethod());
-                        HttpCapture.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
+                        logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
                     }
                     if (cachedResponse != null) {
                         cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
@@ -769,8 +786,8 @@
                              });
                 if (sel != null) {
                     URI uri = sun.net.www.ParseUtil.toURI(url);
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("ProxySelector Request for " + uri);
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("ProxySelector Request for " + uri);
                     }
                     Iterator<Proxy> it = sel.select(uri).iterator();
                     Proxy p;
@@ -786,9 +803,9 @@
                                 http = getNewHttpClient(url, p, connectTimeout, false);
                                 http.setReadTimeout(readTimeout);
                             }
-                            if (HttpCapture.isLoggable("FINEST")) {
+                            if (logger.isLoggable(PlatformLogger.FINEST)) {
                                 if (p != null) {
-                                    HttpCapture.finest("Proxy used: " + p.toString());
+                                    logger.finest("Proxy used: " + p.toString());
                                 }
                             }
                             break;
@@ -1018,15 +1035,15 @@
 
             URI uri = ParseUtil.toURI(url);
             if (uri != null) {
-                if (HttpCapture.isLoggable("FINEST")) {
-                    HttpCapture.finest("CookieHandler request for " + uri);
+                if (logger.isLoggable(PlatformLogger.FINEST)) {
+                    logger.finest("CookieHandler request for " + uri);
                 }
                 Map<String, List<String>> cookies
                     = cookieHandler.get(
                         uri, requests.getHeaders(EXCLUDE_HEADERS));
                 if (!cookies.isEmpty()) {
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Cookies retrieved: " + cookies.toString());
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Cookies retrieved: " + cookies.toString());
                     }
                     for (Map.Entry<String, List<String>> entry :
                              cookies.entrySet()) {
@@ -1157,8 +1174,8 @@
                     writeRequests();
                 }
                 http.parseHTTP(responses, pi, this);
-                if (HttpCapture.isLoggable("FINE")) {
-                    HttpCapture.fine(responses.toString());
+                if (logger.isLoggable(PlatformLogger.FINE)) {
+                    logger.fine(responses.toString());
                 }
                 inputStream = http.getInputStream();
 
@@ -1270,7 +1287,7 @@
                     String raw = srvHdr.raw();
                     if (!doingNTLM2ndStage) {
                         if ((serverAuthentication != null)&&
-                            !(serverAuthentication instanceof NTLMAuthentication)) {
+                            serverAuthentication.getAuthScheme() != NTLM) {
                             if (serverAuthentication.isAuthorizationStale (raw)) {
                                 /* we can retry with the current credentials */
                                 disconnectInternal();
@@ -1523,8 +1540,8 @@
      */
     private AuthenticationInfo
         resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) {
-        if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof
-                                                        NTLMAuthentication)) {
+        if ((proxyAuthentication != null )&&
+             proxyAuthentication.getAuthScheme() != NTLM) {
             String raw = auth.raw();
             if (proxyAuthentication.isAuthorizationStale (raw)) {
                 /* we can retry with the current credentials */
@@ -1602,8 +1619,8 @@
                 http.parseHTTP(responses, null, this);
 
                 /* Log the response to the CONNECT */
-                if (HttpCapture.isLoggable("FINE")) {
-                    HttpCapture.fine(responses.toString());
+                if (logger.isLoggable(PlatformLogger.FINE)) {
+                    logger.fine(responses.toString());
                 }
 
                 statusLine = responses.getValue(0);
@@ -1730,8 +1747,8 @@
         setPreemptiveProxyAuthentication(requests);
 
          /* Log the CONNECT request */
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine(requests.toString());
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine(requests.toString());
         }
 
         http.writeRequests(requests, null);
@@ -1776,28 +1793,31 @@
             HeaderParser p = authhdr.headerParser();
             String realm = p.findValue("realm");
             String scheme = authhdr.scheme();
-            char schemeID;
+            AuthScheme authScheme = UNKNOWN;
             if ("basic".equalsIgnoreCase(scheme)) {
-                schemeID = BasicAuthentication.BASIC_AUTH;
+                authScheme = BASIC;
             } else if ("digest".equalsIgnoreCase(scheme)) {
-                schemeID = DigestAuthentication.DIGEST_AUTH;
+                authScheme = DIGEST;
             } else if ("ntlm".equalsIgnoreCase(scheme)) {
-                schemeID = NTLMAuthentication.NTLM_AUTH;
+                authScheme = NTLM;
                 doingNTLMp2ndStage = true;
             } else if ("Kerberos".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.KERBEROS_AUTH;
+                authScheme = KERBEROS;
                 doingNTLMp2ndStage = true;
             } else if ("Negotiate".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
+                authScheme = NEGOTIATE;
                 doingNTLMp2ndStage = true;
-            } else {
-                schemeID = 0;
             }
+
             if (realm == null)
                 realm = "";
-            ret = AuthenticationInfo.getProxyAuth(host, port, realm, schemeID);
+            ret = AuthenticationInfo.getProxyAuth(host,
+                                                  port,
+                                                  realm,
+                                                  authScheme);
             if (ret == null) {
-                if (schemeID == BasicAuthentication.BASIC_AUTH) {
+                switch (authScheme) {
+                case BASIC:
                     InetAddress addr = null;
                     try {
                         final String finalHost = host;
@@ -1818,9 +1838,9 @@
                     if (a != null) {
                         ret = new BasicAuthentication(true, host, port, realm, a);
                     }
-                } else if (schemeID == DigestAuthentication.DIGEST_AUTH) {
-                    PasswordAuthentication a =
-                        privilegedRequestPasswordAuthentication(
+                    break;
+                case DIGEST:
+                    a = privilegedRequestPasswordAuthentication(
                                     host, null, port, url.getProtocol(),
                                     realm, scheme, url, RequestorType.PROXY);
                     if (a != null) {
@@ -1829,29 +1849,49 @@
                         ret = new DigestAuthentication(true, host, port, realm,
                                                             scheme, a, params);
                     }
-                } else if (schemeID == NTLMAuthentication.NTLM_AUTH) {
-                    PasswordAuthentication a = null;
-                    if (!tryTransparentNTLMProxy) {
-                        a = privilegedRequestPasswordAuthentication(
-                                            host, null, port, url.getProtocol(),
-                                            "", scheme, url, RequestorType.PROXY);
+                    break;
+                case NTLM:
+                    if (NTLMAuthenticationProxy.proxy.supported) {
+                        /* tryTransparentNTLMProxy will always be true the first
+                         * time around, but verify that the platform supports it
+                         * otherwise don't try. */
+                        if (tryTransparentNTLMProxy) {
+                            tryTransparentNTLMProxy =
+                                    NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
+                        }
+                        a = null;
+                        if (tryTransparentNTLMProxy) {
+                            logger.finest("Trying Transparent NTLM authentication");
+                        } else {
+                            a = privilegedRequestPasswordAuthentication(
+                                                host, null, port, url.getProtocol(),
+                                                "", scheme, url, RequestorType.PROXY);
+                        }
+                        /* If we are not trying transparent authentication then
+                         * we need to have a PasswordAuthentication instance. For
+                         * transparent authentication (Windows only) the username
+                         * and password will be picked up from the current logged
+                         * on users credentials.
+                        */
+                        if (tryTransparentNTLMProxy ||
+                              (!tryTransparentNTLMProxy && a != null)) {
+                            ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
+                        }
+
+                        /* set to false so that we do not try again */
+                        tryTransparentNTLMProxy = false;
                     }
-                    /* If we are not trying transparent authentication then
-                     * we need to have a PasswordAuthentication instance. For
-                     * transparent authentication (Windows only) the username
-                     * and password will be picked up from the current logged
-                     * on users credentials.
-                    */
-                    if (tryTransparentNTLMProxy ||
-                          (!tryTransparentNTLMProxy && a != null)) {
-                        ret = new NTLMAuthentication(true, host, port, a);
-                    }
-
-                    tryTransparentNTLMProxy = false;
-                } else if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
+                    break;
+                case NEGOTIATE:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
-                } else if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
+                    break;
+                case KERBEROS:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
+                    break;
+                case UNKNOWN:
+                    logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
+                default:
+                    throw new AssertionError("should not reach here");
                 }
             }
             // For backwards compatibility, we also try defaultAuth
@@ -1875,8 +1915,8 @@
                 }
             }
         }
-        if (HttpCapture.isLoggable("FINER")) {
-            HttpCapture.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
+        if (logger.isLoggable(PlatformLogger.FINER)) {
+            logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
         }
         return ret;
     }
@@ -1896,27 +1936,26 @@
             HeaderParser p = authhdr.headerParser();
             String realm = p.findValue("realm");
             String scheme = authhdr.scheme();
-            char schemeID;
+            AuthScheme authScheme = UNKNOWN;
             if ("basic".equalsIgnoreCase(scheme)) {
-                schemeID = BasicAuthentication.BASIC_AUTH;
+                authScheme = BASIC;
             } else if ("digest".equalsIgnoreCase(scheme)) {
-                schemeID = DigestAuthentication.DIGEST_AUTH;
+                authScheme = DIGEST;
             } else if ("ntlm".equalsIgnoreCase(scheme)) {
-                schemeID = NTLMAuthentication.NTLM_AUTH;
+                authScheme = NTLM;
                 doingNTLM2ndStage = true;
             } else if ("Kerberos".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.KERBEROS_AUTH;
+                authScheme = KERBEROS;
                 doingNTLM2ndStage = true;
             } else if ("Negotiate".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
+                authScheme = NEGOTIATE;
                 doingNTLM2ndStage = true;
-            } else {
-                schemeID = 0;
             }
+
             domain = p.findValue ("domain");
             if (realm == null)
                 realm = "";
-            ret = AuthenticationInfo.getServerAuth(url, realm, schemeID);
+            ret = AuthenticationInfo.getServerAuth(url, realm, authScheme);
             InetAddress addr = null;
             if (ret == null) {
                 try {
@@ -1931,13 +1970,14 @@
                 port = url.getDefaultPort();
             }
             if (ret == null) {
-                if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
+                switch(authScheme) {
+                case KERBEROS:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
-                }
-                if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
+                    break;
+                case NEGOTIATE:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
-                }
-                if (schemeID == BasicAuthentication.BASIC_AUTH) {
+                    break;
+                case BASIC:
                     PasswordAuthentication a =
                         privilegedRequestPasswordAuthentication(
                             url.getHost(), addr, port, url.getProtocol(),
@@ -1945,45 +1985,60 @@
                     if (a != null) {
                         ret = new BasicAuthentication(false, url, realm, a);
                     }
-                }
-
-                if (schemeID == DigestAuthentication.DIGEST_AUTH) {
-                    PasswordAuthentication a =
-                        privilegedRequestPasswordAuthentication(
+                    break;
+                case DIGEST:
+                    a = privilegedRequestPasswordAuthentication(
                             url.getHost(), addr, port, url.getProtocol(),
                             realm, scheme, url, RequestorType.SERVER);
                     if (a != null) {
                         digestparams = new DigestAuthentication.Parameters();
                         ret = new DigestAuthentication(false, url, realm, scheme, a, digestparams);
                     }
-                }
+                    break;
+                case NTLM:
+                    if (NTLMAuthenticationProxy.proxy.supported) {
+                        URL url1;
+                        try {
+                            url1 = new URL (url, "/"); /* truncate the path */
+                        } catch (Exception e) {
+                            url1 = url;
+                        }
 
-                if (schemeID == NTLMAuthentication.NTLM_AUTH) {
-                    URL url1;
-                    try {
-                        url1 = new URL (url, "/"); /* truncate the path */
-                    } catch (Exception e) {
-                        url1 = url;
+                        /* tryTransparentNTLMServer will always be true the first
+                         * time around, but verify that the platform supports it
+                         * otherwise don't try. */
+                        if (tryTransparentNTLMServer) {
+                            tryTransparentNTLMServer =
+                                    NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
+                        }
+                        a = null;
+                        if (tryTransparentNTLMServer) {
+                            logger.finest("Trying Transparent NTLM authentication");
+                        } else {
+                            a = privilegedRequestPasswordAuthentication(
+                                url.getHost(), addr, port, url.getProtocol(),
+                                "", scheme, url, RequestorType.SERVER);
+                        }
+
+                        /* If we are not trying transparent authentication then
+                         * we need to have a PasswordAuthentication instance. For
+                         * transparent authentication (Windows only) the username
+                         * and password will be picked up from the current logged
+                         * on users credentials.
+                         */
+                        if (tryTransparentNTLMServer ||
+                              (!tryTransparentNTLMServer && a != null)) {
+                            ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
+                        }
+
+                        /* set to false so that we do not try again */
+                        tryTransparentNTLMServer = false;
                     }
-                    PasswordAuthentication a = null;
-                    if (!tryTransparentNTLMServer) {
-                        a = privilegedRequestPasswordAuthentication(
-                            url.getHost(), addr, port, url.getProtocol(),
-                            "", scheme, url, RequestorType.SERVER);
-                    }
-
-                    /* If we are not trying transparent authentication then
-                     * we need to have a PasswordAuthentication instance. For
-                     * transparent authentication (Windows only) the username
-                     * and password will be picked up from the current logged
-                     * on users credentials.
-                     */
-                    if (tryTransparentNTLMServer ||
-                          (!tryTransparentNTLMServer && a != null)) {
-                        ret = new NTLMAuthentication(false, url1, a);
-                    }
-
-                    tryTransparentNTLMServer = false;
+                    break;
+                case UNKNOWN:
+                    logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
+                default:
+                    throw new AssertionError("should not reach here");
                 }
             }
 
@@ -2005,8 +2060,8 @@
                 }
             }
         }
-        if (HttpCapture.isLoggable("FINER")) {
-            HttpCapture.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
+        if (logger.isLoggable(PlatformLogger.FINER)) {
+            logger.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
         }
         return ret;
     }
@@ -2081,8 +2136,8 @@
         if (streaming()) {
             throw new HttpRetryException (RETRY_MSG3, stat, loc);
         }
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine("Redirected from " + url + " to " + locUrl);
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine("Redirected from " + url + " to " + locUrl);
         }
 
         // clear out old response headers!!!!
--- a/src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java	Tue Sep 29 14:24:18 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * 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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.net.www.protocol.http;
-
-import java.net.URI;
-import java.net.CookieStore;
-import java.net.HttpCookie;
-import java.net.URISyntaxException;
-import java.util.List;
-import java.util.Map;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * A simple in-memory java.net.CookieStore implementation
- *
- * @author Edward Wang
- * @since 1.6
- */
-public class InMemoryCookieStore implements CookieStore {
-    // the in-memory representation of cookies
-    private List<HttpCookie> cookieJar = null;
-
-    // the cookies are indexed by its domain and associated uri (if present)
-    // CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
-    //          it won't be cleared in domainIndex & uriIndex. Double-check the
-    //          presence of cookie when retrieve one form index store.
-    private Map<String, List<HttpCookie>> domainIndex = null;
-    private Map<URI, List<HttpCookie>> uriIndex = null;
-
-    // use ReentrantLock instead of syncronized for scalability
-    private ReentrantLock lock = null;
-
-
-    /**
-     * The default ctor
-     */
-    public InMemoryCookieStore() {
-        cookieJar = new ArrayList<HttpCookie>();
-        domainIndex = new HashMap<String, List<HttpCookie>>();
-        uriIndex = new HashMap<URI, List<HttpCookie>>();
-
-        lock = new ReentrantLock(false);
-    }
-
-    /**
-     * Add one cookie into cookie store.
-     */
-    public void add(URI uri, HttpCookie cookie) {
-        // pre-condition : argument can't be null
-        if (cookie == null) {
-            throw new NullPointerException("cookie is null");
-        }
-
-
-        lock.lock();
-        try {
-            // remove the ole cookie if there has had one
-            cookieJar.remove(cookie);
-
-            // add new cookie if it has a non-zero max-age
-            if (cookie.getMaxAge() != 0) {
-                cookieJar.add(cookie);
-                // and add it to domain index
-                if (cookie.getDomain() != null) {
-                    addIndex(domainIndex, cookie.getDomain(), cookie);
-                }
-                // add it to uri index, too
-                addIndex(uriIndex, getEffectiveURI(uri), cookie);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-
-    /**
-     * Get all cookies, which:
-     *  1) given uri domain-matches with, or, associated with
-     *     given uri when added to the cookie store.
-     *  3) not expired.
-     * See RFC 2965 sec. 3.3.4 for more detail.
-     */
-    public List<HttpCookie> get(URI uri) {
-        // argument can't be null
-        if (uri == null) {
-            throw new NullPointerException("uri is null");
-        }
-
-        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
-        boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
-        lock.lock();
-        try {
-            // check domainIndex first
-            getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
-            // check uriIndex then
-            getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
-        } finally {
-            lock.unlock();
-        }
-
-        return cookies;
-    }
-
-    /**
-     * Get all cookies in cookie store, except those have expired
-     */
-    public List<HttpCookie> getCookies() {
-        List<HttpCookie> rt;
-
-        lock.lock();
-        try {
-            Iterator<HttpCookie> it = cookieJar.iterator();
-            while (it.hasNext()) {
-                if (it.next().hasExpired()) {
-                    it.remove();
-                }
-            }
-        } finally {
-            rt = Collections.unmodifiableList(cookieJar);
-            lock.unlock();
-        }
-
-        return rt;
-    }
-
-    /**
-     * Get all URIs, which are associated with at least one cookie
-     * of this cookie store.
-     */
-    public List<URI> getURIs() {
-        List<URI> uris = new ArrayList<URI>();
-
-        lock.lock();
-        try {
-            Iterator<URI> it = uriIndex.keySet().iterator();
-            while (it.hasNext()) {
-                URI uri = it.next();
-                List<HttpCookie> cookies = uriIndex.get(uri);
-                if (cookies == null || cookies.size() == 0) {
-                    // no cookies list or an empty list associated with
-                    // this uri entry, delete it
-                    it.remove();
-                }
-            }
-        } finally {
-            uris.addAll(uriIndex.keySet());
-            lock.unlock();
-        }
-
-        return uris;
-    }
-
-
-    /**
-     * Remove a cookie from store
-     */
-    public boolean remove(URI uri, HttpCookie ck) {
-        // argument can't be null
-        if (ck == null) {
-            throw new NullPointerException("cookie is null");
-        }
-
-        boolean modified = false;
-        lock.lock();
-        try {
-            modified = cookieJar.remove(ck);
-        } finally {
-            lock.unlock();
-        }
-
-        return modified;
-    }
-
-
-    /**
-     * Remove all cookies in this cookie store.
-     */
-    public boolean removeAll() {
-        lock.lock();
-        try {
-            cookieJar.clear();
-            domainIndex.clear();
-            uriIndex.clear();
-        } finally {
-            lock.unlock();
-        }
-
-        return true;
-    }
-
-
-    /* ---------------- Private operations -------------- */
-
-
-    /*
-     * This is almost the same as HttpCookie.domainMatches except for
-     * one difference: It won't reject cookies when the 'H' part of the
-     * domain contains a dot ('.').
-     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
-     * and the cookie domain is .domain.com, then it should be rejected.
-     * However that's not how the real world works. Browsers don't reject and
-     * some sites, like yahoo.com do actually expect these cookies to be
-     * passed along.
-     * And should be used for 'old' style cookies (aka Netscape type of cookies)
-     */
-    private boolean netscapeDomainMatches(String domain, String host)
-    {
-        if (domain == null || host == null) {
-            return false;
-        }
-
-        // if there's no embedded dot in domain and domain is not .local
-        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
-        int embeddedDotInDomain = domain.indexOf('.');
-        if (embeddedDotInDomain == 0) {
-            embeddedDotInDomain = domain.indexOf('.', 1);
-        }
-        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
-            return false;
-        }
-
-        // if the host name contains no dot and the domain name is .local
-        int firstDotInHost = host.indexOf('.');
-        if (firstDotInHost == -1 && isLocalDomain) {
-            return true;
-        }
-
-        int domainLength = domain.length();
-        int lengthDiff = host.length() - domainLength;
-        if (lengthDiff == 0) {
-            // if the host name and the domain name are just string-compare euqal
-            return host.equalsIgnoreCase(domain);
-        } else if (lengthDiff > 0) {
-            // need to check H & D component
-            String H = host.substring(0, lengthDiff);
-            String D = host.substring(lengthDiff);
-
-            return (D.equalsIgnoreCase(domain));
-        } else if (lengthDiff == -1) {
-            // if domain is actually .host
-            return (domain.charAt(0) == '.' &&
-                    host.equalsIgnoreCase(domain.substring(1)));
-        }
-
-        return false;
-    }
-
-    private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
-            String host, boolean secureLink) {
-        // Use a separate list to handle cookies that need to be removed so
-        // that there is no conflict with iterators.
-        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
-        for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
-            String domain = entry.getKey();
-            List<HttpCookie> lst = entry.getValue();
-            for (HttpCookie c : lst) {
-                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
-                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
-                    if ((cookieJar.indexOf(c) != -1)) {
-                        // the cookie still in main cookie store
-                        if (!c.hasExpired()) {
-                            // don't add twice and make sure it's the proper
-                            // security level
-                            if ((secureLink || !c.getSecure()) &&
-                                    !cookies.contains(c)) {
-                                cookies.add(c);
-                            }
-                        } else {
-                            toRemove.add(c);
-                        }
-                    } else {
-                        // the cookie has beed removed from main store,
-                        // so also remove it from domain indexed store
-                        toRemove.add(c);
-                    }
-                }
-            }
-            // Clear up the cookies that need to be removed
-            for (HttpCookie c : toRemove) {
-                lst.remove(c);
-                cookieJar.remove(c);
-
-            }
-            toRemove.clear();
-        }
-    }
-
-    // @param cookies           [OUT] contains the found cookies
-    // @param cookieIndex       the index
-    // @param comparator        the prediction to decide whether or not
-    //                          a cookie in index should be returned
-    private <T> void getInternal2(List<HttpCookie> cookies,
-                                Map<T, List<HttpCookie>> cookieIndex,
-                                Comparable<T> comparator, boolean secureLink)
-    {
-        for (T index : cookieIndex.keySet()) {
-            if (comparator.compareTo(index) == 0) {
-                List<HttpCookie> indexedCookies = cookieIndex.get(index);
-                // check the list of cookies associated with this domain
-                if (indexedCookies != null) {
-                    Iterator<HttpCookie> it = indexedCookies.iterator();
-                    while (it.hasNext()) {
-                        HttpCookie ck = it.next();
-                        if (cookieJar.indexOf(ck) != -1) {
-                            // the cookie still in main cookie store
-                            if (!ck.hasExpired()) {
-                                // don't add twice
-                                if ((secureLink || !ck.getSecure()) &&
-                                        !cookies.contains(ck))
-                                    cookies.add(ck);
-                            } else {
-                                it.remove();
-                                cookieJar.remove(ck);
-                            }
-                        } else {
-                            // the cookie has beed removed from main store,
-                            // so also remove it from domain indexed store
-                            it.remove();
-                        }
-                    }
-                } // end of indexedCookies != null
-            } // end of comparator.compareTo(index) == 0
-        } // end of cookieIndex iteration
-    }
-
-    // add 'cookie' indexed by 'index' into 'indexStore'
-    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
-                              T index,
-                              HttpCookie cookie)
-    {
-        if (index != null) {
-            List<HttpCookie> cookies = indexStore.get(index);
-            if (cookies != null) {
-                // there may already have the same cookie, so remove it first
-                cookies.remove(cookie);
-
-                cookies.add(cookie);
-            } else {
-                cookies = new ArrayList<HttpCookie>();
-                cookies.add(cookie);
-                indexStore.put(index, cookies);
-            }
-        }
-    }
-
-
-    //
-    // for cookie purpose, the effective uri should only be http://host
-    // the path will be taken into account when path-match algorithm applied
-    //
-    private URI getEffectiveURI(URI uri) {
-        URI effectiveURI = null;
-        try {
-            effectiveURI = new URI("http",
-                                   uri.getHost(),
-                                   null,  // path component
-                                   null,  // query component
-                                   null   // fragment component
-                                  );
-        } catch (URISyntaxException ignored) {
-            effectiveURI = uri;
-        }
-
-        return effectiveURI;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.net.www.protocol.http;
+
+import java.net.URL;
+import java.net.PasswordAuthentication;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * Proxy class for loading NTLMAuthentication, so as to remove static
+ * dependancy.
+ */
+class NTLMAuthenticationProxy {
+    private static Method supportsTA;
+    private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication";
+    private static final String supportsTAStr = "supportsTransparentAuth";
+
+    static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
+    static final boolean supported = proxy != null ? true : false;
+    static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false;
+
+    private final Constructor<? extends AuthenticationInfo> threeArgCtr;
+    private final Constructor<? extends AuthenticationInfo> fiveArgCtr;
+
+    private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> threeArgCtr,
+                                    Constructor<? extends AuthenticationInfo> fiveArgCtr) {
+        this.threeArgCtr = threeArgCtr;
+        this.fiveArgCtr = fiveArgCtr;
+    }
+
+
+    AuthenticationInfo create(boolean isProxy,
+                              URL url,
+                              PasswordAuthentication pw) {
+        try {
+            return threeArgCtr.newInstance(isProxy, url, pw);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return null;
+    }
+
+    AuthenticationInfo create(boolean isProxy,
+                              String host,
+                              int port,
+                              PasswordAuthentication pw) {
+        try {
+            return fiveArgCtr.newInstance(isProxy, host, port, pw);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return null;
+    }
+
+    /* Returns true if the NTLM implementation supports transparent
+     * authentication (try with the current users credentials before
+     * prompting for username and password, etc).
+     */
+    private static boolean supportsTransparentAuth(Method method) {
+        try {
+            return (Boolean)method.invoke(null);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return false;
+    }
+
+    /**
+     * Loads the NTLM authentiation implementation through reflection. If
+     * the class is present, then it must have the required constructors and
+     * method. Otherwise, it is considered an error.
+     */
+    @SuppressWarnings("unchecked")
+    private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() {
+        Class<? extends AuthenticationInfo> cl;
+        Constructor<? extends AuthenticationInfo> threeArg, fiveArg;
+        try {
+            cl = (Class<? extends AuthenticationInfo>)Class.forName(clazzStr, true, null);
+            if (cl != null) {
+                threeArg = cl.getConstructor(boolean.class,
+                                             URL.class,
+                                             PasswordAuthentication.class);
+                fiveArg = cl.getConstructor(boolean.class,
+                                            String.class,
+                                            int.class,
+                                            PasswordAuthentication.class);
+                supportsTA = cl.getDeclaredMethod(supportsTAStr);
+                return new NTLMAuthenticationProxy(threeArg,
+                                                   fiveArg);
+            }
+        } catch (ClassNotFoundException cnfe) {
+            finest(cnfe);
+        } catch (ReflectiveOperationException roe) {
+            throw new AssertionError(roe);
+        }
+
+        return null;
+    }
+
+    static void finest(Exception e) {
+        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+        logger.finest("NTLMAuthenticationProxy: " + e);
+    }
+}
--- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Sat Oct 03 01:22:26 2009 +0100
@@ -30,11 +30,14 @@
 import sun.net.www.HeaderParser;
 import sun.misc.BASE64Decoder;
 import sun.misc.BASE64Encoder;
+import sun.util.logging.PlatformLogger;
 
 import java.net.URL;
 import java.io.IOException;
 import java.net.Authenticator.RequestorType;
-
+import java.lang.reflect.Constructor;
+import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
+import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
 
 /**
  * NegotiateAuthentication:
@@ -49,9 +52,6 @@
 
     final private HttpCallerInfo hci;
 
-    static final char NEGOTIATE_AUTH = 'S';
-    static final char KERBEROS_AUTH = 'K';
-
     // These maps are used to manage the GSS availability for diffrent
     // hosts. The key for both maps is the host name.
     // <code>supported</code> is set when isSupported is checked,
@@ -68,11 +68,10 @@
     * @param hci a schemed object.
     */
     public NegotiateAuthentication(HttpCallerInfo hci) {
-        super(RequestorType.PROXY==hci.authType?
-                    PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
-                hci.scheme.equalsIgnoreCase("Negotiate")?
-                    NEGOTIATE_AUTH:KERBEROS_AUTH,
-                hci.url, "");
+        super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS,
+              hci.url,
+              "");
         this.hci = hci;
     }
 
@@ -249,13 +248,41 @@
         // The current implementation will make sure NegotiatorImpl is not
         // directly referenced when compiling, thus smooth the way of building
         // the J2SE platform where HttpURLConnection is a bootstrap class.
+        //
+        // Makes NegotiatorImpl, and the security classes it references, a
+        // runtime dependency rather than a static one.
 
-        Class clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl");
-        java.lang.reflect.Constructor c = clazz.getConstructor(HttpCallerInfo.class);
-        return (Negotiator) (c.newInstance(hci));
+        Class clazz;
+        Constructor c;
+        try {
+            clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null);
+            c = clazz.getConstructor(HttpCallerInfo.class);
+        } catch (ClassNotFoundException cnfe) {
+            finest(cnfe);
+            throw cnfe;
+        } catch (ReflectiveOperationException roe) {
+            // if the class is there then something seriously wrong if
+            // the constructor is not.
+            throw new AssertionError(roe);
+        }
+
+        try {
+            return (Negotiator) (c.newInstance(hci));
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+            Throwable t = roe.getCause();
+            if (t != null && t instanceof Exception)
+                finest((Exception)t);
+            throw roe;
+        }
     }
 
     abstract byte[] firstToken() throws IOException;
 
     abstract byte[] nextToken(byte[] in) throws IOException;
+
+    static void finest(Exception e) {
+        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+        logger.finest("NegotiateAuthentication: " + e);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.action;
+
+import java.security.Security;
+
+/**
+ * A convenience class for retrieving the boolean value of a security property
+ * as a privileged action.
+ *
+ * <p>An instance of this class can be used as the argument of
+ * <code>AccessController.doPrivileged</code>.
+ *
+ * <p>The following code retrieves the boolean value of the security
+ * property named <code>"prop"</code> as a privileged action: <p>
+ *
+ * <pre>
+ * boolean b = java.security.AccessController.doPrivileged
+ *              (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
+ * </pre>
+ *
+ */
+public class GetBooleanSecurityPropertyAction
+        implements java.security.PrivilegedAction<Boolean> {
+    private String theProp;
+
+    /**
+     * Constructor that takes the name of the security property whose boolean
+     * value needs to be determined.
+     *
+     * @param theProp the name of the security property
+     */
+    public GetBooleanSecurityPropertyAction(String theProp) {
+        this.theProp = theProp;
+    }
+
+    /**
+     * Determines the boolean value of the security property whose name was
+     * specified in the constructor.
+     *
+     * @return the <code>Boolean</code> value of the security property.
+     */
+    public Boolean run() {
+        boolean b = false;
+        try {
+            String value = Security.getProperty(theProp);
+            b = (value != null) && value.equalsIgnoreCase("true");
+        } catch (NullPointerException e) {}
+        return b;
+    }
+}
--- a/src/share/classes/sun/security/ec/ECDHKeyAgreement.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java	Sat Oct 03 01:22:26 2009 +0100
@@ -39,21 +39,6 @@
  */
 public final class ECDHKeyAgreement extends KeyAgreementSpi {
 
-    // flag indicating whether the native ECC implementation is present
-    private static boolean implementationPresent = true;
-    static {
-        try {
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    System.loadLibrary("sunecc");
-                    return null;
-                }
-            });
-        } catch (UnsatisfiedLinkError e) {
-            implementationPresent = false;
-        }
-    }
-
     // private key, if initialized
     private ECPrivateKey privateKey;
 
@@ -65,16 +50,12 @@
 
     /**
      * Constructs a new ECDHKeyAgreement.
-     *
-     * @exception ProviderException if the native ECC library is unavailable.
      */
     public ECDHKeyAgreement() {
-        if (!implementationPresent) {
-            throw new ProviderException("ECDH implementation is not available");
-        }
     }
 
     // see JCE spec
+    @Override
     protected void engineInit(Key key, SecureRandom random)
             throws InvalidKeyException {
         if (!(key instanceof PrivateKey)) {
@@ -86,6 +67,7 @@
     }
 
     // see JCE spec
+    @Override
     protected void engineInit(Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
             InvalidAlgorithmParameterException {
@@ -97,6 +79,7 @@
     }
 
     // see JCE spec
+    @Override
     protected Key engineDoPhase(Key key, boolean lastPhase)
             throws InvalidKeyException, IllegalStateException {
         if (privateKey == null) {
@@ -130,6 +113,7 @@
     }
 
     // see JCE spec
+    @Override
     protected byte[] engineGenerateSecret() throws IllegalStateException {
         if ((privateKey == null) || (publicValue == null)) {
             throw new IllegalStateException("Not initialized correctly");
@@ -150,6 +134,7 @@
     }
 
     // see JCE spec
+    @Override
     protected int engineGenerateSecret(byte[] sharedSecret, int
             offset) throws IllegalStateException, ShortBufferException {
         if (offset + secretLen > sharedSecret.length) {
@@ -162,6 +147,7 @@
     }
 
     // see JCE spec
+    @Override
     protected SecretKey engineGenerateSecret(String algorithm)
             throws IllegalStateException, NoSuchAlgorithmException,
             InvalidKeyException {
--- a/src/share/classes/sun/security/ec/ECDSASignature.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/ec/ECDSASignature.java	Sat Oct 03 01:22:26 2009 +0100
@@ -52,21 +52,6 @@
  */
 abstract class ECDSASignature extends SignatureSpi {
 
-    // flag indicating whether the native ECC implementation is present
-    private static boolean implementationPresent = true;
-    static {
-        try {
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    System.loadLibrary("sunecc");
-                    return null;
-                }
-            });
-        } catch (UnsatisfiedLinkError e) {
-            implementationPresent = false;
-        }
-    }
-
     // message digest implementation we use
     private final MessageDigest messageDigest;
 
@@ -88,24 +73,13 @@
      * @exception ProviderException if the native ECC library is unavailable.
      */
     ECDSASignature() {
-        if (!implementationPresent) {
-            throw new
-                ProviderException("ECDSA implementation is not available");
-        }
         messageDigest = null;
     }
 
     /**
      * Constructs a new ECDSASignature. Used by subclasses.
-     *
-     * @exception ProviderException if the native ECC library is unavailable.
      */
     ECDSASignature(String digestName) {
-        if (!implementationPresent) {
-            throw new
-                ProviderException("ECDSA implementation is not available");
-        }
-
         try {
             messageDigest = MessageDigest.getInstance(digestName);
         } catch (NoSuchAlgorithmException e) {
@@ -299,8 +273,8 @@
         byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID
         int keySize = params.getCurve().getField().getFieldSize();
 
-        // seed is twice the key size (in bytes)
-        byte[] seed = new byte[((keySize + 7) >> 3) * 2];
+        // seed is twice the key size (in bytes) plus 1
+        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
@@ -356,6 +330,7 @@
 
     // Convert the concatenation of R and S into their DER encoding
     private byte[] encodeSignature(byte[] signature) throws SignatureException {
+
         try {
 
             int n = signature.length >> 1;
--- a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java	Sat Oct 03 01:22:26 2009 +0100
@@ -46,20 +46,6 @@
  */
 public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
 
-    // flag indicating whether the native ECC implementation is present
-    private static boolean implementationPresent = true;
-    static {
-        try {
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    System.loadLibrary("sunecc");
-                    return null;
-                }
-            });
-        } catch (UnsatisfiedLinkError e) {
-            implementationPresent = false;
-        }
-    }
     private static final int KEY_SIZE_MIN = 112; // min bits (see ecc_impl.h)
     private static final int KEY_SIZE_MAX = 571; // max bits (see ecc_impl.h)
     private static final int KEY_SIZE_DEFAULT = 256;
@@ -75,13 +61,8 @@
 
     /**
      * Constructs a new ECKeyPairGenerator.
-     *
-     * @exception ProviderException if the native ECC library is unavailable.
      */
     public ECKeyPairGenerator() {
-        if (!implementationPresent) {
-            throw new ProviderException("EC implementation is not available");
-        }
         // initialize to default in case the app does not call initialize()
         initialize(KEY_SIZE_DEFAULT, null);
     }
@@ -133,8 +114,8 @@
         byte[] encodedParams =
             ECParameters.encodeParameters((ECParameterSpec)params);
 
-        // seed is twice the key size (in bytes)
-        byte[] seed = new byte[2 * ((keySize + 7) >> 3)];
+        // seed is twice the key size (in bytes) plus 1
+        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
--- a/src/share/classes/sun/security/ec/SunEC.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/ec/SunEC.java	Sat Oct 03 01:22:26 2009 +0100
@@ -39,7 +39,10 @@
  * via JNI to a C++ wrapper class which in turn calls C functions.
  * The Java classes are packaged into the signed sunec.jar in the JRE
  * extensions directory and the C++ and C functions are packaged into
- * libsunecc.so or sunecc.dll in the JRE native libraries directory.
+ * libsunec.so or sunec.dll in the JRE native libraries directory.
+ * If the native library is not present then this provider is registered
+ * with support for fewer ECC algorithms (KeyPairGenerator, Signature and
+ * KeyAgreement are omitted).
  *
  * @since   1.7
  */
@@ -47,6 +50,22 @@
 
     private static final long serialVersionUID = -2279741672933606418L;
 
+    // flag indicating whether the full EC implementation is present
+    // (when native library is absent then fewer EC algorithms are available)
+    private static boolean useFullImplementation = true;
+    static {
+        try {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("sunec"); // check for native library
+                    return null;
+                }
+            });
+        } catch (UnsatisfiedLinkError e) {
+            useFullImplementation = false;
+        }
+    }
+
     public SunEC() {
         super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
 
@@ -54,10 +73,10 @@
         // the provider. Otherwise, create a temporary map and use a
         // doPrivileged() call at the end to transfer the contents
         if (System.getSecurityManager() == null) {
-            SunECEntries.putEntries(this);
+            SunECEntries.putEntries(this, useFullImplementation);
         } else {
             Map<Object, Object> map = new HashMap<Object, Object>();
-            SunECEntries.putEntries(map);
+            SunECEntries.putEntries(map, useFullImplementation);
             AccessController.doPrivileged(new PutAllAction(this, map));
         }
     }
--- a/src/share/classes/sun/security/ec/SunECEntries.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/ec/SunECEntries.java	Sat Oct 03 01:22:26 2009 +0100
@@ -38,7 +38,93 @@
         // empty
     }
 
-    static void putEntries(Map<Object, Object> map) {
+    static void putEntries(Map<Object, Object> map,
+        boolean useFullImplementation) {
+
+        /*
+         *  Key Factory engine
+         */
+        map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory");
+        map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC");
+
+        map.put("KeyFactory.EC ImplementedIn", "Software");
+
+        /*
+         * Algorithm Parameter engine
+         */
+        map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
+        map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
+
+        map.put("AlgorithmParameters.EC KeySize", "256");
+
+        map.put("AlgorithmParameters.EC ImplementedIn", "Software");
+
+        map.put("AlgorithmParameters.EC SupportedCurves",
+
+            // A list comprising lists of curve names and object identifiers.
+            // '[' ( <curve-name> ',' )+ <curve-object-identifier> ']' '|'
+
+            // SEC 2 prime curves
+            "[secp112r1,1.3.132.0.6]|" +
+            "[secp112r2,1.3.132.0.7]|" +
+            "[secp128r1,1.3.132.0.28]|" +
+            "[secp128r2,1.3.132.0.29]|" +
+            "[secp160k1,1.3.132.0.9]|" +
+            "[secp160r1,1.3.132.0.8]|" +
+            "[secp160r2,1.3.132.0.30]|" +
+            "[secp192k1,1.3.132.0.31]|" +
+            "[secp192r1,NIST P-192,X9.62 prime192v1,1.2.840.10045.3.1.1]|" +
+            "[secp224k1,1.3.132.0.32]|" +
+            "[secp224r1,NIST P-224,1.3.132.0.33]|" +
+            "[secp256k1,1.3.132.0.10]|" +
+            "[secp256r1,NIST P-256,X9.62 prime256v1,1.2.840.10045.3.1.7]|" +
+            "[secp384r1,NIST P-384,1.3.132.0.34]|" +
+            "[secp521r1,NIST P-521,1.3.132.0.35]|" +
+
+            // ANSI X9.62 prime curves
+            "[X9.62 prime192v2,1.2.840.10045.3.1.2]|" +
+            "[X9.62 prime192v3,1.2.840.10045.3.1.3]|" +
+            "[X9.62 prime239v1,1.2.840.10045.3.1.4]|" +
+            "[X9.62 prime239v2,1.2.840.10045.3.1.5]|" +
+            "[X9.62 prime239v3,1.2.840.10045.3.1.6]|" +
+
+            // SEC 2 binary curves
+            "[sect113r1,1.3.132.0.4]|" +
+            "[sect113r2,1.3.132.0.5]|" +
+            "[sect131r1,1.3.132.0.22]|" +
+            "[sect131r2,1.3.132.0.23]|" +
+            "[sect163k1,NIST K-163,1.3.132.0.1]|" +
+            "[sect163r1,1.3.132.0.2]|" +
+            "[sect163r2,NIST B-163,1.3.132.0.15]|" +
+            "[sect193r1,1.3.132.0.24]|" +
+            "[sect193r2,1.3.132.0.25]|" +
+            "[sect233k1,NIST K-233,1.3.132.0.26]|" +
+            "[sect233r1,NIST B-233,1.3.132.0.27]|" +
+            "[sect239k1,1.3.132.0.3]|" +
+            "[sect283k1,NIST K-283,1.3.132.0.16]|" +
+            "[sect283r1,NIST B-283,1.3.132.0.17]|" +
+            "[sect409k1,NIST K-409,1.3.132.0.36]|" +
+            "[sect409r1,NIST B-409,1.3.132.0.37]|" +
+            "[sect571k1,NIST K-571,1.3.132.0.38]|" +
+            "[sect571r1,NIST B-571,1.3.132.0.39]|" +
+
+            // ANSI X9.62 binary curves
+            "[X9.62 c2tnb191v1,1.2.840.10045.3.0.5]|" +
+            "[X9.62 c2tnb191v2,1.2.840.10045.3.0.6]|" +
+            "[X9.62 c2tnb191v3,1.2.840.10045.3.0.7]|" +
+            "[X9.62 c2tnb239v1,1.2.840.10045.3.0.11]|" +
+            "[X9.62 c2tnb239v2,1.2.840.10045.3.0.12]|" +
+            "[X9.62 c2tnb239v3,1.2.840.10045.3.0.13]|" +
+            "[X9.62 c2tnb359v1,1.2.840.10045.3.0.18]|" +
+            "[X9.62 c2tnb431r1,1.2.840.10045.3.0.20]");
+
+        /*
+         * Register the algorithms below only when the full ECC implementation
+         * is available
+         */
+        if (!useFullImplementation) {
+            return;
+        }
 
         /*
          * Signature engines
@@ -62,48 +148,31 @@
         map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses);
 
+        map.put("Signature.SHA1withECDSA KeySize", "256");
+
+        map.put("Signature.NONEwithECDSA ImplementedIn", "Software");
+        map.put("Signature.SHA1withECDSA ImplementedIn", "Software");
+        map.put("Signature.SHA256withECDSA ImplementedIn", "Software");
+        map.put("Signature.SHA384withECDSA ImplementedIn", "Software");
+        map.put("Signature.SHA512withECDSA ImplementedIn", "Software");
+
         /*
          *  Key Pair Generator engine
          */
         map.put("KeyPairGenerator.EC", "sun.security.ec.ECKeyPairGenerator");
         map.put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
 
-        /*
-         *  Key Factory engine
-         */
-        map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory");
-        map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC");
+        map.put("KeyPairGenerator.EC KeySize", "256");
 
-        /*
-         * Algorithm Parameter engine
-         */
-        map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
-        map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
+        map.put("KeyPairGenerator.EC ImplementedIn", "Software");
 
         /*
          * Key Agreement engine
          */
         map.put("KeyAgreement.ECDH", "sun.security.ec.ECDHKeyAgreement");
+
         map.put("KeyAgreement.ECDH SupportedKeyClasses", ecKeyClasses);
 
-        /*
-         * Key sizes
-         */
-        map.put("Signature.SHA1withECDSA KeySize", "256");
-        map.put("KeyPairGenerator.EC KeySize", "256");
-        map.put("AlgorithmParameterGenerator.ECDSA KeySize", "256");
-
-        /*
-         * Implementation type: software or hardware
-         */
-        map.put("Signature.NONEwithECDSA ImplementedIn", "Software");
-        map.put("Signature.SHA1withECDSA ImplementedIn", "Software");
-        map.put("Signature.SHA256withECDSA ImplementedIn", "Software");
-        map.put("Signature.SHA384withECDSA ImplementedIn", "Software");
-        map.put("Signature.SHA512withECDSA ImplementedIn", "Software");
-        map.put("KeyPairGenerator.EC ImplementedIn", "Software");
-        map.put("KeyFactory.EC ImplementedIn", "Software");
         map.put("KeyAgreement.ECDH ImplementedIn", "Software");
-        map.put("AlgorithmParameters.EC ImplementedIn", "Software");
     }
 }
--- a/src/share/classes/sun/security/krb5/KrbKdcReq.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/krb5/KrbKdcReq.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Portions Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -149,6 +149,11 @@
                 send(realm,tempKdc,useTCP);
                 break;
             } catch (Exception e) {
+                if (DEBUG) {
+                    System.out.println(">>> KrbKdcReq send: error trying " +
+                            tempKdc);
+                    e.printStackTrace(System.out);
+                }
                 savedException = e;
             }
         }
@@ -179,10 +184,36 @@
         /*
          * Get port number for this KDC.
          */
-        StringTokenizer strTok = new StringTokenizer(tempKdc, ":");
-        String kdc = strTok.nextToken();
-        if (strTok.hasMoreTokens()) {
-            String portStr = strTok.nextToken();
+        String kdc = null;
+        String portStr = null;
+
+        if (tempKdc.charAt(0) == '[') {     // Explicit IPv6 in []
+            int pos = tempKdc.indexOf(']', 1);
+            if (pos == -1) {
+                throw new IOException("Illegal KDC: " + tempKdc);
+            }
+            kdc = tempKdc.substring(1, pos);
+            if (pos != tempKdc.length() - 1) {  // with port number
+                if (tempKdc.charAt(pos+1) != ':') {
+                    throw new IOException("Illegal KDC: " + tempKdc);
+                }
+                portStr = tempKdc.substring(pos+2);
+            }
+        } else {
+            int colon = tempKdc.indexOf(':');
+            if (colon == -1) {      // Hostname or IPv4 host only
+                kdc = tempKdc;
+            } else {
+                int nextColon = tempKdc.indexOf(':', colon+1);
+                if (nextColon > 0) {    // >=2 ":", IPv6 with no port
+                    kdc = tempKdc;
+                } else {                // 1 ":", hostname or IPv4 with port
+                    kdc = tempKdc.substring(0, colon);
+                    portStr = tempKdc.substring(colon+1);
+                }
+            }
+        }
+        if (portStr != null) {
             int tempPort = parsePositiveIntString(portStr);
             if (tempPort > 0)
                 port = tempPort;
--- a/src/share/classes/sun/security/provider/certpath/Builder.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/Builder.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,14 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
+import java.security.AccessController;
 import java.security.GeneralSecurityException;
 import java.security.cert.*;
 import java.util.*;
 
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.action.GetBooleanAction;
 import sun.security.util.Debug;
 import sun.security.x509.GeneralNames;
 import sun.security.x509.GeneralNameInterface;
@@ -64,9 +66,8 @@
      * Authority Information Access extension shall be enabled. Currently
      * disabled by default for compatibility reasons.
      */
-    final static boolean USE_AIA =
-        DistributionPointFetcher.getBooleanProperty
-            ("com.sun.security.enableAIAcaIssuers", false);
+    final static boolean USE_AIA = AccessController.doPrivileged
+        (new GetBooleanAction("com.sun.security.enableAIAcaIssuers"));
 
     /**
      * Initialize the builder with the input parameters.
--- a/src/share/classes/sun/security/provider/certpath/CertId.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/CertId.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,9 +25,11 @@
 
 package sun.security.provider.certpath;
 
-import java.io.*;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import sun.misc.HexDumpEncoder;
 import sun.security.x509.*;
@@ -54,21 +56,28 @@
 public class CertId {
 
     private static final boolean debug = false;
-    private AlgorithmId hashAlgId;
-    private byte[] issuerNameHash;
-    private byte[] issuerKeyHash;
-    private SerialNumber certSerialNumber;
+    private static final AlgorithmId SHA1_ALGID
+        = new AlgorithmId(AlgorithmId.SHA_oid);
+    private final AlgorithmId hashAlgId;
+    private final byte[] issuerNameHash;
+    private final byte[] issuerKeyHash;
+    private final SerialNumber certSerialNumber;
     private int myhash = -1; // hashcode for this CertId
 
     /**
      * Creates a CertId. The hash algorithm used is SHA-1.
      */
-    public CertId(X509CertImpl issuerCert, SerialNumber serialNumber)
-        throws Exception {
+    public CertId(X509Certificate issuerCert, SerialNumber serialNumber)
+        throws IOException {
 
         // compute issuerNameHash
-        MessageDigest md = MessageDigest.getInstance("SHA1");
-        hashAlgId = AlgorithmId.get("SHA1");
+        MessageDigest md = null;
+        try {
+            md = MessageDigest.getInstance("SHA1");
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new IOException("Unable to create CertId", nsae);
+        }
+        hashAlgId = SHA1_ALGID;
         md.update(issuerCert.getSubjectX500Principal().getEncoded());
         issuerNameHash = md.digest();
 
@@ -90,6 +99,7 @@
                 encoder.encode(issuerNameHash));
             System.out.println("issuerKeyHash is " +
                 encoder.encode(issuerKeyHash));
+            System.out.println("SerialNumber is " + serialNumber.getNumber());
         }
     }
 
@@ -97,7 +107,6 @@
      * Creates a CertId from its ASN.1 DER encoding.
      */
     public CertId(DerInputStream derIn) throws IOException {
-
         hashAlgId = AlgorithmId.parse(derIn.getDerValue());
         issuerNameHash = derIn.getOctetString();
         issuerKeyHash = derIn.getOctetString();
@@ -157,7 +166,7 @@
      *
      * @return the hashcode value.
      */
-    public int hashCode() {
+    @Override public int hashCode() {
         if (myhash == -1) {
             myhash = hashAlgId.hashCode();
             for (int i = 0; i < issuerNameHash.length; i++) {
@@ -180,8 +189,7 @@
      * @param other the object to test for equality with this object.
      * @return true if the objects are considered equal, false otherwise.
      */
-    public boolean equals(Object other) {
-
+    @Override public boolean equals(Object other) {
         if (this == other) {
             return true;
         }
@@ -203,7 +211,7 @@
     /**
      * Create a string representation of the CertId.
      */
-    public String toString() {
+    @Override public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("CertId \n");
         sb.append("Algorithm: " + hashAlgId.toString() +"\n");
--- a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Sat Oct 03 01:22:26 2009 +0100
@@ -80,6 +80,7 @@
         { false, false, false, false, false, false, true };
     private static final boolean[] ALL_REASONS =
         {true, true, true, true, true, true, true, true, true};
+    private boolean mOnlyEECert = false;
 
     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of CRLs
@@ -114,6 +115,12 @@
     CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
         Collection<X509Certificate> certs) throws CertPathValidatorException
     {
+        this(anchor, params, certs, false);
+    }
+
+    CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
+        Collection<X509Certificate> certs, boolean onlyEECert)
+        throws CertPathValidatorException {
         mAnchor = anchor;
         mParams = params;
         mStores = new ArrayList<CertStore>(params.getCertStores());
@@ -133,6 +140,7 @@
         }
         Date testDate = params.getDate();
         mCurrentTime = (testDate != null ? testDate : new Date());
+        mOnlyEECert = onlyEECert;
         init(false);
     }
 
@@ -264,6 +272,13 @@
                 " ---checking " + msg + "...");
         }
 
+        if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
+            if (debug != null) {
+                debug.println("Skipping revocation check, not end entity cert");
+            }
+            return;
+        }
+
         // reject circular dependencies - RFC 3280 is not explicit on how
         // to handle this, so we feel it is safest to reject them until
         // the issue is resolved in the PKIX WG.
--- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Sat Oct 03 01:22:26 2009 +0100
@@ -32,7 +32,7 @@
 import java.security.cert.*;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.action.GetPropertyAction;
+import sun.security.action.GetBooleanAction;
 import sun.security.util.Debug;
 import sun.security.util.DerOutputStream;
 import sun.security.x509.*;
@@ -62,28 +62,8 @@
      * extension shall be enabled. Currently disabled by default for
      * compatibility and legal reasons.
      */
-    private final static boolean USE_CRLDP =
-        getBooleanProperty("com.sun.security.enableCRLDP", false);
-
-    /**
-     * Return the value of the boolean System property propName.
-     */
-    public static boolean getBooleanProperty(String propName,
-            boolean defaultValue) {
-        // if set, require value of either true or false
-        String b = AccessController.doPrivileged(
-                new GetPropertyAction(propName));
-        if (b == null) {
-            return defaultValue;
-        } else if (b.equalsIgnoreCase("false")) {
-            return false;
-        } else if (b.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            throw new RuntimeException("Value of " + propName
-            + " must either be 'true' or 'false'");
-        }
-    }
+    private final static boolean USE_CRLDP = AccessController.doPrivileged
+        (new GetBooleanAction("com.sun.security.enableCRLDP"));
 
     // singleton instance
     private static final DistributionPointFetcher INSTANCE =
--- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Sat Oct 03 01:22:26 2009 +0100
@@ -82,6 +82,7 @@
     TrustAnchor trustAnchor;
     private Comparator<X509Certificate> comparator;
     private boolean searchAllCertStores = true;
+    private boolean onlyEECert = false;
 
     /**
      * Initialize the builder with the input parameters.
@@ -89,7 +90,8 @@
      * @param params the parameter set used to build a certification path
      */
     ForwardBuilder(PKIXBuilderParameters buildParams,
-        X500Principal targetSubjectDN, boolean searchAllCertStores)
+        X500Principal targetSubjectDN, boolean searchAllCertStores,
+        boolean onlyEECert)
     {
         super(buildParams, targetSubjectDN);
 
@@ -108,6 +110,7 @@
         }
         comparator = new PKIXCertComparator(trustedSubjectDNs);
         this.searchAllCertStores = searchAllCertStores;
+        this.onlyEECert = onlyEECert;
     }
 
     /**
@@ -875,8 +878,8 @@
             /* Check revocation if it is enabled */
             if (buildParams.isRevocationEnabled()) {
                 try {
-                    CrlRevocationChecker crlChecker =
-                        new CrlRevocationChecker(anchor, buildParams);
+                    CrlRevocationChecker crlChecker = new CrlRevocationChecker
+                        (anchor, buildParams, null, onlyEECert);
                     crlChecker.check(cert, anchor.getCAPublicKey(), true);
                 } catch (CertPathValidatorException cpve) {
                     if (debug != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/provider/certpath/OCSP.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.security.provider.certpath;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.HttpURLConnection;
+import java.security.cert.CertificateException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CRLReason;
+import java.security.cert.Extension;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static sun.security.provider.certpath.OCSPResponse.*;
+import sun.security.util.Debug;
+import sun.security.x509.AccessDescription;
+import sun.security.x509.AuthorityInfoAccessExtension;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNameInterface;
+import sun.security.x509.URIName;
+import sun.security.x509.X509CertImpl;
+
+/**
+ * This is a class that checks the revocation status of a certificate(s) using
+ * OCSP. It is not a PKIXCertPathChecker and therefore can be used outside of
+ * the CertPathValidator framework. It is useful when you want to
+ * just check the revocation status of a certificate, and you don't want to
+ * incur the overhead of validating all of the certificates in the
+ * associated certificate chain.
+ *
+ * @author Sean Mullan
+ */
+public final class OCSP {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+
+    private OCSP() {}
+
+    /**
+     * Obtains the revocation status of a certificate using OCSP using the most
+     * common defaults. The OCSP responder URI is retrieved from the
+     * certificate's AIA extension. The OCSP responder certificate is assumed
+     * to be the issuer's certificate (or issued by the issuer CA).
+     *
+     * @param cert the certificate to be checked
+     * @param issuerCert the issuer certificate
+     * @return the RevocationStatus
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    public static RevocationStatus check(X509Certificate cert,
+        X509Certificate issuerCert)
+        throws IOException, CertPathValidatorException {
+        CertId certId = null;
+        URI responderURI = null;
+        try {
+            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+            responderURI = getResponderURI(certImpl);
+            if (responderURI == null) {
+                throw new CertPathValidatorException
+                    ("No OCSP Responder URI in certificate");
+            }
+            certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ce);
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+        OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+            responderURI, issuerCert, null);
+        return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+    }
+
+    /**
+     * Obtains the revocation status of a certificate using OCSP.
+     *
+     * @param cert the certificate to be checked
+     * @param issuerCert the issuer certificate
+     * @param responderURI the URI of the OCSP responder
+     * @param responderCert the OCSP responder's certificate
+     * @param date the time the validity of the OCSP responder's certificate
+     *    should be checked against. If null, the current time is used.
+     * @return the RevocationStatus
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    public static RevocationStatus check(X509Certificate cert,
+        X509Certificate issuerCert, URI responderURI, X509Certificate
+        responderCert, Date date)
+        throws IOException, CertPathValidatorException {
+        CertId certId = null;
+        try {
+            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+            certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ce);
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+        OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+            responderURI, responderCert, date);
+        return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+    }
+
+    /**
+     * Checks the revocation status of a list of certificates using OCSP.
+     *
+     * @param certs the CertIds to be checked
+     * @param responderURI the URI of the OCSP responder
+     * @param responderCert the OCSP responder's certificate
+     * @param date the time the validity of the OCSP responder's certificate
+     *    should be checked against. If null, the current time is used.
+     * @return the OCSPResponse
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    static OCSPResponse check(List<CertId> certIds, URI responderURI,
+        X509Certificate responderCert, Date date)
+        throws IOException, CertPathValidatorException {
+
+        byte[] bytes = null;
+        try {
+            OCSPRequest request = new OCSPRequest(certIds);
+            bytes = request.encodeBytes();
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+
+        InputStream in = null;
+        OutputStream out = null;
+        byte[] response = null;
+        try {
+            URL url = responderURI.toURL();
+            if (debug != null) {
+                debug.println("connecting to OCSP service at: " + url);
+            }
+            HttpURLConnection con = (HttpURLConnection)url.openConnection();
+            con.setDoOutput(true);
+            con.setDoInput(true);
+            con.setRequestMethod("POST");
+            con.setRequestProperty
+                ("Content-type", "application/ocsp-request");
+            con.setRequestProperty
+                ("Content-length", String.valueOf(bytes.length));
+            out = con.getOutputStream();
+            out.write(bytes);
+            out.flush();
+            // Check the response
+            if (debug != null &&
+                con.getResponseCode() != HttpURLConnection.HTTP_OK) {
+                debug.println("Received HTTP error: " + con.getResponseCode()
+                    + " - " + con.getResponseMessage());
+            }
+            in = con.getInputStream();
+            int contentLength = con.getContentLength();
+            if (contentLength == -1) {
+                contentLength = Integer.MAX_VALUE;
+            }
+            response = new byte[contentLength > 2048 ? 2048 : contentLength];
+            int total = 0;
+            while (total < contentLength) {
+                int count = in.read(response, total, response.length - total);
+                if (count < 0)
+                    break;
+
+                total += count;
+                if (total >= response.length && total < contentLength) {
+                    response = Arrays.copyOf(response, total * 2);
+                }
+            }
+            response = Arrays.copyOf(response, total);
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException ioe) {
+                    throw ioe;
+                }
+            }
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException ioe) {
+                    throw ioe;
+                }
+            }
+        }
+
+        OCSPResponse ocspResponse = null;
+        try {
+            ocspResponse = new OCSPResponse(response, date, responderCert);
+        } catch (IOException ioe) {
+            // response decoding exception
+            throw new CertPathValidatorException(ioe);
+        }
+        if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) {
+            throw new CertPathValidatorException
+                ("OCSP response error: " + ocspResponse.getResponseStatus());
+        }
+
+        // Check that the response includes a response for all of the
+        // certs that were supplied in the request
+        for (CertId certId : certIds) {
+            SingleResponse sr = ocspResponse.getSingleResponse(certId);
+            if (sr == null) {
+                if (debug != null) {
+                    debug.println("No response found for CertId: " + certId);
+                }
+                throw new CertPathValidatorException(
+                    "OCSP response does not include a response for a " +
+                    "certificate supplied in the OCSP request");
+            }
+            if (debug != null) {
+                debug.println("Status of certificate (with serial number " +
+                    certId.getSerialNumber() + ") is: " + sr.getCertStatus());
+            }
+        }
+        return ocspResponse;
+    }
+
+    /**
+     * Returns the URI of the OCSP Responder as specified in the
+     * certificate's Authority Information Access extension, or null if
+     * not specified.
+     *
+     * @param cert the certificate
+     * @return the URI of the OCSP Responder, or null if not specified
+     */
+    public static URI getResponderURI(X509Certificate cert) {
+        try {
+            return getResponderURI(X509CertImpl.toImpl(cert));
+        } catch (CertificateException ce) {
+            // treat this case as if the cert had no extension
+            return null;
+        }
+    }
+
+    static URI getResponderURI(X509CertImpl certImpl) {
+
+        // Examine the certificate's AuthorityInfoAccess extension
+        AuthorityInfoAccessExtension aia =
+            certImpl.getAuthorityInfoAccessExtension();
+        if (aia == null) {
+            return null;
+        }
+
+        List<AccessDescription> descriptions = aia.getAccessDescriptions();
+        for (AccessDescription description : descriptions) {
+            if (description.getAccessMethod().equals(
+                AccessDescription.Ad_OCSP_Id)) {
+
+                GeneralName generalName = description.getAccessLocation();
+                if (generalName.getType() == GeneralNameInterface.NAME_URI) {
+                    URIName uri = (URIName) generalName.getName();
+                    return uri.getURI();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * The Revocation Status of a certificate.
+     */
+    public static interface RevocationStatus {
+        public enum CertStatus { GOOD, REVOKED, UNKNOWN };
+
+        /**
+         * Returns the revocation status.
+         */
+        CertStatus getCertStatus();
+        /**
+         * Returns the time when the certificate was revoked, or null
+         * if it has not been revoked.
+         */
+        Date getRevocationTime();
+        /**
+         * Returns the reason the certificate was revoked, or null if it
+         * has not been revoked.
+         */
+        CRLReason getRevocationReason();
+
+        /**
+         * Returns a Map of additional extensions.
+         */
+        Map<String, Extension> getSingleExtensions();
+    }
+}
--- a/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Sat Oct 03 01:22:26 2009 +0100
@@ -25,19 +25,20 @@
 
 package sun.security.provider.certpath;
 
-import java.io.*;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.util.*;
 import java.security.AccessController;
-import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.security.Security;
 import java.security.cert.*;
 import java.security.cert.CertPathValidatorException.BasicReason;
-import java.net.*;
+import java.net.URI;
+import java.net.URISyntaxException;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.util.*;
+import static sun.security.provider.certpath.OCSP.*;
+import sun.security.util.Debug;
 import sun.security.x509.*;
 
 /**
@@ -50,27 +51,18 @@
  */
 class OCSPChecker extends PKIXCertPathChecker {
 
-    public static final String OCSP_ENABLE_PROP = "ocsp.enable";
-    public static final String OCSP_URL_PROP = "ocsp.responderURL";
-    public static final String OCSP_CERT_SUBJECT_PROP =
+    static final String OCSP_ENABLE_PROP = "ocsp.enable";
+    static final String OCSP_URL_PROP = "ocsp.responderURL";
+    static final String OCSP_CERT_SUBJECT_PROP =
         "ocsp.responderCertSubjectName";
-    public static final String OCSP_CERT_ISSUER_PROP =
-        "ocsp.responderCertIssuerName";
-    public static final String OCSP_CERT_NUMBER_PROP =
+    static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
+    static final String OCSP_CERT_NUMBER_PROP =
         "ocsp.responderCertSerialNumber";
 
     private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
     private static final Debug DEBUG = Debug.getInstance("certpath");
     private static final boolean dump = false;
 
-    // Supported extensions
-    private static final int OCSP_NONCE_DATA[] =
-        { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2 };
-    private static final ObjectIdentifier OCSP_NONCE_OID;
-    static {
-        OCSP_NONCE_OID = ObjectIdentifier.newInternal(OCSP_NONCE_DATA);
-    }
-
     private int remainingCerts;
 
     private X509Certificate[] certs;
@@ -79,19 +71,26 @@
 
     private PKIXParameters pkixParams;
 
+    private boolean onlyEECert = false;
+
     /**
      * Default Constructor
      *
      * @param certPath the X509 certification path
      * @param pkixParams the input PKIX parameter set
-     * @exception CertPathValidatorException Exception thrown if cert path
-     * does not validate.
+     * @throws CertPathValidatorException if OCSPChecker can not be created
      */
     OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
         throws CertPathValidatorException {
+        this(certPath, pkixParams, false);
+    }
+
+    OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
+        throws CertPathValidatorException {
 
         this.cp = certPath;
         this.pkixParams = pkixParams;
+        this.onlyEECert = onlyEECert;
         List<? extends Certificate> tmp = cp.getCertificates();
         certs = tmp.toArray(new X509Certificate[tmp.size()]);
         init(false);
@@ -101,6 +100,7 @@
      * Initializes the internal state of the checker from parameters
      * specified in the constructor
      */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (!forward) {
             remainingCerts = certs.length + 1;
@@ -110,11 +110,11 @@
         }
     }
 
-    public boolean isForwardCheckingSupported() {
+    @Override public boolean isForwardCheckingSupported() {
         return false;
     }
 
-    public Set<String> getSupportedExtensions() {
+    @Override public Set<String> getSupportedExtensions() {
         return Collections.<String>emptySet();
     }
 
@@ -127,300 +127,233 @@
      * @exception CertPathValidatorException Exception is thrown if the
      *            certificate has been revoked.
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresolvedCritExts)
         throws CertPathValidatorException {
 
-        InputStream in = null;
-        OutputStream out = null;
-
         // Decrement the certificate counter
         remainingCerts--;
 
+        X509CertImpl currCertImpl = null;
         try {
-            X509Certificate responderCert = null;
-            boolean seekResponderCert = false;
-            X500Principal responderSubjectName = null;
-            X500Principal responderIssuerName = null;
-            BigInteger responderSerialNumber = null;
+            currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
 
-            boolean seekIssuerCert = true;
-            X509CertImpl issuerCertImpl = null;
-            X509CertImpl currCertImpl =
-                X509CertImpl.toImpl((X509Certificate)cert);
+        if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
+            if (DEBUG != null) {
+                DEBUG.println("Skipping revocation check, not end entity cert");
+            }
+            return;
+        }
 
-            /*
-             * OCSP security property values, in the following order:
-             *   1. ocsp.responderURL
-             *   2. ocsp.responderCertSubjectName
-             *   3. ocsp.responderCertIssuerName
-             *   4. ocsp.responderCertSerialNumber
-             */
-            String[] properties = getOCSPProperties();
+        /*
+         * OCSP security property values, in the following order:
+         *   1. ocsp.responderURL
+         *   2. ocsp.responderCertSubjectName
+         *   3. ocsp.responderCertIssuerName
+         *   4. ocsp.responderCertSerialNumber
+         */
+        // should cache these properties to avoid calling every time?
+        String[] properties = getOCSPProperties();
 
-            // Check whether OCSP is feasible before seeking cert information
-            URL url = getOCSPServerURL(currCertImpl, properties);
+        // Check whether OCSP is feasible before seeking cert information
+        URI uri = getOCSPServerURI(currCertImpl, properties[0]);
 
-            // When responder's subject name is set then the issuer/serial
-            // properties are ignored
-            if (properties[1] != null) {
-                responderSubjectName = new X500Principal(properties[1]);
+        // When responder's subject name is set then the issuer/serial
+        // properties are ignored
+        X500Principal responderSubjectName = null;
+        X500Principal responderIssuerName = null;
+        BigInteger responderSerialNumber = null;
+        if (properties[1] != null) {
+            responderSubjectName = new X500Principal(properties[1]);
+        } else if (properties[2] != null && properties[3] != null) {
+            responderIssuerName = new X500Principal(properties[2]);
+            // remove colon or space separators
+            String value = stripOutSeparators(properties[3]);
+            responderSerialNumber = new BigInteger(value, 16);
+        } else if (properties[2] != null || properties[3] != null) {
+            throw new CertPathValidatorException(
+                "Must specify both ocsp.responderCertIssuerName and " +
+                "ocsp.responderCertSerialNumber properties");
+        }
 
-            } else if (properties[2] != null && properties[3] != null) {
-                responderIssuerName = new X500Principal(properties[2]);
-                // remove colon or space separators
-                String value = stripOutSeparators(properties[3]);
-                responderSerialNumber = new BigInteger(value, 16);
+        // If the OCSP responder cert properties are set then the
+        // identified cert must be located in the trust anchors or
+        // in the cert stores.
+        boolean seekResponderCert = false;
+        if (responderSubjectName != null || responderIssuerName != null) {
+            seekResponderCert = true;
+        }
 
-            } else if (properties[2] != null || properties[3] != null) {
-                throw new CertPathValidatorException(
-                    "Must specify both ocsp.responderCertIssuerName and " +
-                    "ocsp.responderCertSerialNumber properties");
+        // Set the issuer certificate to the next cert in the chain
+        // (unless we're processing the final cert).
+        X509Certificate issuerCert = null;
+        boolean seekIssuerCert = true;
+        X509Certificate responderCert = null;
+        if (remainingCerts < certs.length) {
+            issuerCert = certs[remainingCerts];
+            seekIssuerCert = false; // done
+
+            // By default, the OCSP responder's cert is the same as the
+            // issuer of the cert being validated.
+            if (!seekResponderCert) {
+                responderCert = issuerCert;
+                if (DEBUG != null) {
+                    DEBUG.println("Responder's certificate is the same " +
+                        "as the issuer of the certificate being validated");
+                }
+            }
+        }
+
+        // Check anchor certs for:
+        //    - the issuer cert (of the cert being validated)
+        //    - the OCSP responder's cert
+        if (seekIssuerCert || seekResponderCert) {
+
+            if (DEBUG != null && seekResponderCert) {
+                DEBUG.println("Searching trust anchors for responder's " +
+                    "certificate");
             }
 
-            // If the OCSP responder cert properties are set then the
-            // identified cert must be located in the trust anchors or
-            // in the cert stores.
-            if (responderSubjectName != null || responderIssuerName != null) {
-                seekResponderCert = true;
+            // Extract the anchor certs
+            Iterator<TrustAnchor> anchors
+                = pkixParams.getTrustAnchors().iterator();
+            if (!anchors.hasNext()) {
+                throw new CertPathValidatorException(
+                    "Must specify at least one trust anchor");
             }
 
-            // Set the issuer certificate to the next cert in the chain
-            // (unless we're processing the final cert).
-            if (remainingCerts < certs.length) {
-                issuerCertImpl = X509CertImpl.toImpl(certs[remainingCerts]);
-                seekIssuerCert = false; // done
+            X500Principal certIssuerName =
+                currCertImpl.getIssuerX500Principal();
+            while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
 
-                // By default, the OCSP responder's cert is the same as the
-                // issuer of the cert being validated.
-                if (! seekResponderCert) {
-                    responderCert = certs[remainingCerts];
-                    if (DEBUG != null) {
-                        DEBUG.println("Responder's certificate is the same " +
-                            "as the issuer of the certificate being validated");
+                TrustAnchor anchor = anchors.next();
+                X509Certificate anchorCert = anchor.getTrustedCert();
+                X500Principal anchorSubjectName =
+                    anchorCert.getSubjectX500Principal();
+
+                if (dump) {
+                    System.out.println("Issuer DN is " + certIssuerName);
+                    System.out.println("Subject DN is " + anchorSubjectName);
+                }
+
+                // Check if anchor cert is the issuer cert
+                if (seekIssuerCert &&
+                    certIssuerName.equals(anchorSubjectName)) {
+
+                    issuerCert = anchorCert;
+                    seekIssuerCert = false; // done
+
+                    // By default, the OCSP responder's cert is the same as
+                    // the issuer of the cert being validated.
+                    if (!seekResponderCert && responderCert == null) {
+                        responderCert = anchorCert;
+                        if (DEBUG != null) {
+                            DEBUG.println("Responder's certificate is the" +
+                                " same as the issuer of the certificate " +
+                                "being validated");
+                        }
+                    }
+                }
+
+                // Check if anchor cert is the responder cert
+                if (seekResponderCert) {
+                    // Satisfy the responder subject name property only, or
+                    // satisfy the responder issuer name and serial number
+                    // properties only
+                    if ((responderSubjectName != null &&
+                         responderSubjectName.equals(anchorSubjectName)) ||
+                        (responderIssuerName != null &&
+                         responderSerialNumber != null &&
+                         responderIssuerName.equals(
+                         anchorCert.getIssuerX500Principal()) &&
+                         responderSerialNumber.equals(
+                         anchorCert.getSerialNumber()))) {
+
+                        responderCert = anchorCert;
+                        seekResponderCert = false; // done
                     }
                 }
             }
+            if (issuerCert == null) {
+                throw new CertPathValidatorException(
+                    "No trusted certificate for " + currCertImpl.getIssuerDN());
+            }
 
-            // Check anchor certs for:
-            //    - the issuer cert (of the cert being validated)
-            //    - the OCSP responder's cert
-            if (seekIssuerCert || seekResponderCert) {
-
-                if (DEBUG != null && seekResponderCert) {
-                    DEBUG.println("Searching trust anchors for responder's " +
+            // Check cert stores if responder cert has not yet been found
+            if (seekResponderCert) {
+                if (DEBUG != null) {
+                    DEBUG.println("Searching cert stores for responder's " +
                         "certificate");
                 }
-
-                // Extract the anchor certs
-                Iterator anchors = pkixParams.getTrustAnchors().iterator();
-                if (! anchors.hasNext()) {
-                    throw new CertPathValidatorException(
-                        "Must specify at least one trust anchor");
+                X509CertSelector filter = null;
+                if (responderSubjectName != null) {
+                    filter = new X509CertSelector();
+                    filter.setSubject(responderSubjectName);
+                } else if (responderIssuerName != null &&
+                    responderSerialNumber != null) {
+                    filter = new X509CertSelector();
+                    filter.setIssuer(responderIssuerName);
+                    filter.setSerialNumber(responderSerialNumber);
                 }
-
-                X500Principal certIssuerName =
-                    currCertImpl.getIssuerX500Principal();
-                while (anchors.hasNext() &&
-                        (seekIssuerCert || seekResponderCert)) {
-
-                    TrustAnchor anchor = (TrustAnchor)anchors.next();
-                    X509Certificate anchorCert = anchor.getTrustedCert();
-                    X500Principal anchorSubjectName =
-                        anchorCert.getSubjectX500Principal();
-
-                    if (dump) {
-                        System.out.println("Issuer DN is " + certIssuerName);
-                        System.out.println("Subject DN is " +
-                            anchorSubjectName);
-                    }
-
-                    // Check if anchor cert is the issuer cert
-                    if (seekIssuerCert &&
-                        certIssuerName.equals(anchorSubjectName)) {
-
-                        issuerCertImpl = X509CertImpl.toImpl(anchorCert);
-                        seekIssuerCert = false; // done
-
-                        // By default, the OCSP responder's cert is the same as
-                        // the issuer of the cert being validated.
-                        if (! seekResponderCert && responderCert == null) {
-                            responderCert = anchorCert;
+                if (filter != null) {
+                    List<CertStore> certStores = pkixParams.getCertStores();
+                    for (CertStore certStore : certStores) {
+                        Iterator i = null;
+                        try {
+                            i = certStore.getCertificates(filter).iterator();
+                        } catch (CertStoreException cse) {
+                            // ignore and try next certStore
                             if (DEBUG != null) {
-                                DEBUG.println("Responder's certificate is the" +
-                                    " same as the issuer of the certificate " +
-                                    "being validated");
+                                DEBUG.println("CertStore exception:" + cse);
                             }
+                            continue;
                         }
-                    }
-
-                    // Check if anchor cert is the responder cert
-                    if (seekResponderCert) {
-                        // Satisfy the responder subject name property only, or
-                        // satisfy the responder issuer name and serial number
-                        // properties only
-                        if ((responderSubjectName != null &&
-                             responderSubjectName.equals(anchorSubjectName)) ||
-                            (responderIssuerName != null &&
-                             responderSerialNumber != null &&
-                             responderIssuerName.equals(
-                                anchorCert.getIssuerX500Principal()) &&
-                             responderSerialNumber.equals(
-                                anchorCert.getSerialNumber()))) {
-
-                            responderCert = anchorCert;
+                        if (i.hasNext()) {
+                            responderCert = (X509Certificate) i.next();
                             seekResponderCert = false; // done
-                        }
-                    }
-                }
-                if (issuerCertImpl == null) {
-                    throw new CertPathValidatorException(
-                        "No trusted certificate for " +
-                        currCertImpl.getIssuerDN());
-                }
-
-                // Check cert stores if responder cert has not yet been found
-                if (seekResponderCert) {
-                    if (DEBUG != null) {
-                        DEBUG.println("Searching cert stores for responder's " +
-                            "certificate");
-                    }
-                    X509CertSelector filter = null;
-                    if (responderSubjectName != null) {
-                        filter = new X509CertSelector();
-                        filter.setSubject(responderSubjectName.getName());
-                    } else if (responderIssuerName != null &&
-                        responderSerialNumber != null) {
-                        filter = new X509CertSelector();
-                        filter.setIssuer(responderIssuerName.getName());
-                        filter.setSerialNumber(responderSerialNumber);
-                    }
-                    if (filter != null) {
-                        List<CertStore> certStores = pkixParams.getCertStores();
-                        for (CertStore certStore : certStores) {
-                            Iterator i =
-                                certStore.getCertificates(filter).iterator();
-                            if (i.hasNext()) {
-                                responderCert = (X509Certificate) i.next();
-                                seekResponderCert = false; // done
-                                break;
-                            }
+                            break;
                         }
                     }
                 }
             }
+        }
 
-            // Could not find the certificate identified in the OCSP properties
-            if (seekResponderCert) {
-                throw new CertPathValidatorException(
-                    "Cannot find the responder's certificate " +
-                    "(set using the OCSP security properties).");
-            }
+        // Could not find the certificate identified in the OCSP properties
+        if (seekResponderCert) {
+            throw new CertPathValidatorException(
+                "Cannot find the responder's certificate " +
+                "(set using the OCSP security properties).");
+        }
 
-            // Construct an OCSP Request
-            OCSPRequest ocspRequest =
-                new OCSPRequest(currCertImpl, issuerCertImpl);
+        CertId certId = null;
+        OCSPResponse response = null;
+        try {
+            certId = new CertId
+                (issuerCert, currCertImpl.getSerialNumberObject());
+            response = OCSP.check(Collections.singletonList(certId), uri,
+                responderCert, pkixParams.getDate());
+        } catch (IOException ioe) {
+            // should allow this to pass if network failures are acceptable
+            throw new CertPathValidatorException
+                ("Unable to send OCSP request", ioe);
+        }
 
-            // Use the URL to the OCSP service that was created earlier
-            HttpURLConnection con = (HttpURLConnection)url.openConnection();
-            if (DEBUG != null) {
-                DEBUG.println("connecting to OCSP service at: " + url);
-            }
-
-            // Indicate that both input and output will be performed,
-            // that the method is POST, and that the content length is
-            // the length of the byte array
-
-            con.setDoOutput(true);
-            con.setDoInput(true);
-            con.setRequestMethod("POST");
-            con.setRequestProperty("Content-type", "application/ocsp-request");
-            byte[] bytes = ocspRequest.encodeBytes();
-            CertId certId = ocspRequest.getCertId();
-
-            con.setRequestProperty("Content-length",
-                String.valueOf(bytes.length));
-            out = con.getOutputStream();
-            out.write(bytes);
-            out.flush();
-
-            // Check the response
-            if (DEBUG != null &&
-                con.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                DEBUG.println("Received HTTP error: " + con.getResponseCode() +
-                    " - " + con.getResponseMessage());
-            }
-            in = con.getInputStream();
-
-            byte[] response = null;
-            int total = 0;
-            int contentLength = con.getContentLength();
-            if (contentLength != -1) {
-                response = new byte[contentLength];
-            } else {
-                response = new byte[2048];
-                contentLength = Integer.MAX_VALUE;
-            }
-
-            while (total < contentLength) {
-                int count = in.read(response, total, response.length - total);
-                if (count < 0)
-                    break;
-
-                total += count;
-                if (total >= response.length && total < contentLength) {
-                    response = Arrays.copyOf(response, total * 2);
-                }
-            }
-            response = Arrays.copyOf(response, total);
-
-            OCSPResponse ocspResponse = new OCSPResponse(response, pkixParams,
-                responderCert);
-            // Check that response applies to the cert that was supplied
-            if (! certId.equals(ocspResponse.getCertId())) {
-                throw new CertPathValidatorException(
-                    "Certificate in the OCSP response does not match the " +
-                    "certificate supplied in the OCSP request.");
-            }
-            SerialNumber serialNumber = currCertImpl.getSerialNumberObject();
-            int certOCSPStatus = ocspResponse.getCertStatus(serialNumber);
-
-            if (DEBUG != null) {
-                DEBUG.println("Status of certificate (with serial number " +
-                    serialNumber.getNumber() + ") is: " +
-                    OCSPResponse.certStatusToText(certOCSPStatus));
-            }
-
-            if (certOCSPStatus == OCSPResponse.CERT_STATUS_REVOKED) {
-                Throwable t = new CertificateRevokedException(
-                        ocspResponse.getRevocationTime(),
-                        ocspResponse.getRevocationReason(),
-                        responderCert.getSubjectX500Principal(),
-                        ocspResponse.getSingleExtensions());
-                throw new CertPathValidatorException(t.getMessage(), t,
-                        null, -1, BasicReason.REVOKED);
-
-            } else if (certOCSPStatus == OCSPResponse.CERT_STATUS_UNKNOWN) {
-                throw new CertPathValidatorException(
-                    "Certificate's revocation status is unknown", null, cp,
-                    remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-            }
-        } catch (Exception e) {
-            throw new CertPathValidatorException(e);
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException ioe) {
-                    throw new CertPathValidatorException(ioe);
-                }
-            }
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException ioe) {
-                    throw new CertPathValidatorException(ioe);
-                }
-            }
+        RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
+        RevocationStatus.CertStatus certStatus = rs.getCertStatus();
+        if (certStatus == RevocationStatus.CertStatus.REVOKED) {
+            Throwable t = new CertificateRevokedException(
+                rs.getRevocationTime(), rs.getRevocationReason(),
+                responderCert.getSubjectX500Principal(),
+                rs.getSingleExtensions());
+            throw new CertPathValidatorException(t.getMessage(), t,
+                null, -1, BasicReason.REVOKED);
+        } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
+            throw new CertPathValidatorException(
+                "Certificate's revocation status is unknown", null, cp,
+                remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
         }
     }
 
@@ -431,20 +364,18 @@
      *   3. ocsp.responderCertIssuerName
      *   4. ocsp.responderCertSerialNumber
      */
-    private static URL getOCSPServerURL(X509CertImpl currCertImpl,
-        String[] properties)
-        throws CertificateParsingException, CertPathValidatorException {
+    private static URI getOCSPServerURI(X509CertImpl currCertImpl,
+        String responderURL) throws CertPathValidatorException {
 
-        if (properties[0] != null) {
-           try {
-                return new URL(properties[0]);
-           } catch (java.net.MalformedURLException e) {
+        if (responderURL != null) {
+            try {
+                return new URI(responderURL);
+            } catch (URISyntaxException e) {
                 throw new CertPathValidatorException(e);
-           }
+            }
         }
 
         // Examine the certificate's AuthorityInfoAccess extension
-
         AuthorityInfoAccessExtension aia =
             currCertImpl.getAuthorityInfoAccessExtension();
         if (aia == null) {
@@ -459,13 +390,8 @@
 
                 GeneralName generalName = description.getAccessLocation();
                 if (generalName.getType() == GeneralNameInterface.NAME_URI) {
-                    try {
-                        URIName uri = (URIName) generalName.getName();
-                        return (new URL(uri.getName()));
-
-                    } catch (java.net.MalformedURLException e) {
-                        throw new CertPathValidatorException(e);
-                    }
+                    URIName uri = (URIName) generalName.getName();
+                    return uri.getURI();
                 }
             }
         }
--- a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,9 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
-import java.security.cert.CertPathValidatorException;
+import java.util.Collections;
+import java.util.List;
 import sun.misc.HexDumpEncoder;
-import sun.security.x509.*;
 import sun.security.util.*;
 
 /**
@@ -77,47 +77,33 @@
     private static final Debug debug = Debug.getInstance("certpath");
     private static final boolean dump = false;
 
-    // Serial number of the certificates to be checked for revocation
-    private SerialNumber serialNumber;
-
-    // Issuer's certificate (for computing certId hash values)
-    private X509CertImpl issuerCert;
-
-    // CertId of the certificate to be checked
-    private CertId certId = null;
+    // List of request CertIds
+    private final List<CertId> certIds;
 
     /*
      * Constructs an OCSPRequest. This constructor is used
      * to construct an unsigned OCSP Request for a single user cert.
      */
-    // used by OCSPChecker
-    OCSPRequest(X509CertImpl userCert, X509CertImpl issuerCert)
-        throws CertPathValidatorException {
-
-        if (issuerCert == null) {
-            throw new CertPathValidatorException("Null IssuerCertificate");
-        }
-        this.issuerCert = issuerCert;
-        serialNumber = userCert.getSerialNumberObject();
+    OCSPRequest(CertId certId) {
+        this.certIds = Collections.singletonList(certId);
     }
 
-    // used by OCSPChecker
+    OCSPRequest(List<CertId> certIds) {
+        this.certIds = certIds;
+    }
+
     byte[] encodeBytes() throws IOException {
 
         // encode tbsRequest
         DerOutputStream tmp = new DerOutputStream();
-        DerOutputStream derSingleReqList  = new DerOutputStream();
-        SingleRequest singleRequest = null;
-
-        try {
-            singleRequest = new SingleRequest(issuerCert, serialNumber);
-        } catch (Exception e) {
-            throw new IOException("Error encoding OCSP request");
+        DerOutputStream requestsOut = new DerOutputStream();
+        for (CertId certId : certIds) {
+            DerOutputStream certIdOut = new DerOutputStream();
+            certId.encode(certIdOut);
+            requestsOut.write(DerValue.tag_Sequence, certIdOut);
         }
 
-        certId = singleRequest.getCertId();
-        singleRequest.encode(derSingleReqList);
-        tmp.write(DerValue.tag_Sequence, derSingleReqList);
+        tmp.write(DerValue.tag_Sequence, requestsOut);
         // No extensions supported
         DerOutputStream tbsRequest = new DerOutputStream();
         tbsRequest.write(DerValue.tag_Sequence, tmp);
@@ -130,35 +116,14 @@
 
         if (dump) {
             HexDumpEncoder hexEnc = new HexDumpEncoder();
-            System.out.println ("OCSPRequest bytes are... ");
+            System.out.println("OCSPRequest bytes are... ");
             System.out.println(hexEnc.encode(bytes));
         }
 
-        return(bytes);
+        return bytes;
     }
 
-    // used by OCSPChecker
-    CertId getCertId() {
-        return certId;
-    }
-
-    private static class SingleRequest {
-        private CertId certId;
-
-        // No extensions are set
-
-        private SingleRequest(X509CertImpl cert, SerialNumber serialNo) throws Exception {
-            certId = new CertId(cert, serialNo);
-        }
-
-        private void encode(DerOutputStream out) throws IOException {
-            DerOutputStream tmp = new DerOutputStream();
-            certId.encode(tmp);
-            out.write(DerValue.tag_Sequence, tmp);
-        }
-
-        private CertId getCertId() {
-            return certId;
-        }
+    List<CertId> getCertIds() {
+        return certIds;
     }
 }
--- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Sat Oct 03 01:22:26 2009 +0100
@@ -28,17 +28,16 @@
 import java.io.*;
 import java.math.BigInteger;
 import java.security.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CRLReason;
 import java.security.cert.X509Certificate;
-import java.security.cert.PKIXParameters;
-import javax.security.auth.x500.X500Principal;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
 import sun.misc.HexDumpEncoder;
 import sun.security.x509.*;
 import sun.security.util.*;
@@ -113,32 +112,29 @@
  * @author      Ram Marti
  */
 
-class OCSPResponse {
+public final class OCSPResponse {
 
-    // Certificate status CHOICE
-    public static final int CERT_STATUS_GOOD = 0;
-    public static final int CERT_STATUS_REVOKED = 1;
-    public static final int CERT_STATUS_UNKNOWN = 2;
+    public enum ResponseStatus {
+        SUCCESSFUL,            // Response has valid confirmations
+        MALFORMED_REQUEST,     // Illegal confirmation request
+        INTERNAL_ERROR,        // Internal error in issuer
+        TRY_LATER,             // Try again later
+        UNUSED,                // is not used
+        SIG_REQUIRED,          // Must sign the request
+        UNAUTHORIZED           // Request unauthorized
+    };
+    private static ResponseStatus[] rsvalues = ResponseStatus.values();
 
     private static final Debug DEBUG = Debug.getInstance("certpath");
     private static final boolean dump = false;
-    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID;
-    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID;
-    static {
-        ObjectIdentifier tmp1 = null;
-        ObjectIdentifier tmp2 = null;
-        try {
-            tmp1 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.1");
-            tmp2 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.2");
-        } catch (Exception e) {
-            // should not happen; log and exit
-        }
-        OCSP_BASIC_RESPONSE_OID = tmp1;
-        OCSP_NONCE_EXTENSION_OID = tmp2;
-    }
+    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
+        ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
+    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
+        ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
 
-    // OCSP response status code
-    private static final int OCSP_RESPONSE_OK = 0;
+    private static final int CERT_STATUS_GOOD = 0;
+    private static final int CERT_STATUS_REVOKED = 1;
+    private static final int CERT_STATUS_UNKNOWN = 2;
 
     // ResponderID CHOICE tags
     private static final int NAME_TAG = 1;
@@ -147,7 +143,8 @@
     // Object identifier for the OCSPSigning key purpose
     private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
 
-    private SingleResponse singleResponse;
+    private final ResponseStatus responseStatus;
+    private final Map<CertId, SingleResponse> singleResponseMap;
 
     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of OCSP responses
@@ -159,289 +156,289 @@
     /*
      * Create an OCSP response from its ASN.1 DER encoding.
      */
-    // used by OCSPChecker
-    OCSPResponse(byte[] bytes, PKIXParameters params,
+    OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
         X509Certificate responderCert)
         throws IOException, CertPathValidatorException {
 
-        try {
-            int responseStatus;
-            ObjectIdentifier  responseType;
-            int version;
-            CertificateIssuerName responderName = null;
-            Date producedAtDate;
-            AlgorithmId sigAlgId;
-            byte[] ocspNonce;
+        // OCSPResponse
+        if (dump) {
+            HexDumpEncoder hexEnc = new HexDumpEncoder();
+            System.out.println("OCSPResponse bytes are...");
+            System.out.println(hexEnc.encode(bytes));
+        }
+        DerValue der = new DerValue(bytes);
+        if (der.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in OCSP response: " +
+                "expected ASN.1 SEQUENCE tag.");
+        }
+        DerInputStream derIn = der.getData();
 
-            // OCSPResponse
-            if (dump) {
-                HexDumpEncoder hexEnc = new HexDumpEncoder();
-                System.out.println("OCSPResponse bytes are...");
-                System.out.println(hexEnc.encode(bytes));
+        // responseStatus
+        int status = derIn.getEnumerated();
+        if (status >= 0 && status < rsvalues.length) {
+            responseStatus = rsvalues[status];
+        } else {
+            // unspecified responseStatus
+            throw new IOException("Unknown OCSPResponse status: " + status);
+        }
+        if (DEBUG != null) {
+            DEBUG.println("OCSP response status: " + responseStatus);
+        }
+        if (responseStatus != ResponseStatus.SUCCESSFUL) {
+            // no need to continue, responseBytes are not set.
+            singleResponseMap = Collections.emptyMap();
+            return;
+        }
+
+        // responseBytes
+        der = derIn.getDerValue();
+        if (!der.isContextSpecific((byte)0)) {
+            throw new IOException("Bad encoding in responseBytes element " +
+                "of OCSP response: expected ASN.1 context specific tag 0.");
+        }
+        DerValue tmp = der.data.getDerValue();
+        if (tmp.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in responseBytes element " +
+                "of OCSP response: expected ASN.1 SEQUENCE tag.");
+        }
+
+        // responseType
+        derIn = tmp.data;
+        ObjectIdentifier responseType = derIn.getOID();
+        if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
+            if (DEBUG != null) {
+                DEBUG.println("OCSP response type: basic");
             }
-            DerValue der = new DerValue(bytes);
-            if (der.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in OCSP response: " +
-                    "expected ASN.1 SEQUENCE tag.");
+        } else {
+            if (DEBUG != null) {
+                DEBUG.println("OCSP response type: " + responseType);
             }
-            DerInputStream derIn = der.getData();
+            throw new IOException("Unsupported OCSP response type: " +
+                responseType);
+        }
 
-            // responseStatus
-            responseStatus = derIn.getEnumerated();
+        // BasicOCSPResponse
+        DerInputStream basicOCSPResponse =
+            new DerInputStream(derIn.getOctetString());
+
+        DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
+        if (seqTmp.length < 3) {
+            throw new IOException("Unexpected BasicOCSPResponse value");
+        }
+
+        DerValue responseData = seqTmp[0];
+
+        // Need the DER encoded ResponseData to verify the signature later
+        byte[] responseDataDer = seqTmp[0].toByteArray();
+
+        // tbsResponseData
+        if (responseData.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in tbsResponseData " +
+                "element of OCSP response: expected ASN.1 SEQUENCE tag.");
+        }
+        DerInputStream seqDerIn = responseData.data;
+        DerValue seq = seqDerIn.getDerValue();
+
+        // version
+        if (seq.isContextSpecific((byte)0)) {
+            // seq[0] is version
+            if (seq.isConstructed() && seq.isContextSpecific()) {
+                //System.out.println ("version is available");
+                seq = seq.data.getDerValue();
+                int version = seq.getInteger();
+                if (seq.data.available() != 0) {
+                    throw new IOException("Bad encoding in version " +
+                        " element of OCSP response: bad format");
+                }
+                seq = seqDerIn.getDerValue();
+            }
+        }
+
+        // responderID
+        short tag = (byte)(seq.tag & 0x1f);
+        if (tag == NAME_TAG) {
             if (DEBUG != null) {
-                DEBUG.println("OCSP response: " +
-                    responseToText(responseStatus));
+                X500Name responderName = new X500Name(seq.getData());
+                DEBUG.println("OCSP Responder name: " + responderName);
             }
-            if (responseStatus != OCSP_RESPONSE_OK) {
-                throw new CertPathValidatorException(
-                    "OCSP Response Failure: " +
-                        responseToText(responseStatus));
-            }
+        } else if (tag == KEY_TAG) {
+            // Ignore, for now
+        } else {
+            throw new IOException("Bad encoding in responderID element of " +
+                "OCSP response: expected ASN.1 context specific tag 0 or 1");
+        }
 
-            // responseBytes
-            der = derIn.getDerValue();
-            if (! der.isContextSpecific((byte)0)) {
-                throw new IOException("Bad encoding in responseBytes element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0.");
-            };
-            DerValue tmp = der.data.getDerValue();
-            if (tmp.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in responseBytes element " +
-                    "of OCSP response: expected ASN.1 SEQUENCE tag.");
-            }
+        // producedAt
+        seq = seqDerIn.getDerValue();
+        if (DEBUG != null) {
+            Date producedAtDate = seq.getGeneralizedTime();
+            DEBUG.println("OCSP response produced at: " + producedAtDate);
+        }
 
-            // responseType
-            derIn = tmp.data;
-            responseType = derIn.getOID();
-            if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP response type: basic");
-                }
-            } else {
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP response type: " + responseType);
-                }
-                throw new IOException("Unsupported OCSP response type: " +
-                    responseType);
-            }
+        // responses
+        DerValue[] singleResponseDer = seqDerIn.getSequence(1);
+        singleResponseMap
+            = new HashMap<CertId, SingleResponse>(singleResponseDer.length);
+        if (DEBUG != null) {
+            DEBUG.println("OCSP number of SingleResponses: "
+                + singleResponseDer.length);
+        }
+        for (int i = 0; i < singleResponseDer.length; i++) {
+            SingleResponse singleResponse
+                = new SingleResponse(singleResponseDer[i]);
+            singleResponseMap.put(singleResponse.getCertId(), singleResponse);
+        }
 
-            // BasicOCSPResponse
-            DerInputStream basicOCSPResponse =
-                new DerInputStream(derIn.getOctetString());
-
-            DerValue[]  seqTmp = basicOCSPResponse.getSequence(2);
-            DerValue responseData = seqTmp[0];
-
-            // Need the DER encoded ResponseData to verify the signature later
-            byte[] responseDataDer = seqTmp[0].toByteArray();
-
-            // tbsResponseData
-            if (responseData.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in tbsResponseData " +
-                    " element of OCSP response: expected ASN.1 SEQUENCE tag.");
-            }
-            DerInputStream seqDerIn = responseData.data;
-            DerValue seq = seqDerIn.getDerValue();
-
-            // version
-            if (seq.isContextSpecific((byte)0)) {
-                // seq[0] is version
-                if (seq.isConstructed() && seq.isContextSpecific()) {
-                    //System.out.println ("version is available");
-                    seq = seq.data.getDerValue();
-                    version = seq.getInteger();
-                    if (seq.data.available() != 0) {
-                        throw new IOException("Bad encoding in version " +
-                            " element of OCSP response: bad format");
+        // responseExtensions
+        if (seqDerIn.available() > 0) {
+            seq = seqDerIn.getDerValue();
+            if (seq.isContextSpecific((byte)1)) {
+                DerValue[] responseExtDer = seq.data.getSequence(3);
+                for (int i = 0; i < responseExtDer.length; i++) {
+                    Extension responseExtension
+                        = new Extension(responseExtDer[i]);
+                    if (DEBUG != null) {
+                        DEBUG.println("OCSP extension: " + responseExtension);
                     }
-                    seq = seqDerIn.getDerValue();
-                }
-            }
-
-            // responderID
-            short tag = (byte)(seq.tag & 0x1f);
-            if (tag == NAME_TAG) {
-                responderName = new CertificateIssuerName(seq.getData());
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP Responder name: " + responderName);
-                }
-            } else if (tag == KEY_TAG) {
-                // Ignore, for now
-            } else {
-                throw new IOException("Bad encoding in responderID element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0 " +
-                    "or 1");
-            }
-
-            // producedAt
-            seq = seqDerIn.getDerValue();
-            producedAtDate = seq.getGeneralizedTime();
-
-            // responses
-            DerValue[] singleResponseDer = seqDerIn.getSequence(1);
-            // Examine only the first response
-            singleResponse = new SingleResponse(singleResponseDer[0]);
-
-            // responseExtensions
-            if (seqDerIn.available() > 0) {
-                seq = seqDerIn.getDerValue();
-                if (seq.isContextSpecific((byte)1)) {
-                    DerValue[]  responseExtDer = seq.data.getSequence(3);
-                    Extension[] responseExtension =
-                        new Extension[responseExtDer.length];
-                    for (int i = 0; i < responseExtDer.length; i++) {
-                        responseExtension[i] = new Extension(responseExtDer[i]);
-                        if (DEBUG != null) {
-                            DEBUG.println("OCSP extension: " +
-                                responseExtension[i]);
-                        }
-                        if ((responseExtension[i].getExtensionId()).equals(
-                            OCSP_NONCE_EXTENSION_OID)) {
-                            ocspNonce =
-                                responseExtension[i].getExtensionValue();
-
-                        } else if (responseExtension[i].isCritical())  {
-                            throw new IOException(
-                                "Unsupported OCSP critical extension: " +
-                                responseExtension[i].getExtensionId());
-                        }
+                    if (responseExtension.getExtensionId().equals(
+                        OCSP_NONCE_EXTENSION_OID)) {
+                        /*
+                        ocspNonce =
+                            responseExtension[i].getExtensionValue();
+                         */
+                    } else if (responseExtension.isCritical())  {
+                        throw new IOException(
+                            "Unsupported OCSP critical extension: " +
+                            responseExtension.getExtensionId());
                     }
                 }
             }
+        }
 
-            // signatureAlgorithmId
-            sigAlgId = AlgorithmId.parse(seqTmp[1]);
+        // signatureAlgorithmId
+        AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
 
-            // signature
-            byte[] signature = seqTmp[2].getBitString();
-            X509CertImpl[] x509Certs = null;
+        // signature
+        byte[] signature = seqTmp[2].getBitString();
+        X509CertImpl[] x509Certs = null;
 
-            // if seq[3] is available , then it is a sequence of certificates
-            if (seqTmp.length > 3) {
-                // certs are available
-                DerValue seqCert = seqTmp[3];
-                if (! seqCert.isContextSpecific((byte)0)) {
-                    throw new IOException("Bad encoding in certs element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0.");
-                }
-                DerValue[] certs = (seqCert.getData()).getSequence(3);
-                x509Certs = new X509CertImpl[certs.length];
+        // if seq[3] is available , then it is a sequence of certificates
+        if (seqTmp.length > 3) {
+            // certs are available
+            DerValue seqCert = seqTmp[3];
+            if (!seqCert.isContextSpecific((byte)0)) {
+                throw new IOException("Bad encoding in certs element of " +
+                    "OCSP response: expected ASN.1 context specific tag 0.");
+            }
+            DerValue[] certs = seqCert.getData().getSequence(3);
+            x509Certs = new X509CertImpl[certs.length];
+            try {
                 for (int i = 0; i < certs.length; i++) {
                     x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
                 }
+            } catch (CertificateException ce) {
+                throw new IOException("Bad encoding in X509 Certificate", ce);
             }
+        }
 
-            // Check whether the cert returned by the responder is trusted
-            if (x509Certs != null && x509Certs[0] != null) {
-                X509CertImpl cert = x509Certs[0];
+        // Check whether the cert returned by the responder is trusted
+        if (x509Certs != null && x509Certs[0] != null) {
+            X509CertImpl cert = x509Certs[0];
 
-                // First check if the cert matches the responder cert which
-                // was set locally.
-                if (cert.equals(responderCert)) {
-                    // cert is trusted, now verify the signed response
+            // First check if the cert matches the responder cert which
+            // was set locally.
+            if (cert.equals(responderCert)) {
+                // cert is trusted, now verify the signed response
 
-                // Next check if the cert was issued by the responder cert
-                // which was set locally.
-                } else if (cert.getIssuerX500Principal().equals(
-                    responderCert.getSubjectX500Principal())) {
+            // Next check if the cert was issued by the responder cert
+            // which was set locally.
+            } else if (cert.getIssuerX500Principal().equals(
+                responderCert.getSubjectX500Principal())) {
 
-                    // Check for the OCSPSigning key purpose
+                // Check for the OCSPSigning key purpose
+                try {
                     List<String> keyPurposes = cert.getExtendedKeyUsage();
                     if (keyPurposes == null ||
                         !keyPurposes.contains(KP_OCSP_SIGNING_OID)) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate is not " +
-                                "valid for signing OCSP responses.");
-                        }
                         throw new CertPathValidatorException(
                             "Responder's certificate not valid for signing " +
                             "OCSP responses");
                     }
+                } catch (CertificateParsingException cpe) {
+                    // assume cert is not valid for signing
+                    throw new CertPathValidatorException(
+                        "Responder's certificate not valid for signing " +
+                        "OCSP responses", cpe);
+                }
 
-                    // check the validity
-                    try {
-                        Date dateCheckedAgainst = params.getDate();
-                        if (dateCheckedAgainst == null) {
-                            cert.checkValidity();
-                        } else {
-                            cert.checkValidity(dateCheckedAgainst);
-                        }
-                    } catch (GeneralSecurityException e) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate is not " +
-                                "within the validity period.");
-                        }
-                        throw new CertPathValidatorException(
-                            "Responder's certificate not within the " +
-                            "validity period");
+                // check the validity
+                try {
+                    if (dateCheckedAgainst == null) {
+                        cert.checkValidity();
+                    } else {
+                        cert.checkValidity(dateCheckedAgainst);
                     }
+                } catch (GeneralSecurityException e) {
+                    throw new CertPathValidatorException(
+                        "Responder's certificate not within the " +
+                        "validity period", e);
+                }
 
-                    // check for revocation
-                    //
-                    // A CA may specify that an OCSP client can trust a
-                    // responder for the lifetime of the responder's
-                    // certificate. The CA does so by including the
-                    // extension id-pkix-ocsp-nocheck.
-                    //
-                    Extension noCheck =
-                            cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
-                    if (noCheck != null) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate includes " +
-                                "the extension id-pkix-ocsp-nocheck.");
-                        }
-                    } else {
-                        // we should do the revocating checking of the
-                        // authorized responder in a future update.
-                    }
-
-                    // verify the signature
-                    try {
-                        cert.verify(responderCert.getPublicKey());
-                        responderCert = cert;
-                        // cert is trusted, now verify the signed response
-
-                    } catch (GeneralSecurityException e) {
-                        responderCert = null;
+                // check for revocation
+                //
+                // A CA may specify that an OCSP client can trust a
+                // responder for the lifetime of the responder's
+                // certificate. The CA does so by including the
+                // extension id-pkix-ocsp-nocheck.
+                //
+                Extension noCheck =
+                    cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
+                if (noCheck != null) {
+                    if (DEBUG != null) {
+                        DEBUG.println("Responder's certificate includes " +
+                            "the extension id-pkix-ocsp-nocheck.");
                     }
                 } else {
-                    if (DEBUG != null) {
-                        DEBUG.println("Responder's certificate is not " +
-                            "authorized to sign OCSP responses.");
-                    }
-                    throw new CertPathValidatorException(
-                        "Responder's certificate not authorized to sign " +
-                        "OCSP responses");
+                    // we should do the revocation checking of the
+                    // authorized responder in a future update.
                 }
-            }
 
-            // Confirm that the signed response was generated using the public
-            // key from the trusted responder cert
-            if (responderCert != null) {
+                // verify the signature
+                try {
+                    cert.verify(responderCert.getPublicKey());
+                    responderCert = cert;
+                    // cert is trusted, now verify the signed response
 
-                if (! verifyResponse(responseDataDer, responderCert,
-                    sigAlgId, signature, params)) {
-                    if (DEBUG != null) {
-                        DEBUG.println("Error verifying OCSP Responder's " +
-                            "signature");
-                    }
-                    throw new CertPathValidatorException(
-                        "Error verifying OCSP Responder's signature");
+                } catch (GeneralSecurityException e) {
+                    responderCert = null;
                 }
             } else {
-                // Need responder's cert in order to verify the signature
-                if (DEBUG != null) {
-                    DEBUG.println("Unable to verify OCSP Responder's " +
-                        "signature");
-                }
                 throw new CertPathValidatorException(
-                    "Unable to verify OCSP Responder's signature");
+                    "Responder's certificate is not authorized to sign " +
+                    "OCSP responses");
             }
-        } catch (CertPathValidatorException cpve) {
-            throw cpve;
-        } catch (Exception e) {
-            throw new CertPathValidatorException(e);
         }
+
+        // Confirm that the signed response was generated using the public
+        // key from the trusted responder cert
+        if (responderCert != null) {
+            if (!verifyResponse(responseDataDer, responderCert,
+                sigAlgId, signature)) {
+                throw new CertPathValidatorException(
+                    "Error verifying OCSP Responder's signature");
+            }
+        } else {
+            // Need responder's cert in order to verify the signature
+            throw new CertPathValidatorException(
+                "Unable to verify OCSP Responder's signature");
+        }
+    }
+
+    /**
+     * Returns the OCSP ResponseStatus.
+     */
+    ResponseStatus getResponseStatus() {
+        return responseStatus;
     }
 
     /*
@@ -449,11 +446,10 @@
      * The responder's cert is implicitly trusted.
      */
     private boolean verifyResponse(byte[] responseData, X509Certificate cert,
-        AlgorithmId sigAlgId, byte[] signBytes, PKIXParameters params)
-        throws SignatureException {
+        AlgorithmId sigAlgId, byte[] signBytes)
+        throws CertPathValidatorException {
 
         try {
-
             Signature respSignature = Signature.getInstance(sigAlgId.getName());
             respSignature.initVerify(cert);
             respSignature.update(responseData);
@@ -472,92 +468,33 @@
                 return false;
             }
         } catch (InvalidKeyException ike) {
-            throw new SignatureException(ike);
-
+            throw new CertPathValidatorException(ike);
         } catch (NoSuchAlgorithmException nsae) {
-            throw new SignatureException(nsae);
+            throw new CertPathValidatorException(nsae);
+        } catch (SignatureException se) {
+            throw new CertPathValidatorException(se);
         }
     }
 
-    /*
-     * Return the revocation status code for a given certificate.
+    /**
+     * Returns the SingleResponse of the specified CertId, or null if
+     * there is no response for that CertId.
      */
-    // used by OCSPChecker
-    int getCertStatus(SerialNumber sn) {
-        // ignore serial number for now; if we support multiple
-        // requests/responses then it will be used
-        return singleResponse.getStatus();
-    }
-
-    // used by OCSPChecker
-    CertId getCertId() {
-        return singleResponse.getCertId();
-    }
-
-    Date getRevocationTime() {
-        return singleResponse.getRevocationTime();
-    }
-
-    CRLReason getRevocationReason() {
-        return singleResponse.getRevocationReason();
-    }
-
-    Map<String, java.security.cert.Extension> getSingleExtensions() {
-        return singleResponse.getSingleExtensions();
-    }
-
-    /*
-     * Map an OCSP response status code to a string.
-     */
-    static private String responseToText(int status) {
-        switch (status)  {
-        case 0:
-            return "Successful";
-        case 1:
-            return "Malformed request";
-        case 2:
-            return "Internal error";
-        case 3:
-            return "Try again later";
-        case 4:
-            return "Unused status code";
-        case 5:
-            return "Request must be signed";
-        case 6:
-            return "Request is unauthorized";
-        default:
-            return ("Unknown status code: " + status);
-        }
-    }
-
-    /*
-     * Map a certificate's revocation status code to a string.
-     */
-    // used by OCSPChecker
-    static String certStatusToText(int certStatus) {
-        switch (certStatus)  {
-        case 0:
-            return "Good";
-        case 1:
-            return "Revoked";
-        case 2:
-            return "Unknown";
-        default:
-            return ("Unknown certificate status code: " + certStatus);
-        }
+    SingleResponse getSingleResponse(CertId certId) {
+        return singleResponseMap.get(certId);
     }
 
     /*
      * A class representing a single OCSP response.
      */
-    private class SingleResponse {
-        private CertId certId;
-        private int certStatus;
-        private Date thisUpdate;
-        private Date nextUpdate;
-        private Date revocationTime;
-        private CRLReason revocationReason = CRLReason.UNSPECIFIED;
-        private HashMap<String, java.security.cert.Extension> singleExtensions;
+    final static class SingleResponse implements OCSP.RevocationStatus {
+        private final CertId certId;
+        private final CertStatus certStatus;
+        private final Date thisUpdate;
+        private final Date nextUpdate;
+        private final Date revocationTime;
+        private final CRLReason revocationReason;
+        private final Map<String, java.security.cert.Extension> singleExtensions;
 
         private SingleResponse(DerValue der) throws IOException {
             if (der.tag != DerValue.tag_Sequence) {
@@ -568,35 +505,48 @@
             certId = new CertId(tmp.getDerValue().data);
             DerValue derVal = tmp.getDerValue();
             short tag = (byte)(derVal.tag & 0x1f);
-            if (tag ==  CERT_STATUS_GOOD) {
-                certStatus = CERT_STATUS_GOOD;
-            } else if (tag == CERT_STATUS_REVOKED) {
-                certStatus = CERT_STATUS_REVOKED;
+            if (tag ==  CERT_STATUS_REVOKED) {
+                certStatus = CertStatus.REVOKED;
                 revocationTime = derVal.data.getGeneralizedTime();
                 if (derVal.data.available() != 0) {
-                    int reason = derVal.getEnumerated();
-                    // if reason out-of-range just leave as UNSPECIFIED
-                    if (reason >= 0 && reason < values.length) {
-                        revocationReason = values[reason];
+                    DerValue dv = derVal.data.getDerValue();
+                    tag = (byte)(dv.tag & 0x1f);
+                    if (tag == 0) {
+                        int reason = dv.data.getEnumerated();
+                        // if reason out-of-range just leave as UNSPECIFIED
+                        if (reason >= 0 && reason < values.length) {
+                            revocationReason = values[reason];
+                        } else {
+                            revocationReason = CRLReason.UNSPECIFIED;
+                        }
+                    } else {
+                        revocationReason = CRLReason.UNSPECIFIED;
                     }
+                } else {
+                    revocationReason = CRLReason.UNSPECIFIED;
                 }
                 // RevokedInfo
                 if (DEBUG != null) {
                     DEBUG.println("Revocation time: " + revocationTime);
                     DEBUG.println("Revocation reason: " + revocationReason);
                 }
-
-            } else if (tag == CERT_STATUS_UNKNOWN) {
-                certStatus = CERT_STATUS_UNKNOWN;
-
             } else {
-                throw new IOException("Invalid certificate status");
+                revocationTime = null;
+                revocationReason = CRLReason.UNSPECIFIED;
+                if (tag == CERT_STATUS_GOOD) {
+                    certStatus = CertStatus.GOOD;
+                } else if (tag == CERT_STATUS_UNKNOWN) {
+                    certStatus = CertStatus.UNKNOWN;
+                } else {
+                    throw new IOException("Invalid certificate status");
+                }
             }
 
             thisUpdate = tmp.getGeneralizedTime();
 
             if (tmp.available() == 0)  {
                 // we are done
+                nextUpdate = null;
             } else {
                 derVal = tmp.getDerValue();
                 tag = (byte)(derVal.tag & 0x1f);
@@ -610,6 +560,8 @@
                         derVal = tmp.getDerValue();
                         tag = (byte)(derVal.tag & 0x1f);
                     }
+                } else {
+                    nextUpdate = null;
                 }
             }
             // singleExtensions
@@ -627,7 +579,11 @@
                             DEBUG.println("OCSP single extension: " + ext);
                         }
                     }
+                } else {
+                    singleExtensions = Collections.emptyMap();
                 }
+            } else {
+                singleExtensions = Collections.emptyMap();
             }
 
             long now = System.currentTimeMillis();
@@ -657,7 +613,7 @@
         /*
          * Return the certificate's revocation status code
          */
-        private int getStatus() {
+        @Override public CertStatus getCertStatus() {
             return certStatus;
         }
 
@@ -665,28 +621,28 @@
             return certId;
         }
 
-        private Date getRevocationTime() {
-            return revocationTime;
+        @Override public Date getRevocationTime() {
+            return (Date) revocationTime.clone();
         }
 
-        private CRLReason getRevocationReason() {
+        @Override public CRLReason getRevocationReason() {
             return revocationReason;
         }
 
-        private Map<String, java.security.cert.Extension> getSingleExtensions() {
-            return singleExtensions;
+        @Override
+        public Map<String, java.security.cert.Extension> getSingleExtensions() {
+            return Collections.unmodifiableMap(singleExtensions);
         }
 
         /**
          * Construct a string representation of a single OCSP response.
          */
-        public String toString() {
+        @Override public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("SingleResponse:  \n");
             sb.append(certId);
-            sb.append("\nCertStatus: "+ certStatusToText(getCertStatus(null)) +
-                "\n");
-            if (certStatus == CERT_STATUS_REVOKED) {
+            sb.append("\nCertStatus: "+ certStatus + "\n");
+            if (certStatus == CertStatus.REVOKED) {
                 sb.append("revocationTime is " + revocationTime + "\n");
                 sb.append("revocationReason is " + revocationReason + "\n");
             }
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,8 +28,6 @@
 import java.io.IOException;
 import java.security.AccessController;
 import java.security.InvalidAlgorithmParameterException;
-import java.security.PrivilegedAction;
-import java.security.Security;
 import java.security.cert.CertPath;
 import java.security.cert.CertPathParameters;
 import java.security.cert.CertPathValidatorException;
@@ -49,6 +47,7 @@
 import java.util.Date;
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanSecurityPropertyAction;
 import sun.security.util.Debug;
 
 /**
@@ -67,7 +66,8 @@
     private List<PKIXCertPathChecker> userCheckers;
     private String sigProvider;
     private BasicChecker basicChecker;
-    private String ocspProperty;
+    private boolean ocspEnabled = false;
+    private boolean onlyEECert = false;
 
     /**
      * Default constructor.
@@ -253,13 +253,12 @@
 
         if (pkixParam.isRevocationEnabled()) {
             // Examine OCSP security property
-            ocspProperty = AccessController.doPrivileged(
-                new PrivilegedAction<String>() {
-                    public String run() {
-                        return
-                            Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP);
-                    }
-                });
+            ocspEnabled = AccessController.doPrivileged(
+                new GetBooleanSecurityPropertyAction
+                    (OCSPChecker.OCSP_ENABLE_PROP));
+            onlyEECert = AccessController.doPrivileged(
+                new GetBooleanSecurityPropertyAction
+                    ("com.sun.security.onlyCheckRevocationOfEECert"));
         }
     }
 
@@ -301,15 +300,15 @@
         if (pkixParam.isRevocationEnabled()) {
 
             // Use OCSP if it has been enabled
-            if ("true".equalsIgnoreCase(ocspProperty)) {
+            if (ocspEnabled) {
                 OCSPChecker ocspChecker =
-                    new OCSPChecker(cpOriginal, pkixParam);
+                    new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
                 certPathCheckers.add(ocspChecker);
             }
 
             // Always use CRLs
-            CrlRevocationChecker revocationChecker =
-                new CrlRevocationChecker(anchor, pkixParam, certList);
+            CrlRevocationChecker revocationChecker = new
+                CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
             certPathCheckers.add(revocationChecker);
         }
 
--- a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Sat Oct 03 01:22:26 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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 sun.security.provider.certpath;
 
 import java.io.IOException;
+import java.security.AccessController;
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.Principal;
@@ -44,6 +45,7 @@
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.action.GetBooleanSecurityPropertyAction;
 import sun.security.x509.X500Name;
 import sun.security.x509.PKIXExtensions;
 import sun.security.util.Debug;
@@ -85,6 +87,7 @@
     private PublicKey finalPublicKey;
     private X509CertSelector targetSel;
     private List<CertStore> orderedCertStores;
+    private boolean onlyEECert = false;
 
     /**
      * Create an instance of <code>SunCertPathBuilder</code>.
@@ -97,6 +100,9 @@
         } catch (CertificateException e) {
             throw new CertPathBuilderException(e);
         }
+        onlyEECert = AccessController.doPrivileged(
+            new GetBooleanSecurityPropertyAction
+                ("com.sun.security.onlyCheckRevocationOfEECert"));
     }
 
     /**
@@ -256,7 +262,6 @@
 
     /*
      * Private build reverse method.
-     *
      */
     private void buildReverse(List<List<Vertex>> adjacencyList,
         LinkedList<X509Certificate> certPathList) throws Exception
@@ -296,7 +301,7 @@
             currentState.updateState(anchor);
             // init the crl checker
             currentState.crlChecker =
-                new CrlRevocationChecker(null, buildParams);
+                new CrlRevocationChecker(null, buildParams, null, onlyEECert);
             try {
                 depthFirstSearchReverse(null, currentState,
                 new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -341,10 +346,12 @@
         adjacencyList.add(new LinkedList<Vertex>());
 
         // init the crl checker
-        currentState.crlChecker = new CrlRevocationChecker(null, buildParams);
+        currentState.crlChecker
+            = new CrlRevocationChecker(null, buildParams, null, onlyEECert);
 
         depthFirstSearchForward(targetSubjectDN, currentState,
-          new ForwardBuilder(buildParams, targetSubjectDN, searchAllCertStores),
+          new ForwardBuilder
+              (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
           adjacencyList, certPathList);
     }
 
@@ -486,8 +493,8 @@
                     userCheckers.add(mustCheck, basicChecker);
                     mustCheck++;
                     if (buildParams.isRevocationEnabled()) {
-                        userCheckers.add(mustCheck,
-                            new CrlRevocationChecker(anchor, buildParams));
+                        userCheckers.add(mustCheck, new CrlRevocationChecker
+                            (anchor, buildParams, null, onlyEECert));
                         mustCheck++;
                     }
                 }
--- a/src/share/classes/sun/security/x509/AccessDescription.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/security/x509/AccessDescription.java	Sat Oct 03 01:22:26 2009 +0100
@@ -113,7 +113,7 @@
         } else {
             method = accessMethod.toString();
         }
-        return ("accessMethod: " + method +
+        return ("\n   accessMethod: " + method +
                 "\n   accessLocation: " + accessLocation.toString() + "\n");
     }
 }
--- a/src/share/classes/sun/util/LocaleServiceProviderPool.java	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/classes/sun/util/LocaleServiceProviderPool.java	Sat Oct 03 01:22:26 2009 +0100
@@ -39,8 +39,8 @@
 import java.util.ServiceConfigurationError;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
 import java.util.spi.LocaleServiceProvider;
+import sun.util.logging.PlatformLogger;
 import sun.util.resources.LocaleData;
 import sun.util.resources.OpenListResourceBundle;
 
@@ -122,10 +122,15 @@
                 }
             });
         }  catch (PrivilegedActionException e) {
-            Logger.getLogger("sun.util.LocaleServiceProviderPool").config(e.toString());
+            config(e.toString());
         }
     }
 
+    private static void config(String message) {
+        PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool");
+        logger.config(message);
+    }
+
     /**
      * Lazy loaded set of available locales.
      * Loading all locales is a very long operation.
@@ -337,7 +342,7 @@
                     if (providersObj != null) {
                         return providersObj;
                     } else if (isObjectProvider) {
-                        Logger.getLogger("sun.util.LocaleServiceProviderPool").config(
+                        config(
                             "A locale sensitive service provider returned null for a localized objects,  which should not happen.  provider: " + lsp + " locale: " + requested);
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/util/logging/PlatformLogger.java	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package sun.util.logging;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import sun.misc.JavaLangAccess;
+import sun.misc.SharedSecrets;
+
+/**
+ * Platform logger provides an API for the JRE components to log
+ * messages.  This enables the runtime components to eliminate the
+ * static dependency of the logging facility and also defers the
+ * java.util.logging initialization until it is enabled.
+ * In addition, the PlatformLogger API can be used if the logging
+ * module does not exist.
+ *
+ * If the logging facility is not enabled, the platform loggers
+ * will output log messages per the default logging configuration
+ * (see below). In this implementation, it does not log the
+ * the stack frame information issuing the log message.
+ *
+ * When the logging facility is enabled (at startup or runtime),
+ * the java.util.logging.Logger will be created for each platform
+ * logger and all log messages will be forwarded to the Logger
+ * to handle.
+ *
+ * Logging facility is "enabled" when one of the following
+ * conditions is met:
+ * 1) a system property "java.util.logging.config.class" or
+ *    "java.util.logging.config.file" is set
+ * 2) java.util.logging.LogManager or java.util.logging.Logger
+ *    is referenced that will trigger the logging initialization.
+ *
+ * Default logging configuration:
+ *   global logging level = INFO
+ *   handlers = java.util.logging.ConsoleHandler
+ *   java.util.logging.ConsoleHandler.level = INFO
+ *   java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+ *
+ * Limitation:
+ * <JAVA_HOME>/lib/logging.properties is the system-wide logging
+ * configuration defined in the specification and read in the
+ * default case to configure any java.util.logging.Logger instances.
+ * Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
+ * is modified. In other words, unless the java.util.logging API
+ * is used at runtime or the logging system properties is set,
+ * the platform loggers will use the default setting described above.
+ * The platform loggers are designed for JDK developers use and
+ * this limitation can be workaround with setting
+ * -Djava.util.logging.config.file system property.
+ *
+ * @since 1.7
+ */
+public class PlatformLogger {
+    // Same values as java.util.logging.Level for easy mapping
+    public static final int OFF     = Integer.MAX_VALUE;
+    public static final int SEVERE  = 1000;
+    public static final int WARNING = 900;
+    public static final int INFO    = 800;
+    public static final int CONFIG  = 700;
+    public static final int FINE    = 500;
+    public static final int FINER   = 400;
+    public static final int FINEST  = 300;
+    public static final int ALL     = Integer.MIN_VALUE;
+
+    private static final int defaultLevel = INFO;
+    private static boolean loggingEnabled;
+    static {
+        loggingEnabled = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    String cname = System.getProperty("java.util.logging.config.class");
+                    String fname = System.getProperty("java.util.logging.config.file");
+                    return (cname != null || fname != null);
+                }
+            });
+    }
+
+    // Table of known loggers.  Maps names to PlatformLoggers.
+    private static Map<String,WeakReference<PlatformLogger>> loggers =
+        new HashMap<String,WeakReference<PlatformLogger>>();
+
+    /**
+     * Returns a PlatformLogger of a given name.
+     */
+    public static synchronized PlatformLogger getLogger(String name) {
+        PlatformLogger log = null;
+        WeakReference<PlatformLogger> ref = loggers.get(name);
+        if (ref != null) {
+            log = ref.get();
+        }
+        if (log == null) {
+            log = new PlatformLogger(name);
+            loggers.put(name, new WeakReference<PlatformLogger>(log));
+        }
+        return log;
+    }
+
+    /**
+     * Initialize java.util.logging.Logger objects for all platform loggers.
+     * This method is called from LogManager.readPrimordialConfiguration().
+     */
+    public static synchronized void redirectPlatformLoggers() {
+        if (loggingEnabled || !JavaLogger.supported) return;
+
+        loggingEnabled = true;
+        for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
+            WeakReference<PlatformLogger> ref = entry.getValue();
+            PlatformLogger plog = ref.get();
+            if (plog != null) {
+                plog.newJavaLogger();
+            }
+        }
+    }
+
+    /**
+     * Creates a new JavaLogger that the platform logger uses
+     */
+    private void newJavaLogger() {
+        logger = new JavaLogger(logger.name, logger.effectiveLevel);
+    }
+
+    // logger may be replaced with a JavaLogger object
+    // when the logging facility is enabled
+    private volatile LoggerProxy logger;
+
+    private PlatformLogger(String name) {
+        if (loggingEnabled) {
+            this.logger = new JavaLogger(name);
+        } else {
+            this.logger = new LoggerProxy(name);
+        }
+    }
+
+    /**
+     * A convenience method to test if the logger is turned off.
+     * (i.e. its level is OFF).
+     */
+    public boolean isEnabled() {
+        return logger.isEnabled();
+    }
+
+    /**
+     * Gets the name for this platform logger.
+     */
+    public String getName() {
+        return logger.name;
+    }
+
+    /**
+     * Returns true if a message of the given level would actually
+     * be logged by this logger.
+     */
+    public boolean isLoggable(int level) {
+        return logger.isLoggable(level);
+    }
+
+    /**
+     * Gets the current log level.  Returns 0 if the current effective level
+     * is not set (equivalent to Logger.getLevel() returns null).
+     */
+    public int getLevel() {
+        return logger.getLevel();
+    }
+
+    /**
+     * Sets the log level.
+     */
+    public void setLevel(int newLevel) {
+        logger.setLevel(newLevel);
+    }
+
+    /**
+     * Logs a SEVERE message.
+     */
+    public void severe(String msg) {
+        logger.doLog(SEVERE, msg);
+    }
+
+    public void severe(String msg, Throwable t) {
+        logger.doLog(SEVERE, msg, t);
+    }
+
+    public void severe(String msg, Object... params) {
+        logger.doLog(SEVERE, msg, params);
+    }
+
+    /**
+     * Logs a WARNING message.
+     */
+    public void warning(String msg) {
+        logger.doLog(WARNING, msg);
+    }
+
+    public void warning(String msg, Throwable t) {
+        logger.doLog(WARNING, msg, t);
+    }
+
+    public void warning(String msg, Object... params) {
+        logger.doLog(WARNING, msg, params);
+    }
+
+    /**
+     * Logs an INFO message.
+     */
+    public void info(String msg) {
+        logger.doLog(INFO, msg);
+    }
+
+    public void info(String msg, Throwable t) {
+        logger.doLog(INFO, msg, t);
+    }
+
+    public void info(String msg, Object... params) {
+        logger.doLog(INFO, msg, params);
+    }
+
+    /**
+     * Logs a CONFIG message.
+     */
+    public void config(String msg) {
+        logger.doLog(CONFIG, msg);
+    }
+
+    public void config(String msg, Throwable t) {
+        logger.doLog(CONFIG, msg, t);
+    }
+
+    public void config(String msg, Object... params) {
+        logger.doLog(CONFIG, msg, params);
+    }
+
+    /**
+     * Logs a FINE message.
+     */
+    public void fine(String msg) {
+        logger.doLog(FINE, msg);
+    }
+
+    public void fine(String msg, Throwable t) {
+        logger.doLog(FINE, msg, t);
+    }
+
+    public void fine(String msg, Object... params) {
+        logger.doLog(FINE, msg, params);
+    }
+
+    /**
+     * Logs a FINER message.
+     */
+    public void finer(String msg) {
+        logger.doLog(FINER, msg);
+    }
+
+    public void finer(String msg, Throwable t) {
+        logger.doLog(FINER, msg, t);
+    }
+
+    public void finer(String msg, Object... params) {
+        logger.doLog(FINER, msg, params);
+    }
+
+    /**
+     * Logs a FINEST message.
+     */
+    public void finest(String msg) {
+        logger.doLog(FINEST, msg);
+    }
+
+    public void finest(String msg, Throwable t) {
+        logger.doLog(FINEST, msg, t);
+    }
+
+    public void finest(String msg, Object... params) {
+        logger.doLog(FINEST, msg, params);
+    }
+
+    /**
+     * Default platform logging support - output messages to
+     * System.err - equivalent to ConsoleHandler with SimpleFormatter.
+     */
+    static class LoggerProxy {
+        private static final PrintStream defaultStream = System.err;
+        private static final String lineSeparator = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty("line.separator");
+                }
+            });
+
+        final String name;
+        volatile int levelValue;
+        volatile int effectiveLevel = 0; // current effective level value
+
+        LoggerProxy(String name) {
+            this(name, defaultLevel);
+        }
+
+        LoggerProxy(String name, int level) {
+            this.name = name;
+            this.levelValue = level == 0 ? defaultLevel : level;
+        }
+
+        boolean isEnabled() {
+            return levelValue != OFF;
+        }
+
+        int getLevel() {
+            return effectiveLevel;
+        }
+
+        void setLevel(int newLevel) {
+            levelValue = newLevel;
+            effectiveLevel = newLevel;
+        }
+
+        void doLog(int level, String msg) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            defaultStream.println(format(level, msg, null));
+        }
+
+        void doLog(int level, String msg, Throwable thrown) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            defaultStream.println(format(level, msg, thrown));
+        }
+
+        void doLog(int level, String msg, Object... params) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            String newMsg = formatMessage(msg, params);
+            defaultStream.println(format(level, newMsg, null));
+        }
+
+        public boolean isLoggable(int level) {
+            if (level < levelValue || levelValue == OFF) {
+                return false;
+            }
+            return true;
+        }
+
+        private static final String format = "{0,date} {0,time}";
+
+        private Object args[] = new Object[1];
+        private MessageFormat formatter;
+        private Date dat;
+
+        // Copied from java.util.logging.Formatter.formatMessage
+        private String formatMessage(String format, Object... parameters) {
+            // Do the formatting.
+            try {
+                if (parameters == null || parameters.length == 0) {
+                    // No parameters.  Just return format string.
+                    return format;
+                }
+                // Is it a java.text style format?
+                // Ideally we could match with
+                // Pattern.compile("\\{\\d").matcher(format).find())
+                // However the cost is 14% higher, so we cheaply check for
+                // 1 of the first 4 parameters
+                if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
+                            format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
+                    return java.text.MessageFormat.format(format, parameters);
+                }
+                return format;
+            } catch (Exception ex) {
+                // Formatting failed: use format string.
+                return format;
+            }
+        }
+
+        private synchronized String format(int level, String msg, Throwable thrown) {
+            StringBuffer sb = new StringBuffer();
+            // Minimize memory allocations here.
+            if (dat == null) {
+                dat = new Date();
+                formatter = new MessageFormat(format);
+            }
+            dat.setTime(System.currentTimeMillis());
+            args[0] = dat;
+            StringBuffer text = new StringBuffer();
+            formatter.format(args, text, null);
+            sb.append(text);
+            sb.append(" ");
+            sb.append(getCallerInfo());
+            sb.append(lineSeparator);
+            sb.append(PlatformLogger.getLevelName(level));
+            sb.append(": ");
+            sb.append(msg);
+            if (thrown != null) {
+                try {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);
+                    thrown.printStackTrace(pw);
+                    pw.close();
+                    sb.append(sw.toString());
+                } catch (Exception ex) {
+                    throw new AssertionError(ex);
+                }
+            }
+
+            return sb.toString();
+        }
+
+        // Returns the caller's class and method's name; best effort
+        // if cannot infer, return the logger's name.
+        private String getCallerInfo() {
+            String sourceClassName = null;
+            String sourceMethodName = null;
+
+            JavaLangAccess access = SharedSecrets.getJavaLangAccess();
+            Throwable throwable = new Throwable();
+            int depth = access.getStackTraceDepth(throwable);
+
+            String logClassName = "sun.util.logging.PlatformLogger";
+            boolean lookingForLogger = true;
+            for (int ix = 0; ix < depth; ix++) {
+                // Calling getStackTraceElement directly prevents the VM
+                // from paying the cost of building the entire stack frame.
+                StackTraceElement frame =
+                    access.getStackTraceElement(throwable, ix);
+                String cname = frame.getClassName();
+                if (lookingForLogger) {
+                    // Skip all frames until we have found the first logger frame.
+                    if (cname.equals(logClassName)) {
+                        lookingForLogger = false;
+                    }
+                } else {
+                    if (!cname.equals(logClassName)) {
+                        // We've found the relevant frame.
+                        sourceClassName = cname;
+                        sourceMethodName = frame.getMethodName();
+                        break;
+                    }
+                }
+            }
+
+            if (sourceClassName != null) {
+                return sourceClassName + " " + sourceMethodName;
+            } else {
+                return name;
+            }
+        }
+    }
+
+    /**
+     * JavaLogger forwards all the calls to its corresponding
+     * java.util.logging.Logger object.
+     */
+    static class JavaLogger extends LoggerProxy {
+        private static final boolean supported;
+        private static final Class<?> loggerClass;
+        private static final Class<?> levelClass;
+        private static final Method getLoggerMethod;
+        private static final Method setLevelMethod;
+        private static final Method getLevelMethod;
+        private static final Method isLoggableMethod;
+        private static final Method logMethod;
+        private static final Method logThrowMethod;
+        private static final Method logParamsMethod;
+        private static final Map<Integer, Object> levelObjects =
+            new HashMap<Integer, Object>();
+
+        static {
+            loggerClass = getClass("java.util.logging.Logger");
+            levelClass = getClass("java.util.logging.Level");
+            getLoggerMethod = getMethod(loggerClass, "getLogger", String.class);
+            setLevelMethod = getMethod(loggerClass, "setLevel", levelClass);
+            getLevelMethod = getMethod(loggerClass, "getLevel");
+            isLoggableMethod = getMethod(loggerClass, "isLoggable", levelClass);
+            logMethod = getMethod(loggerClass, "log", levelClass, String.class);
+            logThrowMethod = getMethod(loggerClass, "log", levelClass, String.class, Throwable.class);
+            logParamsMethod = getMethod(loggerClass, "log", levelClass, String.class, Object[].class);
+            supported = (loggerClass != null && levelClass != null && getLoggerMethod != null &&
+                         getLevelMethod != null && setLevelMethod != null &&
+                         logMethod != null && logThrowMethod != null && logParamsMethod != null);
+            if (supported) {
+                // initialize the map to Level objects
+                getLevelObjects();
+            }
+        }
+
+        private static Class<?> getClass(String name) {
+            try {
+                return Class.forName(name, true, null);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+
+        private static Method getMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
+            if (cls == null) return null;
+
+            try {
+                return cls.getMethod(name, parameterTypes);
+            } catch (NoSuchMethodException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        private static Object invoke(Method m, Object obj, Object... params) {
+            try {
+                return m.invoke(obj, params);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            } catch (InvocationTargetException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        private static void getLevelObjects() {
+            // get all java.util.logging.Level objects
+            Method parseLevelMethod = getMethod(levelClass, "parse", String.class);
+            int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
+            for (int l : levelArray) {
+                Object o = invoke(parseLevelMethod, null, getLevelName(l));
+                levelObjects.put(l, o);
+            }
+        }
+
+        private final Object javaLogger;
+        JavaLogger(String name) {
+            this(name, 0);
+        }
+
+        JavaLogger(String name, int level) {
+            super(name, level);
+            this.javaLogger = invoke(getLoggerMethod, null, name);
+            if (level != 0) {
+                // level has been updated and so set the Logger's level
+                invoke(setLevelMethod, javaLogger, levelObjects.get(level));
+            }
+        }
+
+       /**
+        * Let Logger.log() do the filtering since if the level of a
+        * platform logger is altered directly from
+        * java.util.logging.Logger.setLevel(), the levelValue will
+        * not be updated.
+        */
+        void doLog(int level, String msg) {
+            invoke(logMethod, javaLogger, levelObjects.get(level), msg);
+        }
+
+        void doLog(int level, String msg, Throwable t) {
+            invoke(logThrowMethod, javaLogger, levelObjects.get(level), msg, t);
+        }
+
+        void doLog(int level, String msg, Object... params) {
+            invoke(logParamsMethod, javaLogger, levelObjects.get(level), msg, params);
+        }
+
+        boolean isEnabled() {
+            Object level = invoke(getLevelMethod, javaLogger);
+            return level == null || level.equals(levelObjects.get(OFF)) == false;
+        }
+
+        int getLevel() {
+            Object level = invoke(getLevelMethod, javaLogger);
+            if (level != null) {
+                for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) {
+                    if (level == l.getValue()) {
+                        return l.getKey();
+                    }
+                }
+            }
+            return 0;
+        }
+
+        void setLevel(int newLevel) {
+            levelValue = newLevel;
+            invoke(setLevelMethod, javaLogger, levelObjects.get(newLevel));
+        }
+
+        public boolean isLoggable(int level) {
+            return (Boolean) invoke(isLoggableMethod, javaLogger, levelObjects.get(level));
+        }
+    }
+
+
+    private static String getLevelName(int level) {
+        switch (level) {
+            case OFF     : return "OFF";
+            case SEVERE  : return "SEVERE";
+            case WARNING : return "WARNING";
+            case INFO    : return "INFO";
+            case CONFIG  : return "CONFIG";
+            case FINE    : return "FINE";
+            case FINER   : return "FINER";
+            case FINEST  : return "FINEST";
+            case ALL     : return "ALL";
+            default      : return "UNKNOWN";
+        }
+    }
+
+}
--- a/src/share/demo/jvmti/waiters/Agent.cpp	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/demo/jvmti/waiters/Agent.cpp	Sat Oct 03 01:22:26 2009 +0100
@@ -72,36 +72,30 @@
 {
     jvmtiError err;
     Monitor   *m;
+    jlong      tag;
 
-    /* We use tags to track these, the tag is the Monitor pointer */
-    err = jvmti->RawMonitorEnter(lock); {
-        check_jvmti_error(jvmti, err, "raw monitor enter");
-
-        /* The raw monitor enter/exit protects us from creating two
-         *   instances for the same object.
-         */
-        jlong tag;
-
-        m   = NULL;
-        tag = (jlong)0;
-        err = jvmti->GetTag(object, &tag);
-        check_jvmti_error(jvmti, err, "get tag");
+    m   = NULL;
+    tag = (jlong)0;
+    err = jvmti->GetTag(object, &tag);
+    check_jvmti_error(jvmti, err, "get tag");
+    /*LINTED*/
+    m = (Monitor *)(void *)(ptrdiff_t)tag;
+    if ( m == NULL ) {
+        m = new Monitor(jvmti, env, object);
+        /* Save monitor on list */
+        if (monitor_count == monitor_list_size) {
+            monitor_list_size += monitor_list_grow_size;
+            monitor_list = (Monitor**)realloc((void*)monitor_list,
+                (monitor_list_size)*(int)sizeof(Monitor*));
+        }
+        monitor_list[monitor_count] = m;
+        m->set_slot(monitor_count);
+        monitor_count++;
         /*LINTED*/
-        m = (Monitor *)(void *)(ptrdiff_t)tag;
-        if ( m == NULL ) {
-            m = new Monitor(jvmti, env, object);
-            /*LINTED*/
-            tag = (jlong)(ptrdiff_t)(void *)m;
-            err = jvmti->SetTag(object, tag);
-            check_jvmti_error(jvmti, err, "set tag");
-            /* Save monitor on list */
-            monitor_list = (Monitor**)realloc((void*)monitor_list,
-                                (monitor_count+1)*(int)sizeof(Monitor*));
-            monitor_list[monitor_count++] = m;
-        }
-    } err = jvmti->RawMonitorExit(lock);
-    check_jvmti_error(jvmti, err, "raw monitor exit");
-
+        tag = (jlong)(ptrdiff_t)(void *)m;
+        err = jvmti->SetTag(object, tag);
+        check_jvmti_error(jvmti, err, "set tag");
+    }
     return m;
 }
 
@@ -112,12 +106,11 @@
 
     stdout_message("Agent created..\n");
     stdout_message("VMInit...\n");
-    /* Create a Monitor lock to use */
-    err = jvmti->CreateRawMonitor("waiters Agent lock", &lock);
-    check_jvmti_error(jvmti, err, "create raw monitor");
     /* Start monitor list */
     monitor_count = 0;
-    monitor_list  = (Monitor**)malloc((int)sizeof(Monitor*));
+    monitor_list_size = initial_monitor_list_size;
+    monitor_list = (Monitor**)
+        malloc(monitor_list_size*(int)sizeof(Monitor*));
 }
 
 Agent::~Agent()
@@ -134,9 +127,6 @@
         delete monitor_list[i];
     }
     free(monitor_list);
-    /* Destroy the Monitor lock to use */
-    err = jvmti->DestroyRawMonitor(lock);
-    check_jvmti_error(jvmti, err, "destroy raw monitor");
     /* Print death message */
     stdout_message("VMDeath...\n");
 }
@@ -215,8 +205,16 @@
     /* We just cast the tag to a C++ pointer and delete it.
      *   we know it can only be a Monitor *.
      */
-    Monitor *m;
+    Monitor   *m;
     /*LINTED*/
     m = (Monitor *)(ptrdiff_t)tag;
+    if (monitor_count > 1) {
+        /* Move the last element to this Monitor's slot */
+        int slot = m->get_slot();
+        Monitor *last = monitor_list[monitor_count-1];
+        monitor_list[slot] = last;
+        last->set_slot(slot);
+    }
+    monitor_count--;
     delete m;
 }
--- a/src/share/demo/jvmti/waiters/Agent.hpp	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/demo/jvmti/waiters/Agent.hpp	Sat Oct 03 01:22:26 2009 +0100
@@ -34,8 +34,12 @@
 class Agent {
 
   private:
-    jrawMonitorID lock;
+    enum {
+      initial_monitor_list_size = 64,
+      monitor_list_grow_size = 16
+    };
     Monitor     **monitor_list;
+    unsigned      monitor_list_size;
     unsigned      monitor_count;
     Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
     Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
--- a/src/share/demo/jvmti/waiters/Monitor.cpp	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/demo/jvmti/waiters/Monitor.cpp	Sat Oct 03 01:22:26 2009 +0100
@@ -73,6 +73,16 @@
         name, contends, waits, timeouts);
 }
 
+int Monitor::get_slot()
+{
+    return slot;
+}
+
+void Monitor::set_slot(int aslot)
+{
+    slot = aslot;
+}
+
 void Monitor::contended()
 {
     contends++;
--- a/src/share/demo/jvmti/waiters/Monitor.hpp	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/demo/jvmti/waiters/Monitor.hpp	Sat Oct 03 01:22:26 2009 +0100
@@ -35,6 +35,7 @@
 
   private:
     char     name[64];
+    int      slot;
     unsigned contends;
     unsigned waits;
     unsigned timeouts;
@@ -42,6 +43,8 @@
   public:
     Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
     ~Monitor();
+    int get_slot();
+    void set_slot(int i);
     void contended();
     void waited();
     void timeout();
--- a/src/share/javavm/export/jvm.h	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/javavm/export/jvm.h	Sat Oct 03 01:22:26 2009 +0100
@@ -375,6 +375,12 @@
 JVM_ResolveClass(JNIEnv *env, jclass cls);
 
 /*
+ * Find a class from a boot class loader. Returns NULL if class not found.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
+
+/*
  * Find a class from a given class loader. Throw ClassNotFoundException
  * or NoClassDefFoundError depending on the value of the last
  * argument.
--- a/src/share/lib/net.properties	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/lib/net.properties	Sat Oct 03 01:22:26 2009 +0100
@@ -32,7 +32,7 @@
 #
 # http.proxyHost=
 # http.proxyPort=80
-# http.nonProxyHosts=localhost|127.0.0.1
+http.nonProxyHosts=localhost|127.*|[::1]
 #
 # HTTPS Proxy Settings. proxyHost is the name of the proxy server
 # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
@@ -49,7 +49,7 @@
 #
 # ftp.proxyHost=
 # ftp.proxyPort=80
-# ftp.nonProxyHosts=localhost|127.0.0.1
+ftp.nonProxyHosts=localhost|127.*|[::1]
 #
 # Gopher Proxy settings. proxyHost is the name of the proxy server
 # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
--- a/src/share/native/java/lang/ClassLoader.c	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/native/java/lang/ClassLoader.c	Sat Oct 03 01:22:26 2009 +0100
@@ -237,6 +237,9 @@
     JVM_ResolveClass(env, cls);
 }
 
+/*
+ * Returns NULL if class not found.
+ */
 JNIEXPORT jclass JNICALL
 Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
                                               jstring classname)
@@ -246,7 +249,6 @@
     char buf[128];
 
     if (classname == NULL) {
-        JNU_ThrowClassNotFoundException(env, 0);
         return 0;
     }
 
@@ -258,11 +260,10 @@
     VerifyFixClassname(clname);
 
     if (!VerifyClassname(clname, JNI_TRUE)) {  /* expects slashed name */
-        JNU_ThrowClassNotFoundException(env, clname);
         goto done;
     }
 
-    cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE);
+    cls = JVM_FindClassFromBootLoader(env, clname);
 
  done:
     if (clname != buf) {
--- a/src/share/native/sun/security/ec/ECC_JNI.cpp	Tue Sep 29 14:24:18 2009 +0100
+++ b/src/share/native/sun/security/ec/ECC_JNI.cpp	Sat Oct 03 01:22:26 2009 +0100
@@ -24,7 +24,7 @@
  */
 
 #include <jni.h>
-#include "ecc_impl.h"
+#include "impl/ecc_impl.h"
 
 #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
 #define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
--- a/src/share/native/sun/security/ec/ec.c	Tue Sep 29 14:24:18 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1099 +0,0 @@
-/* *********************************************************************
- *
- * Sun elects to have this file available under and governed by the
- * Mozilla Public License Version 1.1 ("MPL") (see
- * http://www.mozilla.org/MPL/ for full license text). For the avoidance
- * of doubt and subject to the following, Sun also elects to allow
- * licensees to use this file under the MPL, the GNU General Public
- * License version 2 only or the Lesser General Public License version
- * 2.1 only. Any references to the "GNU General Public License version 2
- * or later" or "GPL" in the following shall be construed to mean the
- * GNU General Public License version 2 only. Any references to the "GNU
- * Lesser General Public License version 2.1 or later" or "LGPL" in the
- * following shall be construed to mean the GNU Lesser General Public
- * License version 2.1 only. However, the following notice accompanied
- * the original version of this file:
- *
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Elliptic Curve Cryptography library.
- *
- * The Initial Developer of the Original Code is
- * Sun Microsystems, Inc.
- * Portions created by the Initial Developer are Copyright (C) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dr Vipul Gupta <vipul.gupta@sun.com> and
- *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- *********************************************************************** */
-/*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident   "%Z%%M% %I%     %E% SMI"
-
-#include "mplogic.h"
-#include "ec.h"
-#include "ecl.h"
-
-#include <sys/types.h>
-#ifndef _KERNEL
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef _WIN32
-#include <strings.h>
-#endif /* _WIN32 */
-
-#endif
-#include "ecl-exp.h"
-#include "mpi.h"
-#include "ecc_impl.h"
-
-#ifdef _KERNEL
-#define PORT_ZFree(p, l)                bzero((p), (l)); kmem_free((p), (l))
-#else
-#ifndef _WIN32
-#define PORT_ZFree(p, l)                bzero((p), (l)); free((p))
-#else
-#define PORT_ZFree(p, l)                memset((p), 0, (l)); free((p))
-#endif /* _WIN32 */
-#endif
-
-/*
- * Returns true if pointP is the point at infinity, false otherwise
- */
-PRBool
-ec_point_at_infinity(SECItem *pointP)
-{
-    unsigned int i;
-
-    for (i = 1; i < pointP->len; i++) {
-        if (pointP->data[i] != 0x00) return PR_FALSE;
-    }
-
-    return PR_TRUE;
-}
-
-/*
- * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
- * the curve whose parameters are encoded in params with base point G.
- */
-SECStatus
-ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
-             const SECItem *pointP, SECItem *pointQ, int kmflag)
-{
-    mp_int Px, Py, Qx, Qy;
-    mp_int Gx, Gy, order, irreducible, a, b;
-#if 0 /* currently don't support non-named curves */
-    unsigned int irr_arr[5];
-#endif
-    ECGroup *group = NULL;
-    SECStatus rv = SECFailure;
-    mp_err err = MP_OKAY;
-    int len;
-
-#if EC_DEBUG
-    int i;
-    char mpstr[256];
-
-    printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
-    for (i = 0; i < params->DEREncoding.len; i++)
-            printf("%02x:", params->DEREncoding.data[i]);
-    printf("\n");
-
-        if (k1 != NULL) {
-                mp_tohex(k1, mpstr);
-                printf("ec_points_mul: scalar k1: %s\n", mpstr);
-                mp_todecimal(k1, mpstr);
-                printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
-        }
-
-        if (k2 != NULL) {
-                mp_tohex(k2, mpstr);
-                printf("ec_points_mul: scalar k2: %s\n", mpstr);
-                mp_todecimal(k2, mpstr);
-                printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
-        }
-
-        if (pointP != NULL) {
-                printf("ec_points_mul: pointP [len=%d]:", pointP->len);
-                for (i = 0; i < pointP->len; i++)
-                        printf("%02x:", pointP->data[i]);
-                printf("\n");
-        }
-#endif
-
-        /* NOTE: We only support uncompressed points for now */
-        len = (params->fieldID.size + 7) >> 3;
-        if (pointP != NULL) {
-                if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
-                        (pointP->len != (2 * len + 1))) {
-                        return SECFailure;
-                };
-        }
-
-        MP_DIGITS(&Px) = 0;
-        MP_DIGITS(&Py) = 0;
-        MP_DIGITS(&Qx) = 0;
-        MP_DIGITS(&Qy) = 0;
-        MP_DIGITS(&Gx) = 0;
-        MP_DIGITS(&Gy) = 0;
-        MP_DIGITS(&order) = 0;
-        MP_DIGITS(&irreducible) = 0;
-        MP_DIGITS(&a) = 0;
-        MP_DIGITS(&b) = 0;
-        CHECK_MPI_OK( mp_init(&Px, kmflag) );
-        CHECK_MPI_OK( mp_init(&Py, kmflag) );
-        CHECK_MPI_OK( mp_init(&Qx, kmflag) );
-        CHECK_MPI_OK( mp_init(&Qy, kmflag) );
-        CHECK_MPI_OK( mp_init(&Gx, kmflag) );
-        CHECK_MPI_OK( mp_init(&Gy, kmflag) );
-        CHECK_MPI_OK( mp_init(&order, kmflag) );
-        CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
-        CHECK_MPI_OK( mp_init(&a, kmflag) );
-        CHECK_MPI_OK( mp_init(&b, kmflag) );
-
-        if ((k2 != NULL) && (pointP != NULL)) {
-                /* Initialize Px and Py */
-                CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
-                CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
-        }
-
-        /* construct from named params, if possible */
-        if (params->name != ECCurve_noName) {
-                group = ECGroup_fromName(params->name, kmflag);
-        }
-
-#if 0 /* currently don't support non-named curves */
-        if (group == NULL) {
-                /* Set up mp_ints containing the curve coefficients */
-                CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
-                                                                                  (mp_size) len) );
-                CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
-                                                                                  (mp_size) len) );
-                SECITEM_TO_MPINT( params->order, &order );
-                SECITEM_TO_MPINT( params->curve.a, &a );
-                SECITEM_TO_MPINT( params->curve.b, &b );
-                if (params->fieldID.type == ec_field_GFp) {
-                        SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
-                        group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
-                } else {
-                        SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
-                        irr_arr[0] = params->fieldID.size;
-                        irr_arr[1] = params->fieldID.k1;
-                        irr_arr[2] = params->fieldID.k2;
-                        irr_arr[3] = params->fieldID.k3;
-                        irr_arr[4] = 0;
-                        group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
-                }
-        }
-#endif
-        if (group == NULL)
-                goto cleanup;
-
-        if ((k2 != NULL) && (pointP != NULL)) {
-                CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
-        } else {
-                CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
-    }
-
-    /* Construct the SECItem representation of point Q */
-    pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
-    CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
-                                      (mp_size) len) );
-    CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
-                                      (mp_size) len) );
-
-    rv = SECSuccess;
-
-#if EC_DEBUG
-    printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
-    for (i = 0; i < pointQ->len; i++)
-            printf("%02x:", pointQ->data[i]);
-    printf("\n");
-#endif
-
-cleanup:
-    ECGroup_free(group);
-    mp_clear(&Px);
-    mp_clear(&Py);
-    mp_clear(&Qx);
-    mp_clear(&Qy);
-    mp_clear(&Gx);
-    mp_clear(&Gy);
-    mp_clear(&order);
-    mp_clear(&irreducible);
-    mp_clear(&a);
-    mp_clear(&b);
-    if (err) {
-        MP_TO_SEC_ERROR(err);
-        rv = SECFailure;
-    }
-
-    return rv;
-}
-
-/* Generates a new EC key pair. The private key is a supplied
- * value and the public key is the result of performing a scalar
- * point multiplication of that value with the curve's base point.
- */
-SECStatus
-ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
-    const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    PRArenaPool *arena;
-    ECPrivateKey *key;
-    mp_int k;
-    mp_err err = MP_OKAY;
-    int len;
-
-#if EC_DEBUG
-    printf("ec_NewKey called\n");
-#endif
-
-#ifndef _WIN32
-int printf();
-#endif /* _WIN32 */
-
-    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    /* Initialize an arena for the EC key. */
-    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
-        return SECFailure;
-
-    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
-        kmflag);
-    if (!key) {
-        PORT_FreeArena(arena, PR_TRUE);
-        return SECFailure;
-    }
-
-    /* Set the version number (SEC 1 section C.4 says it should be 1) */
-    SECITEM_AllocItem(arena, &key->version, 1, kmflag);
-    key->version.data[0] = 1;
-
-    /* Copy all of the fields from the ECParams argument to the
-     * ECParams structure within the private key.
-     */
-    key->ecParams.arena = arena;
-    key->ecParams.type = ecParams->type;
-    key->ecParams.fieldID.size = ecParams->fieldID.size;
-    key->ecParams.fieldID.type = ecParams->fieldID.type;
-    if (ecParams->fieldID.type == ec_field_GFp) {
-        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
-            &ecParams->fieldID.u.prime, kmflag));
-    } else {
-        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
-            &ecParams->fieldID.u.poly, kmflag));
-    }
-    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
-    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
-    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
-        &ecParams->curve.a, kmflag));
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
-        &ecParams->curve.b, kmflag));
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
-        &ecParams->curve.seed, kmflag));
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
-        &ecParams->base, kmflag));
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
-        &ecParams->order, kmflag));
-    key->ecParams.cofactor = ecParams->cofactor;
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
-        &ecParams->DEREncoding, kmflag));
-    key->ecParams.name = ecParams->name;
-    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
-        &ecParams->curveOID, kmflag));
-
-    len = (ecParams->fieldID.size + 7) >> 3;
-    SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
-    len = ecParams->order.len;
-    SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
-
-    /* Copy private key */
-    if (privKeyLen >= len) {
-        memcpy(key->privateValue.data, privKeyBytes, len);
-    } else {
-        memset(key->privateValue.data, 0, (len - privKeyLen));
-        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
-    }
-
-    /* Compute corresponding public key */
-    MP_DIGITS(&k) = 0;
-    CHECK_MPI_OK( mp_init(&k, kmflag) );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
-        (mp_size) len) );
-
-    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
-    if (rv != SECSuccess) goto cleanup;
-    *privKey = key;
-
-cleanup:
-    mp_clear(&k);
-    if (rv)
-        PORT_FreeArena(arena, PR_TRUE);
-
-#if EC_DEBUG
-    printf("ec_NewKey returning %s\n",
-        (rv == SECSuccess) ? "success" : "failure");
-#endif
-
-    return rv;
-
-}
-
-/* Generates a new EC key pair. The private key is a supplied
- * random value (in seed) and the public key is the result of
- * performing a scalar point multiplication of that value with
- * the curve's base point.
- */
-SECStatus
-EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
-    const unsigned char *seed, int seedlen, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
-    return rv;
-}
-
-/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
- * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
- * random number generator.
- *
- * Parameters
- * - order: a buffer that holds the curve's group order
- * - len: the length in octets of the order buffer
- * - random: a buffer of 2 * len random bytes
- * - randomlen: the length in octets of the random buffer
- *
- * Return Value
- * Returns a buffer of len octets that holds the private key. The caller
- * is responsible for freeing the buffer with PORT_ZFree.
- */
-static unsigned char *
-ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
-    const unsigned char *random, int randomlen, int kmflag)
-{
-    SECStatus rv = SECSuccess;
-    mp_err err;
-    unsigned char *privKeyBytes = NULL;
-    mp_int privKeyVal, order_1, one;
-
-    MP_DIGITS(&privKeyVal) = 0;
-    MP_DIGITS(&order_1) = 0;
-    MP_DIGITS(&one) = 0;
-    CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
-    CHECK_MPI_OK( mp_init(&order_1, kmflag) );
-    CHECK_MPI_OK( mp_init(&one, kmflag) );
-
-    /*
-     * Reduces the 2*len buffer of random bytes modulo the group order.
-     */
-    if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
-    if (randomlen != 2 * len) {
-        randomlen = 2 * len;
-    }
-    /* No need to generate - random bytes are now supplied */
-    /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
-    memcpy(privKeyBytes, random, randomlen);
-
-    CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
-    CHECK_MPI_OK( mp_set_int(&one, 1) );
-    CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
-    CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
-    CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
-    CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
-    memset(privKeyBytes+len, 0, len);
-cleanup:
-    mp_clear(&privKeyVal);
-    mp_clear(&order_1);
-    mp_clear(&one);
-    if (err < MP_OKAY) {
-        MP_TO_SEC_ERROR(err);
-        rv = SECFailure;
-    }
-    if (rv != SECSuccess && privKeyBytes) {
-#ifdef _KERNEL
-        kmem_free(privKeyBytes, 2*len);
-#else
-        free(privKeyBytes);
-#endif
-        privKeyBytes = NULL;
-    }
-    return privKeyBytes;
-}
-
-/* Generates a new EC key pair. The private key is a random value and
- * the public key is the result of performing a scalar point multiplication
- * of that value with the curve's base point.
- */
-SECStatus
-EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
-    const unsigned char* random, int randomlen, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    int len;
-    unsigned char *privKeyBytes = NULL;
-
-    if (!ecParams) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    len = ecParams->order.len;
-    privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
-        random, randomlen, kmflag);
-    if (privKeyBytes == NULL) goto cleanup;
-    /* generate public key */
-    CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
-
-cleanup:
-    if (privKeyBytes) {
-        PORT_ZFree(privKeyBytes, len * 2);
-    }
-#if EC_DEBUG
-    printf("EC_NewKey returning %s\n",
-        (rv == SECSuccess) ? "success" : "failure");
-#endif
-
-    return rv;
-}
-
-/* Validates an EC public key as described in Section 5.2.2 of
- * X9.62. The ECDH primitive when used without the cofactor does
- * not address small subgroup attacks, which may occur when the
- * public key is not valid. These attacks can be prevented by
- * validating the public key before using ECDH.
- */
-SECStatus
-EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
-{
-    mp_int Px, Py;
-    ECGroup *group = NULL;
-    SECStatus rv = SECFailure;
-    mp_err err = MP_OKAY;
-    int len;
-
-    if (!ecParams || !publicValue) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    /* NOTE: We only support uncompressed points for now */
-    len = (ecParams->fieldID.size + 7) >> 3;
-    if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
-        return SECFailure;
-    } else if (publicValue->len != (2 * len + 1)) {
-        PORT_SetError(SEC_ERROR_BAD_KEY);
-        return SECFailure;
-    }
-
-    MP_DIGITS(&Px) = 0;
-    MP_DIGITS(&Py) = 0;
-    CHECK_MPI_OK( mp_init(&Px, kmflag) );
-    CHECK_MPI_OK( mp_init(&Py, kmflag) );
-
-    /* Initialize Px and Py */
-    CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
-
-    /* construct from named params */
-    group = ECGroup_fromName(ecParams->name, kmflag);
-    if (group == NULL) {
-        /*
-         * ECGroup_fromName fails if ecParams->name is not a valid
-         * ECCurveName value, or if we run out of memory, or perhaps
-         * for other reasons.  Unfortunately if ecParams->name is a
-         * valid ECCurveName value, we don't know what the right error
-         * code should be because ECGroup_fromName doesn't return an
-         * error code to the caller.  Set err to MP_UNDEF because
-         * that's what ECGroup_fromName uses internally.
-         */
-        if ((ecParams->name <= ECCurve_noName) ||
-            (ecParams->name >= ECCurve_pastLastCurve)) {
-            err = MP_BADARG;
-        } else {
-            err = MP_UNDEF;
-        }
-        goto cleanup;
-    }
-
-    /* validate public point */
-    if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
-        if (err == MP_NO) {
-            PORT_SetError(SEC_ERROR_BAD_KEY);
-            rv = SECFailure;
-            err = MP_OKAY;  /* don't change the error code */
-        }
-        goto cleanup;
-    }
-
-    rv = SECSuccess;
-
-cleanup:
-    ECGroup_free(group);
-    mp_clear(&Px);
-    mp_clear(&Py);
-    if (err) {
-        MP_TO_SEC_ERROR(err);
-        rv = SECFailure;
-    }
-    return rv;
-}
-
-/*
-** Performs an ECDH key derivation by computing the scalar point
-** multiplication of privateValue and publicValue (with or without the
-** cofactor) and returns the x-coordinate of the resulting elliptic
-** curve point in derived secret.  If successful, derivedSecret->data
-** is set to the address of the newly allocated buffer containing the
-** derived secret, and derivedSecret->len is the size of the secret
-** produced. It is the caller's responsibility to free the allocated
-** buffer containing the derived secret.
-*/
-SECStatus
-ECDH_Derive(SECItem  *publicValue,
-            ECParams *ecParams,
-            SECItem  *privateValue,
-            PRBool    withCofactor,
-            SECItem  *derivedSecret,
-            int kmflag)
-{
-    SECStatus rv = SECFailure;
-    unsigned int len = 0;
-    SECItem pointQ = {siBuffer, NULL, 0};
-    mp_int k; /* to hold the private value */
-    mp_int cofactor;
-    mp_err err = MP_OKAY;
-#if EC_DEBUG
-    int i;
-#endif
-
-    if (!publicValue || !ecParams || !privateValue ||
-        !derivedSecret) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    memset(derivedSecret, 0, sizeof *derivedSecret);
-    len = (ecParams->fieldID.size + 7) >> 3;
-    pointQ.len = 2*len + 1;
-    if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
-
-    MP_DIGITS(&k) = 0;
-    CHECK_MPI_OK( mp_init(&k, kmflag) );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
-                                          (mp_size) privateValue->len) );
-
-    if (withCofactor && (ecParams->cofactor != 1)) {
-            /* multiply k with the cofactor */
-            MP_DIGITS(&cofactor) = 0;
-            CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
-            mp_set(&cofactor, ecParams->cofactor);
-            CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
-    }
-
-    /* Multiply our private key and peer's public point */
-    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
-        ec_point_at_infinity(&pointQ))
-        goto cleanup;
-
-    /* Allocate memory for the derived secret and copy
-     * the x co-ordinate of pointQ into it.
-     */
-    SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
-    memcpy(derivedSecret->data, pointQ.data + 1, len);
-
-    rv = SECSuccess;
-
-#if EC_DEBUG
-    printf("derived_secret:\n");
-    for (i = 0; i < derivedSecret->len; i++)
-        printf("%02x:", derivedSecret->data[i]);
-    printf("\n");
-#endif
-
-cleanup:
-    mp_clear(&k);
-
-    if (pointQ.data) {
-        PORT_ZFree(pointQ.data, 2*len + 1);
-    }
-
-    return rv;
-}
-
-/* Computes the ECDSA signature (a concatenation of two values r and s)
- * on the digest using the given key and the random value kb (used in
- * computing s).
- */
-SECStatus
-ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
-    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    mp_int x1;
-    mp_int d, k;     /* private key, random integer */
-    mp_int r, s;     /* tuple (r, s) is the signature */
-    mp_int n;
-    mp_err err = MP_OKAY;
-    ECParams *ecParams = NULL;
-    SECItem kGpoint = { siBuffer, NULL, 0};
-    int flen = 0;    /* length in bytes of the field size */
-    unsigned olen;   /* length in bytes of the base point order */
-
-#if EC_DEBUG
-    char mpstr[256];
-#endif
-
-    /* Initialize MPI integers. */
-    /* must happen before the first potential call to cleanup */
-    MP_DIGITS(&x1) = 0;
-    MP_DIGITS(&d) = 0;
-    MP_DIGITS(&k) = 0;
-    MP_DIGITS(&r) = 0;
-    MP_DIGITS(&s) = 0;
-    MP_DIGITS(&n) = 0;
-
-    /* Check args */
-    if (!key || !signature || !digest || !kb || (kblen < 0)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        goto cleanup;
-    }
-
-    ecParams = &(key->ecParams);
-    flen = (ecParams->fieldID.size + 7) >> 3;
-    olen = ecParams->order.len;
-    if (signature->data == NULL) {
-        /* a call to get the signature length only */
-        goto finish;
-    }
-    if (signature->len < 2*olen) {
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-        rv = SECBufferTooSmall;
-        goto cleanup;
-    }
-
-
-    CHECK_MPI_OK( mp_init(&x1, kmflag) );
-    CHECK_MPI_OK( mp_init(&d, kmflag) );
-    CHECK_MPI_OK( mp_init(&k, kmflag) );
-    CHECK_MPI_OK( mp_init(&r, kmflag) );
-    CHECK_MPI_OK( mp_init(&s, kmflag) );
-    CHECK_MPI_OK( mp_init(&n, kmflag) );
-
-    SECITEM_TO_MPINT( ecParams->order, &n );
-    SECITEM_TO_MPINT( key->privateValue, &d );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
-    /* Make sure k is in the interval [1, n-1] */
-    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
-#if EC_DEBUG
-        printf("k is outside [1, n-1]\n");
-        mp_tohex(&k, mpstr);
-        printf("k : %s \n", mpstr);
-        mp_tohex(&n, mpstr);
-        printf("n : %s \n", mpstr);
-#endif
-        PORT_SetError(SEC_ERROR_NEED_RANDOM);
-        goto cleanup;
-    }
-
-    /*
-    ** ANSI X9.62, Section 5.3.2, Step 2
-    **
-    ** Compute kG
-    */
-    kGpoint.len = 2*flen + 1;
-    kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
-    if ((kGpoint.data == NULL) ||
-        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
-            != SECSuccess))
-        goto cleanup;
-
-    /*
-    ** ANSI X9.62, Section 5.3.3, Step 1
-    **
-    ** Extract the x co-ordinate of kG into x1
-    */
-    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
-                                          (mp_size) flen) );
-
-    /*
-    ** ANSI X9.62, Section 5.3.3, Step 2
-    **
-    ** r = x1 mod n  NOTE: n is the order of the curve
-    */
-    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
-
-    /*
-    ** ANSI X9.62, Section 5.3.3, Step 3
-    **
-    ** verify r != 0
-    */
-    if (mp_cmp_z(&r) == 0) {
-        PORT_SetError(SEC_ERROR_NEED_RANDOM);
-        goto cleanup;
-    }
-
-    /*
-    ** ANSI X9.62, Section 5.3.3, Step 4
-    **
-    ** s = (k**-1 * (HASH(M) + d*r)) mod n
-    */
-    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
-
-    /* In the definition of EC signing, digests are truncated
-     * to the length of n in bits.
-     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
-    if (digest->len*8 > ecParams->fieldID.size) {
-        mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
-    }
-
-#if EC_DEBUG
-    mp_todecimal(&n, mpstr);
-    printf("n : %s (dec)\n", mpstr);
-    mp_todecimal(&d, mpstr);
-    printf("d : %s (dec)\n", mpstr);
-    mp_tohex(&x1, mpstr);
-    printf("x1: %s\n", mpstr);
-    mp_todecimal(&s, mpstr);
-    printf("digest: %s (decimal)\n", mpstr);
-    mp_todecimal(&r, mpstr);
-    printf("r : %s (dec)\n", mpstr);
-    mp_tohex(&r, mpstr);
-    printf("r : %s\n", mpstr);
-#endif
-
-    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
-    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
-    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
-    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
-
-#if EC_DEBUG
-    mp_todecimal(&s, mpstr);
-    printf("s : %s (dec)\n", mpstr);
-    mp_tohex(&s, mpstr);
-    printf("s : %s\n", mpstr);
-#endif
-
-    /*
-    ** ANSI X9.62, Section 5.3.3, Step 5
-    **
-    ** verify s != 0
-    */
-    if (mp_cmp_z(&s) == 0) {
-        PORT_SetError(SEC_ERROR_NEED_RANDOM);
-        goto cleanup;
-    }
-
-   /*
-    **
-    ** Signature is tuple (r, s)
-    */
-    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
-    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
-finish:
-    signature->len = 2*olen;
-
-    rv = SECSuccess;
-    err = MP_OKAY;
-cleanup:
-    mp_clear(&x1);
-    mp_clear(&d);
-    mp_clear(&k);
-    mp_clear(&r);
-    mp_clear(&s);
-    mp_clear(&n);
-
-    if (kGpoint.data) {
-        PORT_ZFree(kGpoint.data, 2*flen + 1);
-    }
-
-    if (err) {
-        MP_TO_SEC_ERROR(err);
-        rv = SECFailure;
-    }
-
-#if EC_DEBUG
-    printf("ECDSA signing with seed %s\n",
-        (rv == SECSuccess) ? "succeeded" : "failed");
-#endif
-
-   return rv;
-}
-
-/*
-** Computes the ECDSA signature on the digest using the given key
-** and a random seed.
-*/
-SECStatus
-ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
-    const unsigned char* random, int randomLen, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    int len;
-    unsigned char *kBytes= NULL;
-
-    if (!key) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    /* Generate random value k */
-    len = key->ecParams.order.len;
-    kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
-        random, randomLen, kmflag);
-    if (kBytes == NULL) goto cleanup;
-
-    /* Generate ECDSA signature with the specified k value */
-    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
-
-cleanup:
-    if (kBytes) {
-        PORT_ZFree(kBytes, len * 2);
-    }
-
-#if EC_DEBUG
-    printf("ECDSA signing %s\n",
-        (rv == SECSuccess) ? "succeeded" : "failed");
-#endif
-
-    return rv;
-}
-
-/*
-** Checks the signature on the given digest using the key provided.
-*/
-SECStatus
-ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
-                 const SECItem *digest, int kmflag)
-{
-    SECStatus rv = SECFailure;
-    mp_int r_, s_;           /* tuple (r', s') is received signature) */
-    mp_int c, u1, u2, v;     /* intermediate values used in verification */
-    mp_int x1;
-    mp_int n;
-    mp_err err = MP_OKAY;
-    ECParams *ecParams = NULL;
-    SECItem pointC = { siBuffer, NULL, 0 };
-    int slen;       /* length in bytes of a half signature (r or s) */
-    int flen;       /* length in bytes of the field size */
-    unsigned olen;  /* length in bytes of the base point order */
-
-#if EC_DEBUG
-    char mpstr[256];
-    printf("ECDSA verification called\n");
-#endif
-
-    /* Initialize MPI integers. */
-    /* must happen before the first potential call to cleanup */
-    MP_DIGITS(&r_) = 0;
-    MP_DIGITS(&s_) = 0;
-    MP_DIGITS(&c) = 0;
-    MP_DIGITS(&u1) = 0;
-    MP_DIGITS(&u2) = 0;
-    MP_DIGITS(&x1) = 0;
-    MP_DIGITS(&v)  = 0;
-    MP_DIGITS(&n)  = 0;
-
-    /* Check args */
-    if (!key || !signature || !digest) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        goto cleanup;
-    }
-
-    ecParams = &(key->ecParams);
-    flen = (ecParams->fieldID.size + 7) >> 3;
-    olen = ecParams->order.len;
-    if (signature->len == 0 || signature->len%2 != 0 ||
-        signature->len > 2*olen) {
-        PORT_SetError(SEC_ERROR_INPUT_LEN);
-        goto cleanup;
-    }
-    slen = signature->len/2;
-
-    SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
-    if (pointC.data == NULL)
-        goto cleanup;
-
-    CHECK_MPI_OK( mp_init(&r_, kmflag) );
-    CHECK_MPI_OK( mp_init(&s_, kmflag) );
-    CHECK_MPI_OK( mp_init(&c, kmflag)  );
-    CHECK_MPI_OK( mp_init(&u1, kmflag) );
-    CHECK_MPI_OK( mp_init(&u2, kmflag) );
-    CHECK_MPI_OK( mp_init(&x1, kmflag)  );
-    CHECK_MPI_OK( mp_init(&v, kmflag)  );
-    CHECK_MPI_OK( mp_init(&n, kmflag)  );
-
-    /*
-    ** Convert received signature (r', s') into MPI integers.
-    */
-    CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
-    CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
-
-    /*
-    ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
-    **
-    ** Verify that 0 < r' < n and 0 < s' < n
-    */
-    SECITEM_TO_MPINT(ecParams->order, &n);
-    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
-        mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
-        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-        goto cleanup; /* will return rv == SECFailure */
-    }
-
-    /*
-    ** ANSI X9.62, Section 5.4.2, Step 3
-    **
-    ** c = (s')**-1 mod n
-    */
-    CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */
-
-    /*
-    ** ANSI X9.62, Section 5.4.2, Step 4
-    **
-    ** u1 = ((HASH(M')) * c) mod n
-    */
-    SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */
-
-    /* In the definition of EC signing, digests are truncated
-     * to the length of n in bits.
-     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
-    if (digest->len*8 > ecParams->fieldID.size) {  /* u1 = HASH(M')     */
-        mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
-    }
-
-#if EC_DEBUG
-    mp_todecimal(&r_, mpstr);
-    printf("r_: %s (dec)\n", mpstr);
-    mp_todecimal(&s_, mpstr);
-    printf("s_: %s (dec)\n", mpstr);
-    mp_todecimal(&c, mpstr);
-    printf("c : %s (dec)\n", mpstr);
-    mp_todecimal(&u1, mpstr);
-    printf("digest: %s (dec)\n", mpstr);
-#endif
-
-    CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */
-
-    /*
-    ** ANSI X9.62, Section 5.4.2, Step 4
-    **
-    ** u2 = ((r') * c) mod n
-    */
-    CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
-
-    /*
-    ** ANSI X9.62, Section 5.4.3, Step 1
-    **
-    ** Compute u1*G + u2*Q
-    ** Here, A = u1.G     B = u2.Q    and   C = A + B
-    ** If the result, C, is the point at infinity, reject the signature
-    */
-    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
-        != SECSuccess) {
-        rv = SECFailure;
-        goto cleanup;
-    }
-    if (ec_point_at_infinity(&pointC)) {
-        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-        rv = SECFailure;
-        goto cleanup;
-    }
-
-    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
-
-    /*
-    ** ANSI X9.62, Section 5.4.4, Step 2
-    **
-    ** v = x1 mod n
-    */
-    CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
-
-#if EC_DEBUG
-    mp_todecimal(&r_, mpstr);
-    printf("r_: %s (dec)\n", mpstr);
-    mp_todecimal(&v, mpstr);
-    printf("v : %s (dec)\n", mpstr);
-#endif
-
-    /*
-    ** ANSI X9.62, Section 5.4.4, Step 3
-    **
-    ** Verification:  v == r'
-    */
-    if (mp_cmp(&v, &r_)) {
-        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-        rv = SECFailure; /* Signature failed to verify. */
-    } else {
-        rv = SECSuccess; /* Signature verified. */
-    }
-
-#if EC_DEBUG
-    mp_todecimal(&u1, mpstr);
-    printf("u1: %s (dec)\n", mpstr);
-    mp_todecimal(&u2, mpstr);
-    printf("u2: %s (dec)\n", mpstr);
-    mp_tohex(&x1, mpstr);
-    printf("x1: %s\n", mpstr);
-    mp_todecimal(&v, mpstr);
-    printf("v : %s (dec)\n", mpstr);
-#endif
-
-cleanup:
-    mp_clear(&r_);
-    mp_clear(&s_);
-    mp_clear(&c);
-    mp_clear(&u1);
-    mp_clear(&u2);
-    mp_clear(&x1);
-    mp_clear(&v);
-    mp_clear(&n);
-
-    if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
-    if (err) {
-        MP_TO_SEC_ERROR(err);
-        rv = SECFailure;
-    }
-
-#if EC_DEBUG
-    printf("ECDSA verification %s\n",
-        (rv == SECSuccess) ? "succeeded" : "failed");
-#endif
-
-    return rv;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/impl/ec.c	Sat Oct 03 01:22:26 2009 +0100
@@ -0,0 +1,1099 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Elliptic Curve Cryptography library.
+ *
+ * The Initial Developer of the Original Code is
+ * Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dr Vipul Gupta <vipul.gupta@sun.com> and
+ *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+#include "mplogic.h"
+#include "ec.h"
+#include "ecl.h"
+
+#include <sys/types.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <strings.h>
+#endif /* _WIN32 */
+
+#endif
+#include "ecl-exp.h"
+#include "mpi.h"
+#include "ecc_impl.h"
+
+#ifdef _KERNEL
+#define PORT_ZFree(p, l)                bzero((p), (l)); kmem_free((p), (l))
+#else
+#ifndef _WIN32
+#define PORT_ZFree(p, l)                bzero((p), (l)); free((p))
+#else
+#define PORT_ZFree(p, l)                memset((p), 0, (l)); free((p))
+#endif /* _WIN32 */
+#endif
+
+/*
+ * Returns true if pointP is the point at infinity, false otherwise
+ */
+PRBool
+ec_point_at_infinity(SECItem *pointP)
+{
+    unsigned int i;
+
+    for (i = 1; i < pointP->len; i++) {
+        if (pointP->data[i] != 0x00) return PR_FALSE;
+    }
+
+    return PR_TRUE;
+}
+
+/*
+ * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
+ * the curve whose parameters are encoded in params with base point G.
+ */
+SECStatus
+ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
+             const SECItem *pointP, SECItem *pointQ, int kmflag)
+{
+    mp_int Px, Py, Qx, Qy;
+    mp_int Gx, Gy, order, irreducible, a, b;
+#if 0 /* currently don't support non-named curves */
+    unsigned int irr_arr[5];
+#endif
+    ECGroup *group = NULL;
+    SECStatus rv = SECFailure;
+    mp_err err = MP_OKAY;
+    int len;
+
+#if EC_DEBUG
+    int i;
+    char mpstr[256];
+
+    printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
+    for (i = 0; i < params->DEREncoding.len; i++)
+            printf("%02x:", params->DEREncoding.data[i]);
+    printf("\n");
+
+        if (k1 != NULL) {
+                mp_tohex(k1, mpstr);
+                printf("ec_points_mul: scalar k1: %s\n", mpstr);
+                mp_todecimal(k1, mpstr);
+                printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
+        }
+
+        if (k2 != NULL) {
+                mp_tohex(k2, mpstr);
+                printf("ec_points_mul: scalar k2: %s\n", mpstr);
+                mp_todecimal(k2, mpstr);
+                printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
+        }
+
+        if (pointP != NULL) {
+                printf("ec_points_mul: pointP [len=%d]:", pointP->len);
+                for (i = 0; i < pointP->len; i++)
+                        printf("%02x:", pointP->data[i]);
+                printf("\n");
+        }
+#endif
+
+        /* NOTE: We only support uncompressed points for now */
+        len = (params->fieldID.size + 7) >> 3;
+        if (pointP != NULL) {
+                if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
+                        (pointP->len != (2 * len + 1))) {
+                        return SECFailure;
+                };
+        }
+
+        MP_DIGITS(&Px) = 0;
+        MP_DIGITS(&Py) = 0;
+        MP_DIGITS(&Qx) = 0;
+        MP_DIGITS(&Qy) = 0;
+        MP_DIGITS(&Gx) = 0;
+        MP_DIGITS(&Gy) = 0;
+        MP_DIGITS(&order) = 0;
+        MP_DIGITS(&irreducible) = 0;
+        MP_DIGITS(&a) = 0;
+        MP_DIGITS(&b) = 0;
+        CHECK_MPI_OK( mp_init(&Px, kmflag) );
+        CHECK_MPI_OK( mp_init(&Py, kmflag) );
+        CHECK_MPI_OK( mp_init(&Qx, kmflag) );
+        CHECK_MPI_OK( mp_init(&Qy, kmflag) );
+        CHECK_MPI_OK( mp_init(&Gx, kmflag) );
+        CHECK_MPI_OK( mp_init(&Gy, kmflag) );
+        CHECK_MPI_OK( mp_init(&order, kmflag) );
+        CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
+        CHECK_MPI_OK( mp_init(&a, kmflag) );
+        CHECK_MPI_OK( mp_init(&b, kmflag) );
+
+        if ((k2 != NULL) && (pointP != NULL)) {
+                /* Initialize Px and Py */
+                CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
+                CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
+        }
+
+        /* construct from named params, if possible */
+        if (params->name != ECCurve_noName) {
+                group = ECGroup_fromName(params->name, kmflag);
+        }
+
+#if 0 /* currently don't support non-named curves */
+        if (group == NULL) {
+                /* Set up mp_ints containing the curve coefficients */
+                CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
+                                                                                  (mp_size) len) );
+                CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
+                                                                                  (mp_size) len) );
+                SECITEM_TO_MPINT( params->order, &order );
+                SECITEM_TO_MPINT( params->curve.a, &a );
+                SECITEM_TO_MPINT( params->curve.b, &b );
+                if (params->fieldID.type == ec_field_GFp) {
+                        SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
+                        group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
+                } else {
+                        SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
+                        irr_arr[0] = params->fieldID.size;
+                        irr_arr[1] = params->fieldID.k1;
+                        irr_arr[2] = params->fieldID.k2;
+                        irr_arr[3] = params->fieldID.k3;
+                        irr_arr[4] = 0;
+                        group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
+                }
+        }
+#endif
+        if (group == NULL)
+                goto cleanup;
+
+        if ((k2 != NULL) && (pointP != NULL)) {
+                CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
+        } else {
+                CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
+    }
+
+    /* Construct the SECItem representation of point Q */
+    pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
+    CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
+                                      (mp_size) len) );
+    CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
+                                      (mp_size) len) );
+
+    rv = SECSuccess;
+
+#if EC_DEBUG
+    printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
+    for (i = 0; i < pointQ->len; i++)
+            printf("%02x:", pointQ->data[i]);
+    printf("\n");
+#endif
+
+cleanup:
+    ECGroup_free(group);
+    mp_clear(&Px);
+    mp_clear(&Py);
+    mp_clear(&Qx);
+    mp_clear(&Qy);
+    mp_clear(&Gx);
+    mp_clear(&Gy);
+    mp_clear(&order);
+    mp_clear(&irreducible);
+    mp_clear(&a);
+    mp_clear(&b);
+    if (err) {
+        MP_TO_SEC_ERROR(err);
+        rv = SECFailure;
+    }
+
+    return rv;
+}
+
+/* Generates a new EC key pair. The private key is a supplied
+ * value and the public key is the result of performing a scalar
+ * point multiplication of that value with the curve's base point.
+ */
+SECStatus
+ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+    const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    PRArenaPool *arena;
+    ECPrivateKey *key;
+    mp_int k;
+    mp_err err = MP_OKAY;
+    int len;
+
+#if EC_DEBUG
+    printf("ec_NewKey called\n");
+#endif
+
+#ifndef _WIN32
+int printf();
+#endif /* _WIN32 */
+
+    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    /* Initialize an arena for the EC key. */
+    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
+        return SECFailure;
+
+    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
+        kmflag);
+    if (!key) {
+        PORT_FreeArena(arena, PR_TRUE);
+        return SECFailure;
+    }
+
+    /* Set the version number (SEC 1 section C.4 says it should be 1) */
+    SECITEM_AllocItem(arena, &key->version, 1, kmflag);
+    key->version.data[0] = 1;
+
+    /* Copy all of the fields from the ECParams argument to the
+     * ECParams structure within the private key.
+     */
+    key->ecParams.arena = arena;
+    key->ecParams.type = ecParams->type;
+    key->ecParams.fieldID.size = ecParams->fieldID.size;
+    key->ecParams.fieldID.type = ecParams->fieldID.type;
+    if (ecParams->fieldID.type == ec_field_GFp) {
+        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
+            &ecParams->fieldID.u.prime, kmflag));
+    } else {
+        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
+            &ecParams->fieldID.u.poly, kmflag));
+    }
+    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
+    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
+    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
+        &ecParams->curve.a, kmflag));
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
+        &ecParams->curve.b, kmflag));
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
+        &ecParams->curve.seed, kmflag));
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
+        &ecParams->base, kmflag));
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
+        &ecParams->order, kmflag));
+    key->ecParams.cofactor = ecParams->cofactor;
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
+        &ecParams->DEREncoding, kmflag));
+    key->ecParams.name = ecParams->name;
+    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
+        &ecParams->curveOID, kmflag));
+
+    len = (ecParams->fieldID.size + 7) >> 3;
+    SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
+    len = ecParams->order.len;
+    SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
+
+    /* Copy private key */
+    if (privKeyLen >= len) {
+        memcpy(key->privateValue.data, privKeyBytes, len);
+    } else {
+        memset(key->privateValue.data, 0, (len - privKeyLen));
+        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
+    }
+
+    /* Compute corresponding public key */
+    MP_DIGITS(&k) = 0;
+    CHECK_MPI_OK( mp_init(&k, kmflag) );
+    CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
+        (mp_size) len) );
+
+    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
+    if (rv != SECSuccess) goto cleanup;
+    *privKey = key;
+
+cleanup:
+    mp_clear(&k);
+    if (rv)
+        PORT_FreeArena(arena, PR_TRUE);
+
+#if EC_DEBUG
+    printf("ec_NewKey returning %s\n",
+        (rv == SECSuccess) ? "success" : "failure");
+#endif
+
+    return rv;
+
+}
+
+/* Generates a new EC key pair. The private key is a supplied
+ * random value (in seed) and the public key is the result of
+ * performing a scalar point multiplication of that value with
+ * the curve's base point.
+ */
+SECStatus
+EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
+    const unsigned char *seed, int seedlen, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
+    return rv;
+}
+
+/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
+ * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
+ * random number generator.
+ *
+ * Parameters
+ * - order: a buffer that holds the curve's group order
+ * - len: the length in octets of the order buffer
+ * - random: a buffer of 2 * len random bytes
+ * - randomlen: the length in octets of the random buffer
+ *
+ * Return Value
+ * Returns a buffer of len octets that holds the private key. The caller
+ * is responsible for freeing the buffer with PORT_ZFree.
+ */
+static unsigned char *
+ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
+    const unsigned char *random, int randomlen, int kmflag)
+{
+    SECStatus rv = SECSuccess;
+    mp_err err;
+    unsigned char *privKeyBytes = NULL;
+    mp_int privKeyVal, order_1, one;
+
+    MP_DIGITS(&privKeyVal) = 0;
+    MP_DIGITS(&order_1) = 0;
+    MP_DIGITS(&one) = 0;
+    CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
+    CHECK_MPI_OK( mp_init(&order_1, kmflag) );
+    CHECK_MPI_OK( mp_init(&one, kmflag) );
+
+    /*
+     * Reduces the 2*len buffer of random bytes modulo the group order.
+     */
+    if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
+    if (randomlen != 2 * len) {
+        randomlen = 2 * len;
+    }
+    /* No need to generate - random bytes are now supplied */
+    /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
+    memcpy(privKeyBytes, random, randomlen);
+
+    CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
+    CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
+    CHECK_MPI_OK( mp_set_int(&one, 1) );
+    CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
+    CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
+    CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
+    CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
+    memset(privKeyBytes+len, 0, len);
+cleanup:
+    mp_clear(&privKeyVal);
+    mp_clear(&order_1);
+    mp_clear(&one);
+    if (err < MP_OKAY) {
+        MP_TO_SEC_ERROR(err);
+        rv = SECFailure;
+    }
+    if (rv != SECSuccess && privKeyBytes) {
+#ifdef _KERNEL
+        kmem_free(privKeyBytes, 2*len);
+#else
+        free(privKeyBytes);
+#endif
+        privKeyBytes = NULL;
+    }
+    return privKeyBytes;
+}
+
+/* Generates a new EC key pair. The private key is a random value and
+ * the public key is the result of performing a scalar point multiplication
+ * of that value with the curve's base point.
+ */
+SECStatus
+EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+    const unsigned char* random, int randomlen, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    int len;
+    unsigned char *privKeyBytes = NULL;
+
+    if (!ecParams) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    len = ecParams->order.len;
+    privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
+        random, randomlen, kmflag);
+    if (privKeyBytes == NULL) goto cleanup;
+    /* generate public key */
+    CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
+
+cleanup:
+    if (privKeyBytes) {
+        PORT_ZFree(privKeyBytes, len * 2);
+    }
+#if EC_DEBUG
+    printf("EC_NewKey returning %s\n",
+        (rv == SECSuccess) ? "success" : "failure");
+#endif
+
+    return rv;
+}
+
+/* Validates an EC public key as described in Section 5.2.2 of
+ * X9.62. The ECDH primitive when used without the cofactor does
+ * not address small subgroup attacks, which may occur when the
+ * public key is not valid. These attacks can be prevented by
+ * validating the public key before using ECDH.
+ */
+SECStatus
+EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
+{
+    mp_int Px, Py;
+    ECGroup *group = NULL;
+    SECStatus rv = SECFailure;
+    mp_err err = MP_OKAY;
+    int len;
+
+    if (!ecParams || !publicValue) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    /* NOTE: We only support uncompressed points for now */
+    len = (ecParams->fieldID.size + 7) >> 3;
+    if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
+        return SECFailure;
+    } else if (publicValue->len != (2 * len + 1)) {
+        PORT_SetError(SEC_ERROR_BAD_KEY);
+        return SECFailure;
+    }
+
+    MP_DIGITS(&Px) = 0;
+    MP_DIGITS(&Py) = 0;
+    CHECK_MPI_OK( mp_init(&Px, kmflag) );
+    CHECK_MPI_OK( mp_init(&Py, kmflag) );
+
+    /* Initialize Px and Py */
+    CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
+    CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
+
+    /* construct from named params */
+    group = ECGroup_fromName(ecParams->name, kmflag);
+    if (group == NULL) {
+        /*
+         * ECGroup_fromName fails if ecParams->name is not a valid
+         * ECCurveName value, or if we run out of memory, or perhaps
+         * for other reasons.  Unfortunately if ecParams->name is a
+         * valid ECCurveName value, we don't know what the right error
+         * code should be because ECGroup_fromName doesn't return an
+         * error code to the caller.  Set err to MP_UNDEF because
+         * that's what ECGroup_fromName uses internally.
+         */
+        if ((ecParams->name <= ECCurve_noName) ||
+            (ecParams->name >= ECCurve_pastLastCurve)) {
+            err = MP_BADARG;
+        } else {
+            err = MP_UNDEF;
+        }
+        goto cleanup;
+    }
+
+    /* validate public point */
+    if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
+        if (err == MP_NO) {
+            PORT_SetError(SEC_ERROR_BAD_KEY);
+            rv = SECFailure;
+            err = MP_OKAY;  /* don't change the error code */
+        }
+        goto cleanup;
+    }
+
+    rv = SECSuccess;
+
+cleanup:
+    ECGroup_free(group);
+    mp_clear(&Px);
+    mp_clear(&Py);
+    if (err) {
+        MP_TO_SEC_ERROR(err);
+        rv = SECFailure;
+    }
+    return rv;
+}
+
+/*
+** Performs an ECDH key derivation by computing the scalar point
+** multiplication of privateValue and publicValue (with or without the
+** cofactor) and returns the x-coordinate of the resulting elliptic
+** curve point in derived secret.  If successful, derivedSecret->data
+** is set to the address of the newly allocated buffer containing the
+** derived secret, and derivedSecret->len is the size of the secret
+** produced. It is the caller's responsibility to free the allocated
+** buffer containing the derived secret.
+*/
+SECStatus
+ECDH_Derive(SECItem  *publicValue,
+            ECParams *ecParams,
+            SECItem  *privateValue,
+            PRBool    withCofactor,
+            SECItem  *derivedSecret,
+            int kmflag)
+{
+    SECStatus rv = SECFailure;
+    unsigned int len = 0;
+    SECItem pointQ = {siBuffer, NULL, 0};
+    mp_int k; /* to hold the private value */
+    mp_int cofactor;
+    mp_err err = MP_OKAY;
+#if EC_DEBUG
+    int i;
+#endif
+
+    if (!publicValue || !ecParams || !privateValue ||
+        !derivedSecret) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    memset(derivedSecret, 0, sizeof *derivedSecret);
+    len = (ecParams->fieldID.size + 7) >> 3;
+    pointQ.len = 2*len + 1;
+    if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
+
+    MP_DIGITS(&k) = 0;
+    CHECK_MPI_OK( mp_init(&k, kmflag) );
+    CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
+                                          (mp_size) privateValue->len) );
+
+    if (withCofactor && (ecParams->cofactor != 1)) {
+            /* multiply k with the cofactor */
+            MP_DIGITS(&cofactor) = 0;
+            CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
+            mp_set(&cofactor, ecParams->cofactor);
+            CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
+    }
+
+    /* Multiply our private key and peer's public point */
+    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
+        ec_point_at_infinity(&pointQ))
+        goto cleanup;
+
+    /* Allocate memory for the derived secret and copy
+     * the x co-ordinate of pointQ into it.
+     */
+    SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
+    memcpy(derivedSecret->data, pointQ.data + 1, len);
+
+    rv = SECSuccess;
+
+#if EC_DEBUG
+    printf("derived_secret:\n");
+    for (i = 0; i < derivedSecret->len; i++)
+        printf("%02x:", derivedSecret->data[i]);
+    printf("\n");
+#endif
+
+cleanup:
+    mp_clear(&k);
+
+    if (pointQ.data) {
+        PORT_ZFree(pointQ.data, 2*len + 1);
+    }
+
+    return rv;
+}
+
+/* Computes the ECDSA signature (a concatenation of two values r and s)
+ * on the digest using the given key and the random value kb (used in
+ * computing s).
+ */
+SECStatus
+ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
+    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    mp_int x1;
+    mp_int d, k;     /* private key, random integer */
+    mp_int r, s;     /* tuple (r, s) is the signature */
+    mp_int n;
+    mp_err err = MP_OKAY;
+    ECParams *ecParams = NULL;
+    SECItem kGpoint = { siBuffer, NULL, 0};
+    int flen = 0;    /* length in bytes of the field size */
+    unsigned olen;   /* length in bytes of the base point order */
+
+#if EC_DEBUG
+    char mpstr[256];
+#endif
+
+    /* Initialize MPI integers. */
+    /* must happen before the first potential call to cleanup */
+    MP_DIGITS(&x1) = 0;
+    MP_DIGITS(&d) = 0;
+    MP_DIGITS(&k) = 0;
+    MP_DIGITS(&r) = 0;
+    MP_DIGITS(&s) = 0;
+    MP_DIGITS(&n) = 0;
+
+    /* Check args */
+    if (!key || !signature || !digest || !kb || (kblen < 0)) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        goto cleanup;
+    }
+
+    ecParams = &(key->ecParams);
+    flen = (ecParams->fieldID.size + 7) >> 3;
+    olen = ecParams->order.len;
+    if (signature->data == NULL) {
+        /* a call to get the signature length only */
+        goto finish;
+    }
+    if (signature->len < 2*olen) {
+        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+        rv = SECBufferTooSmall;
+        goto cleanup;
+    }
+
+
+    CHECK_MPI_OK( mp_init(&x1, kmflag) );
+    CHECK_MPI_OK( mp_init(&d, kmflag) );
+    CHECK_MPI_OK( mp_init(&k, kmflag) );
+    CHECK_MPI_OK( mp_init(&r, kmflag) );
+    CHECK_MPI_OK( mp_init(&s, kmflag) );
+    CHECK_MPI_OK( mp_init(&n, kmflag) );
+
+    SECITEM_TO_MPINT( ecParams->order, &n );
+    SECITEM_TO_MPINT( key->privateValue, &d );
+    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
+    /* Make sure k is in the interval [1, n-1] */
+    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
+#if EC_DEBUG
+        printf("k is outside [1, n-1]\n");
+        mp_tohex(&k, mpstr);
+        printf("k : %s \n", mpstr);
+        mp_tohex(&n, mpstr);
+        printf("n : %s \n", mpstr);
+#endif
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        goto cleanup;
+    }
+
+    /*
+    ** ANSI X9.62, Section 5.3.2, Step 2
+    **
+    ** Compute kG
+    */
+    kGpoint.len = 2*flen + 1;
+    kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
+    if ((kGpoint.data == NULL) ||
+        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
+            != SECSuccess))
+        goto cleanup;
+
+    /*
+    ** ANSI X9.62, Section 5.3.3, Step 1
+    **
+    ** Extract the x co-ordinate of kG into x1
+    */
+    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
+                                          (mp_size) flen) );
+
+    /*
+    ** ANSI X9.62, Section 5.3.3, Step 2
+    **
+    ** r = x1 mod n  NOTE: n is the order of the curve
+    */
+    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
+
+    /*
+    ** ANSI X9.62, Section 5.3.3, Step 3
+    **
+    ** verify r != 0
+    */
+    if (mp_cmp_z(&r) == 0) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        goto cleanup;
+    }
+
+    /*
+    ** ANSI X9.62, Section 5.3.3, Step 4
+    **
+    ** s = (k**-1 * (HASH(M) + d*r)) mod n
+    */
+    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
+
+    /* In the definition of EC signing, digests are truncated
+     * to the length of n in bits.
+     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
+    if (digest->len*8 > ecParams->fieldID.size) {
+        mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
+    }
+
+#if EC_DEBUG
+    mp_todecimal(&n, mpstr);
+    printf("n : %s (dec)\n", mpstr);
+    mp_todecimal(&d, mpstr);
+    printf("d : %s (dec)\n", mpstr);
+    mp_tohex(&x1, mpstr);
+    printf("x1: %s\n", mpstr);
+    mp_todecimal(&s, mpstr);
+    printf("digest: %s (decimal)\n", mpstr);
+    mp_todecimal(&r, mpstr);
+    printf("r : %s (dec)\n", mpstr);
+    mp_tohex(&r, mpstr);
+    printf("r : %s\n", mpstr);
+#endif
+
+    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
+    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
+    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
+    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
+
+#if EC_DEBUG
+    mp_todecimal(&s, mpstr);
+    printf("s : %s (dec)\n", mpstr);
+    mp_tohex(&s, mpstr);
+    printf("s : %s\n", mpstr);
+#endif
+
+    /*
+    ** ANSI X9.62, Section 5.3.3, Step 5
+    **
+    ** verify s != 0
+    */
+    if (mp_cmp_z(&s) == 0) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        goto cleanup;
+    }
+
+   /*
+    **
+    ** Signature is tuple (r, s)
+    */
+    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
+    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
+finish:
+    signature->len = 2*olen;
+
+    rv = SECSuccess;
+    err = MP_OKAY;
+cleanup:
+    mp_clear(&x1);
+    mp_clear(&d);
+    mp_clear(&k);
+    mp_clear(&r);
+    mp_clear(&s);
+    mp_clear(&n);
+
+    if (kGpoint.data) {
+        PORT_ZFree(kGpoint.data, 2*flen + 1);
+    }
+
+    if (err) {
+        MP_TO_SEC_ERROR(err);
+        rv = SECFailure;
+    }
+
+#if EC_DEBUG
+    printf("ECDSA signing with seed %s\n",
+        (rv == SECSuccess) ? "succeeded" : "failed");
+#endif
+
+   return rv;
+}
+
+/*
+** Computes the ECDSA signature on the digest using the given key
+** and a random seed.
+*/
+SECStatus
+ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
+    const unsigned char* random, int randomLen, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    int len;
+    unsigned char *kBytes= NULL;
+
+    if (!key) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    /* Generate random value k */
+    len = key->ecParams.order.len;
+    kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
+        random, randomLen, kmflag);
+    if (kBytes == NULL) goto cleanup;
+
+    /* Generate ECDSA signature with the specified k value */
+    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
+
+cleanup:
+    if (kBytes) {
+        PORT_ZFree(kBytes, len * 2);
+    }
+
+#if EC_DEBUG
+    printf("ECDSA signing %s\n",
+        (rv == SECSuccess) ? "succeeded" : "failed");
+#endif
+
+    return rv;
+}
+
+/*
+** Checks the signature on the given digest using the key provided.
+*/
+SECStatus
+ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
+                 const SECItem *digest, int kmflag)
+{
+    SECStatus rv = SECFailure;
+    mp_int r_, s_;           /* tuple (r', s') is received signature) */
+    mp_int c, u1, u2, v;     /* intermediate values used in verification */
+    mp_int x1;
+    mp_int n;
+    mp_err err = MP_OKAY;
+    ECParams *ecParams = NULL;
+    SECItem pointC = { siBuffer, NULL, 0 };
+    int slen;       /* length in bytes of a half signature (r or s) */
+    int flen;       /* length in bytes of the field size */
+    unsigned olen;  /* length in bytes of the base point order */
+
+#if EC_DEBUG
+    char mpstr[256];
+    printf("ECDSA verification called\n");
+#endif
+
+    /* Initialize MPI integers. */