changeset 2901:61f1bbd49a5e

Merge
author lana
date Thu, 16 Sep 2010 11:19:43 -0700
parents 21562f873588 441e86ab3233
children b53f226b1d91
files src/solaris/classes/sun/net/spi/SdpProvider.java src/solaris/native/sun/net/spi/SdpProvider.c test/tools/launcher/VerifyExceptions.java
diffstat 124 files changed, 8495 insertions(+), 4063 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/Makefile	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/com/Makefile	Thu Sep 16 11:19:43 2010 -0700
@@ -31,7 +31,7 @@
 PRODUCT = com
 include $(BUILDDIR)/common/Defs.gmk
 
-SUBDIRS = sun
+SUBDIRS = sun oracle
 include $(BUILDDIR)/common/Subdirs.gmk
 
 all build clean clobber::
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/com/oracle/Makefile	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+PRODUCT = oracle
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = net
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+	$(SUBDIRS-loop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/com/oracle/net/Makefile	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../../..
+PRODUCT = oracle
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files to compile
+#
+AUTO_FILES_JAVA_DIRS = com/oracle/net
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
+
--- a/make/common/Release.gmk	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/common/Release.gmk	Thu Sep 16 11:19:43 2010 -0700
@@ -573,13 +573,13 @@
 	$(ECHO) "sun/jvmstat/" >> $@
 	$(ECHO) "sun/nio/cs/ext/" >> $@
 	$(ECHO) "sun/awt/HKSCS.class" >> $@
-	$(ECHO) "sun/awt/motif/X11GB2312$Decoder.class" >> $@
-	$(ECHO) "sun/awt/motif/X11GB2312$Encoder.class" >> $@
+	$(ECHO) "sun/awt/motif/X11GB2312\$$Decoder.class" >> $@
+	$(ECHO) "sun/awt/motif/X11GB2312\$$Encoder.class" >> $@
 	$(ECHO) "sun/awt/motif/X11GB2312.class" >> $@
-	$(ECHO) "sun/awt/motif/X11GBK$Encoder.class" >> $@
+	$(ECHO) "sun/awt/motif/X11GBK\$$Encoder.class" >> $@
 	$(ECHO) "sun/awt/motif/X11GBK.class" >> $@
-	$(ECHO) "sun/awt/motif/X11KSC5601$Decoder.class" >> $@
-	$(ECHO) "sun/awt/motif/X11KSC5601$Encoder.class" >> $@
+	$(ECHO) "sun/awt/motif/X11KSC5601\$$Decoder.class" >> $@
+	$(ECHO) "sun/awt/motif/X11KSC5601\$$Encoder.class" >> $@
 	$(ECHO) "sun/awt/motif/X11KSC5601.class" >> $@
 	$(ECHO) "sun/rmi/rmic/" >> $@
 	$(ECHO) "sun/tools/asm/" >> $@
--- a/make/docs/NON_CORE_PKGS.gmk	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/docs/NON_CORE_PKGS.gmk	Thu Sep 16 11:19:43 2010 -0700
@@ -91,6 +91,8 @@
 TRACING_PKGS     = com.sun.tracing         \
                    com.sun.tracing.dtrace
 
+ORACLENET_PKGS   = com.oracle.net
+
 # non-core packages in rt.jar
 NON_CORE_PKGS    = $(DOMAPI_PKGS) \
                    $(MGMT_PKGS) \
@@ -101,5 +103,6 @@
                    $(HTTPSERVER_PKGS) \
                    $(SMARTCARDIO_PKGS) \
                    $(TRACING_PKGS) \
-                   $(SCTPAPI_PKGS)
+                   $(SCTPAPI_PKGS) \
+                   $(ORACLENET_PKGS)
 
--- a/make/java/net/FILES_c.gmk	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/net/FILES_c.gmk	Thu Sep 16 11:19:43 2010 -0700
@@ -39,10 +39,6 @@
 	ResolverConfigurationImpl.c \
 	DefaultProxySelector.c
 
-ifeq ($(PLATFORM), solaris)
-    FILES_c += SdpProvider.c
-endif
-
 ifeq ($(PLATFORM), linux)
     FILES_c += linux_close.c
 endif
--- a/make/java/net/Makefile	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/net/Makefile	Thu Sep 16 11:19:43 2010 -0700
@@ -44,6 +44,8 @@
     endif
     FILES_c += NTLMAuthSequence.c
     FILES_c += NetworkInterface_winXP.c
+else
+    FILES_c += SdpSupport.c
 endif
 
 FILES_export = \
@@ -84,7 +86,8 @@
 #
 # Find platform specific native code
 #
-vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
+vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm \
+    $(PLATFORM_SRC)/native/sun/net/sdp $(PLATFORM_SRC)/native/sun/net/spi
 
 #
 # Include rules
--- a/make/java/net/mapfile-vers	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/net/mapfile-vers	Thu Sep 16 11:19:43 2010 -0700
@@ -88,9 +88,10 @@
 		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
 		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
 		Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0;
+		Java_sun_net_sdp_SdpSupport_convert0;
+		Java_sun_net_sdp_SdpSupport_create0;
 		Java_sun_net_spi_DefaultProxySelector_init;
 		Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
-		Java_sun_net_spi_SdpProvider_convert;
 		NET_AllocSockaddr;
 		NET_SockaddrToInetAddress;
                 NET_SockaddrEqualsInetAddress;
--- a/make/java/nio/FILES_java.gmk	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/nio/FILES_java.gmk	Thu Sep 16 11:19:43 2010 -0700
@@ -83,6 +83,7 @@
 	java/nio/file/ClosedFileSystemException.java \
 	java/nio/file/ClosedWatchServiceException.java \
 	java/nio/file/CopyOption.java \
+	java/nio/file/DirectoryIteratorException.java \
 	java/nio/file/DirectoryNotEmptyException.java \
 	java/nio/file/DirectoryStream.java \
 	java/nio/file/FileAlreadyExistsException.java \
@@ -199,6 +200,7 @@
 	sun/nio/ch/PipeImpl.java \
 	sun/nio/ch/PollArrayWrapper.java \
 	sun/nio/ch/Reflect.java \
+	sun/nio/ch/Secrets.java \
 	sun/nio/ch/SelectionKeyImpl.java \
 	sun/nio/ch/SelectorImpl.java \
 	sun/nio/ch/SelectorProviderImpl.java \
--- a/make/java/nio/mapfile-linux	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/nio/mapfile-linux	Thu Sep 16 11:19:43 2010 -0700
@@ -89,7 +89,7 @@
                 Java_sun_nio_ch_IOUtil_drain;
                 Java_sun_nio_ch_IOUtil_fdVal;
                 Java_sun_nio_ch_IOUtil_initIDs;
-                Java_sun_nio_ch_IOUtil_initPipe;
+                Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
 		Java_sun_nio_ch_NativeThread_current;
--- a/make/java/nio/mapfile-solaris	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/java/nio/mapfile-solaris	Thu Sep 16 11:19:43 2010 -0700
@@ -76,7 +76,7 @@
                 Java_sun_nio_ch_IOUtil_drain;
                 Java_sun_nio_ch_IOUtil_fdVal;
                 Java_sun_nio_ch_IOUtil_initIDs;
-                Java_sun_nio_ch_IOUtil_initPipe;
+                Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
 		Java_sun_nio_ch_NativeThread_current;
--- a/make/sun/net/FILES_java.gmk	Thu Sep 16 11:17:32 2010 -0700
+++ b/make/sun/net/FILES_java.gmk	Thu Sep 16 11:19:43 2010 -0700
@@ -53,6 +53,7 @@
 	sun/net/ftp/FtpProtocolException.java \
 	sun/net/ftp/impl/FtpClient.java \
 	sun/net/ftp/impl/DefaultFtpClientProvider.java \
+	sun/net/sdp/SdpSupport.java \
 	sun/net/spi/DefaultProxySelector.java \
 	sun/net/spi/nameservice/NameServiceDescriptor.java \
 	sun/net/spi/nameservice/NameService.java \
@@ -136,8 +137,6 @@
 
 ifeq ($(PLATFORM), windows)
     FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java 
+else
+    FILES_java += sun/net/sdp/SdpProvider.java
 endif
-
-ifeq ($(PLATFORM), solaris)
-    FILES_java += sun/net/spi/SdpProvider.java
-endif
--- a/src/share/bin/java.c	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/bin/java.c	Thu Sep 16 11:19:43 2010 -0700
@@ -712,19 +712,19 @@
     struct stat statbuf;
 
     /* return if jre/lib/rt.jar exists */
-    sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
+    JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator);
     if (stat(pathname, &statbuf) == 0) {
         return;
     }
 
     /* return if jre/classes exists */
-    sprintf(pathname, "%s%sclasses", jrepath, separator);
+    JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator);
     if (stat(pathname, &statbuf) == 0) {
         return;
     }
 
     /* modularized jre */
-    sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
+    JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator);
     s = (char *) JLI_WildcardExpandClasspath(pathname);
     def = JLI_MemAlloc(sizeof(format)
                        - 2 /* strlen("%s") */
@@ -1624,11 +1624,8 @@
     if (JLI_IsTraceLauncher()) {
         start = CounterGet();
     }
-
-    JLI_StrCpy(jvmCfgName, jrepath);
-    JLI_StrCat(jvmCfgName, FILESEP "lib" FILESEP);
-    JLI_StrCat(jvmCfgName, arch);
-    JLI_StrCat(jvmCfgName, FILESEP "jvm.cfg");
+    JLI_Snprintf(jvmCfgName, sizeof(jvmCfgName), "%s%slib%s%s%sjvm.cfg",
+        jrepath, FILESEP, FILESEP, arch, FILESEP);
 
     jvmCfg = fopen(jvmCfgName, "r");
     if (jvmCfg == NULL) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/oracle/net/Sdp.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.net;
+
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.SocketImpl;
+import java.net.SocketImplFactory;
+import java.net.SocketException;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.net.sdp.SdpSupport;
+
+/**
+ * This class consists exclusively of static methods that Sockets or Channels to
+ * sockets that support the InfiniBand Sockets Direct Protocol (SDP).
+ */
+
+public final class Sdp {
+    private Sdp() { }
+
+    /**
+     * The package-privage ServerSocket(SocketImpl) constructor
+     */
+    private static final Constructor<ServerSocket> serverSocketCtor;
+    static {
+        try {
+            serverSocketCtor = (Constructor<ServerSocket>)
+                ServerSocket.class.getDeclaredConstructor(SocketImpl.class);
+            setAccessible(serverSocketCtor);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * The package-private SdpSocketImpl() constructor
+     */
+    private static final Constructor<SocketImpl> socketImplCtor;
+    static {
+        try {
+            Class<?> cl = Class.forName("java.net.SdpSocketImpl", true, null);
+            socketImplCtor = (Constructor<SocketImpl>)cl.getDeclaredConstructor();
+            setAccessible(socketImplCtor);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError(e);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static void setAccessible(final AccessibleObject o) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                o.setAccessible(true);
+                return null;
+            }
+        });
+    }
+
+    /**
+     * SDP enabled Socket.
+     */
+    private static class SdpSocket extends Socket {
+        SdpSocket(SocketImpl impl) throws SocketException {
+            super(impl);
+        }
+    }
+
+    /**
+     * Creates a SDP enabled SocketImpl
+     */
+    private static SocketImpl createSocketImpl() {
+        try {
+            return socketImplCtor.newInstance();
+        } catch (InstantiationException x) {
+            throw new AssertionError(x);
+        } catch (IllegalAccessException x) {
+            throw new AssertionError(x);
+        } catch (InvocationTargetException x) {
+            throw new AssertionError(x);
+        }
+    }
+
+    /**
+     * Creates an unconnected and unbound SDP socket. The {@code Socket} is
+     * associated with a {@link java.net.SocketImpl} of the system-default type.
+     *
+     * @return  a new Socket
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static Socket openSocket() throws IOException {
+        SocketImpl impl = createSocketImpl();
+        return new SdpSocket(impl);
+    }
+
+    /**
+     * Creates an unbound SDP server socket. The {@code ServerSocket} is
+     * associated with a {@link java.net.SocketImpl} of the system-default type.
+     *
+     * @return  a new ServerSocket
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static ServerSocket openServerSocket() throws IOException {
+        // create ServerSocket via package-private constructor
+        SocketImpl impl = createSocketImpl();
+        try {
+            return serverSocketCtor.newInstance(impl);
+        } catch (IllegalAccessException x) {
+            throw new AssertionError(x);
+        } catch (InstantiationException x) {
+            throw new AssertionError(x);
+        } catch (InvocationTargetException x) {
+            Throwable cause = x.getCause();
+            if (cause instanceof IOException)
+                throw (IOException)cause;
+            if (cause instanceof RuntimeException)
+                throw (RuntimeException)cause;
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * Opens a socket channel to a SDP socket.
+     *
+     * <p> The channel will be associated with the system-wide default
+     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
+     *
+     * @return  a new SocketChannel
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported or not supported by the default selector
+     *          provider
+     * @throws  IOException
+     *          If an I/O error occurs.
+     */
+    public static SocketChannel openSocketChannel() throws IOException {
+        FileDescriptor fd = SdpSupport.createSocket();
+        return sun.nio.ch.Secrets.newSocketChannel(fd);
+    }
+
+    /**
+     * Opens a socket channel to a SDP socket.
+     *
+     * <p> The channel will be associated with the system-wide default
+     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
+     *
+     * @return  a new ServerSocketChannel
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported or not supported by the default selector
+     *          provider
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static ServerSocketChannel openServerSocketChannel()
+        throws IOException
+    {
+        FileDescriptor fd = SdpSupport.createSocket();
+        return sun.nio.ch.Secrets.newServerSocketChannel(fd);
+    }
+}
--- a/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -518,7 +518,7 @@
             setReadOnly(true);
         setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
         setEscapeProcessing(true);
-        setTypeMap(null);
+        //setTypeMap(null);
         checkTransactionalWriter();
 
         //Instantiating the vector for MatchColumns
@@ -679,7 +679,10 @@
                 } else if (obj instanceof Clob) {
                     obj = new SerialClob((Clob)obj);
                 } else if (obj instanceof java.sql.Array) {
-                    obj = new SerialArray((java.sql.Array)obj, map);
+                    if(map != null)
+                        obj = new SerialArray((java.sql.Array)obj, map);
+                    else
+                        obj = new SerialArray((java.sql.Array)obj);
                 }
 
                 ((Row)currentRow).initColumnObject(i, obj);
@@ -762,7 +765,7 @@
         if( conn != null){
            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
            // must be implemented, therefore, the previous fix for 5055528 is being backed out
-           dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
+            dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
         }
     }
 
@@ -6322,6 +6325,7 @@
         crs.RowSetMD = RowSetMD;
         crs.numRows = 1;
         crs.cursorPos = 0;
+        crs.setTypeMap(this.getTypeMap());
 
         // make sure we don't get someone playing with these
         // %%% is this now necessary ???
@@ -10114,7 +10118,7 @@
      * during the deserialization process
      *
      */
-    protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
         // Default state initialization happens here
         ois.defaultReadObject();
         // Initialization of transient Res Bundle happens here .
@@ -10125,5 +10129,15 @@
         }
 
     }
-        static final long serialVersionUID =1884577171200622428L;
+
+    //------------------------- JDBC 4.1 -----------------------------------
+    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Not supported yet.");
+    }
+
+    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Not supported yet.");
+    }
+
+    static final long serialVersionUID =1884577171200622428L;
 }
--- a/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1746,5 +1746,23 @@
       onInsertRow = false;
       super.insertRow();
    }
-  static final long serialVersionUID = 6178454588413509360L;
+
+   /**
+    * This method re populates the resBundle
+    * during the deserialization process
+    *
+    */
+   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+       // Default state initialization happens here
+       ois.defaultReadObject();
+       // Initialization of transient Res Bundle happens here .
+       try {
+          resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+       } catch(IOException ioe) {
+           throw new RuntimeException(ioe);
+       }
+
+   }
+
+   static final long serialVersionUID = 6178454588413509360L;
 } // end FilteredRowSetImpl class
--- a/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,7 @@
     private Vector strMatchColumns;
 
 
-    protected transient JdbcRowSetResourceBundle jdbcResBundle;
+    protected transient JdbcRowSetResourceBundle resBundle;
 
     /**
      * Constructs a default <code>JdbcRowSet</code> object.
@@ -140,7 +140,7 @@
         rs   = null;
 
         try {
-           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
         } catch(IOException ioe) {
             throw new RuntimeException(ioe);
         }
@@ -154,42 +154,42 @@
         try {
             setShowDeleted(false);
         } catch(SQLException sqle) {
-             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setshowdeleted").toString() +
+             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setshowdeleted").toString() +
                                 sqle.getLocalizedMessage());
         }
 
         try {
             setQueryTimeout(0);
         } catch(SQLException sqle) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
                                 sqle.getLocalizedMessage());
         }
 
         try {
             setMaxRows(0);
         } catch(SQLException sqle) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
                                 sqle.getLocalizedMessage());
         }
 
         try {
             setMaxFieldSize(0);
         } catch(SQLException sqle) {
-             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
+             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
                                 sqle.getLocalizedMessage());
         }
 
         try {
             setEscapeProcessing(true);
         } catch(SQLException sqle) {
-             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
+             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
                                 sqle.getLocalizedMessage());
         }
 
         try {
             setConcurrency(ResultSet.CONCUR_UPDATABLE);
         } catch (SQLException sqle) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setconcurrency").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setconcurrency").toString() +
                                 sqle.getLocalizedMessage());
         }
 
@@ -198,7 +198,7 @@
         try {
             setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
         } catch(SQLException sqle){
-          System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settype").toString() +
+          System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.settype").toString() +
                                 sqle.getLocalizedMessage());
         }
 
@@ -207,7 +207,7 @@
         try {
             setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
         } catch(SQLException sqle){
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settransactionisolation").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.settransactionisolation").toString() +
                                 sqle.getLocalizedMessage());
         }
 
@@ -263,7 +263,7 @@
         rs = null;
 
         try {
-           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
         } catch(IOException ioe) {
             throw new RuntimeException(ioe);
         }
@@ -338,7 +338,7 @@
         rs = null;
 
         try {
-           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
         } catch(IOException ioe) {
             throw new RuntimeException(ioe);
         }
@@ -430,7 +430,7 @@
         rs = res;
 
         try {
-           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
         } catch(IOException ioe) {
             throw new RuntimeException(ioe);
         }
@@ -517,7 +517,7 @@
         // to the db, implies undesirable state so throw exception
 
         if (conn == null && ps == null && rs == null ) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.invalstate").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.invalstate").toString());
         }
     }
 
@@ -593,28 +593,28 @@
         try {
             ps.setEscapeProcessing(getEscapeProcessing());
         } catch (SQLException ex) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
                                 ex.getLocalizedMessage());
         }
 
         try {
             ps.setMaxFieldSize(getMaxFieldSize());
         } catch (SQLException ex) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
                                 ex.getLocalizedMessage());
         }
 
         try {
             ps.setMaxRows(getMaxRows());
         } catch (SQLException ex) {
-           System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
+           System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
                                 ex.getLocalizedMessage());
         }
 
         try {
             ps.setQueryTimeout(getQueryTimeout());
         } catch (SQLException ex) {
-           System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
+           System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
                                 ex.getLocalizedMessage());
         }
 
@@ -651,7 +651,7 @@
                 }
             }
             catch (javax.naming.NamingException ex) {
-                throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
+                throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
             }
 
         } else if (getUrl() != null) {
@@ -681,7 +681,7 @@
             }
             ps = conn.prepareStatement(getCommand(),ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
         } catch (SQLException ex) {
-            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.prepare").toString() +
+            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.prepare").toString() +
                                 ex.getLocalizedMessage());
 
             if (ps != null)
@@ -721,15 +721,15 @@
                     if (param[0] instanceof java.sql.Date ||
                         param[0] instanceof java.sql.Time ||
                         param[0] instanceof java.sql.Timestamp) {
-                        System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detecteddate"));
+                        System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.detecteddate"));
                         if (param[1] instanceof java.util.Calendar) {
-                            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detectedcalendar"));
+                            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.detectedcalendar"));
                             ps.setDate(i + 1, (java.sql.Date)param[0],
                                        (java.util.Calendar)param[1]);
                             continue;
                         }
                         else {
-                            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
+                            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
                         }
                     }
 
@@ -770,7 +770,7 @@
                                               (java.io.InputStream)param[0],
                                               ((Integer)param[1]).intValue());
                         default:
-                            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
+                            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
                         }
                     }
 
@@ -784,7 +784,7 @@
                         continue;
                     }
 
-                    throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
+                    throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
 
                 } else {
                     // common case - this catches all SQL92 types
@@ -3749,7 +3749,7 @@
          for( int j= 0 ;j < columnIdxes.length; j++) {
             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
             if(columnIdxes[j] != i_val) {
-               throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
+               throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
             }
          }
 
@@ -3776,7 +3776,7 @@
 
         for(int j = 0 ;j < columnIdxes.length; j++) {
            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
-              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
+              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
            }
         }
 
@@ -3800,7 +3800,7 @@
         String []str_temp = new String[strMatchColumns.size()];
 
         if( strMatchColumns.get(0) == null) {
-           throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
+           throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
         }
 
         strMatchColumns.copyInto(str_temp);
@@ -3825,7 +3825,7 @@
         i_val = ((Integer)iMatchColumns.get(0)).intValue();
 
         if( i_val == -1 ) {
-           throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
+           throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
         }
 
 
@@ -3859,7 +3859,7 @@
 
         for(int j = 0 ; j < columnIdxes.length; j++) {
            if( columnIdxes[j] < 0 ) {
-              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
+              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
            }
         }
         for(int i = 0 ;i < columnIdxes.length; i++) {
@@ -3886,7 +3886,7 @@
 
         for(int j = 0; j < columnNames.length; j++) {
            if( columnNames[j] == null || columnNames[j].equals("")) {
-              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
+              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
            }
         }
         for( int i = 0; i < columnNames.length; i++) {
@@ -3915,7 +3915,7 @@
     public void setMatchColumn(int columnIdx) throws SQLException {
         // validate, if col is ok to be set
         if(columnIdx < 0) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
         } else {
             // set iMatchColumn
             iMatchColumns.set(0, new Integer(columnIdx));
@@ -3941,7 +3941,7 @@
     public void setMatchColumn(String columnName) throws SQLException {
         // validate, if col is ok to be set
         if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
         } else {
             // set strMatchColumn
             strMatchColumns.set(0, columnName);
@@ -3966,9 +3966,9 @@
     public void unsetMatchColumn(int columnIdx) throws SQLException {
         // check if we are unsetting the SAME column
         if(! iMatchColumns.get(0).equals(new Integer(columnIdx) )  ) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
         } else if(strMatchColumns.get(0) != null) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.usecolname").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.usecolname").toString());
         } else {
                 // that is, we are unsetting it.
                iMatchColumns.set(0, new Integer(-1));
@@ -3995,9 +3995,9 @@
         columnName = columnName.trim();
 
         if(!((strMatchColumns.get(0)).equals(columnName))) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
         } else if( ((Integer)(iMatchColumns.get(0))).intValue() > 0) {
-            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.usecolid").toString());
+            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.usecolid").toString());
         } else {
             strMatchColumns.set(0, null);   // that is, we are unsetting it.
         }
@@ -4152,7 +4152,7 @@
     private void checkTypeConcurrency() throws SQLException {
         if(rs.getType() == TYPE_FORWARD_ONLY ||
            rs.getConcurrency() == CONCUR_READ_ONLY) {
-              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.resnotupd").toString());
+              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.resnotupd").toString());
          }
     }
 
@@ -4642,7 +4642,7 @@
      * @since 6.0
      */
     public SQLXML getSQLXML(int columnIndex) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4653,7 +4653,7 @@
      * @throws SQLException if a database access error occurs
      */
     public SQLXML getSQLXML(String colName) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4668,7 +4668,7 @@
      * @since 6.0
      */
     public RowId getRowId(int columnIndex) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4683,7 +4683,7 @@
      * @since 6.0
      */
     public RowId getRowId(String columnName) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4699,7 +4699,7 @@
      * @since 6.0
      */
     public void updateRowId(int columnIndex, RowId x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4715,7 +4715,7 @@
      * @since 6.0
      */
     public void updateRowId(String columnName, RowId x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4725,7 +4725,7 @@
      * @since 6.0
      */
     public int getHoldability() throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4736,7 +4736,7 @@
      * @since 6.0
      */
     public boolean isClosed() throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4748,7 +4748,7 @@
      * @since 6.0
      */
     public void updateNString(int columnIndex, String nString) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4760,7 +4760,7 @@
      * @since 6.0
      */
     public void updateNString(String columnName, String nString) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -4773,7 +4773,7 @@
      * @since 6.0
      */
     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4785,7 +4785,7 @@
      * @since 6.0
      */
     public void updateNClob(String columnName, NClob nClob) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -4800,7 +4800,7 @@
      * @since 6.0
      */
     public NClob getNClob(int i) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -4816,7 +4816,7 @@
      * @since 6.0
      */
     public NClob getNClob(String colName) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException{
@@ -4836,7 +4836,7 @@
       * @since 1.6
       */
      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
     /**
@@ -4848,7 +4848,7 @@
      * @since 1.6
      */
     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
     /**
@@ -4863,7 +4863,7 @@
      * @since 1.6
      */
     public void setRowId(int parameterIndex, RowId x) throws SQLException {
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
     /**
@@ -4877,7 +4877,7 @@
     * @since 1.6
     */
    public void setRowId(String parameterName, RowId x) throws SQLException {
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
 
@@ -4897,7 +4897,7 @@
      * @since 1.6
      */
      public void setNString(int parameterIndex, String value) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
 
@@ -4925,7 +4925,7 @@
     * @since 1.6
     */
     public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
   /**
@@ -4940,7 +4940,7 @@
     * @since 1.6
     */
     public void setNClob(String parameterName, NClob value) throws SQLException {
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
 
@@ -4960,7 +4960,7 @@
      * @since 1.6
      */
     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
-       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
 
@@ -4980,7 +4980,7 @@
      * @since 1.6
      */
     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
-       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
      }
 
     /**
@@ -4996,7 +4996,7 @@
      * @since 1.6
      */
     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5013,7 +5013,7 @@
      * @since 1.6
      */
     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
      /**
@@ -5031,7 +5031,7 @@
      * @since 1.6
      */
     public String getNString(int columnIndex) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5049,7 +5049,7 @@
      * @since 1.6
      */
     public String getNString(String columnName) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
      /**
@@ -5071,7 +5071,7 @@
                             java.io.Reader x,
                             long length)
                             throws SQLException {
-          throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
        }
 
      /**
@@ -5093,7 +5093,7 @@
                             java.io.Reader x,
                             long length)
                             throws SQLException {
-          throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
        }
 
     /**
@@ -5123,7 +5123,7 @@
      */
     public void updateNCharacterStream(int columnIndex,
                              java.io.Reader x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5155,7 +5155,7 @@
      */
     public void updateNCharacterStream(String columnLabel,
                              java.io.Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5188,7 +5188,7 @@
      * @since 1.6
      */
     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5221,7 +5221,7 @@
      * @since 1.6
      */
     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5256,7 +5256,7 @@
      * @since 1.6
      */
     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5291,7 +5291,7 @@
      * @since 1.6
      */
     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5323,7 +5323,7 @@
      * @since 1.6
      */
     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5355,7 +5355,7 @@
      * @since 1.6
      */
     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5389,7 +5389,7 @@
      * @since 1.6
      */
     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5424,7 +5424,7 @@
      * @since 1.6
      */
     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
    /**
@@ -5458,7 +5458,7 @@
      * @since 1.6
      */
     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5492,7 +5492,7 @@
      * @since 1.6
      */
     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5528,7 +5528,7 @@
      * @since 1.6
      */
     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5565,7 +5565,7 @@
      * @since 1.6
      */
     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -5590,7 +5590,7 @@
     public void updateAsciiStream(int columnIndex,
                            java.io.InputStream x,
                            long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5614,7 +5614,7 @@
     public void updateBinaryStream(int columnIndex,
                             java.io.InputStream x,
                             long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5638,7 +5638,7 @@
     public void updateCharacterStream(int columnIndex,
                              java.io.Reader x,
                              long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
      /**
@@ -5662,7 +5662,7 @@
     public void updateAsciiStream(String columnLabel,
                            java.io.InputStream x,
                            long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5687,7 +5687,7 @@
      */
     public void updateAsciiStream(int columnIndex,
                            java.io.InputStream x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5713,7 +5713,7 @@
      */
     public void updateAsciiStream(String columnLabel,
                            java.io.InputStream x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -5738,7 +5738,7 @@
     public void updateBinaryStream(String columnLabel,
                             java.io.InputStream x,
                             long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5763,7 +5763,7 @@
      */
     public void updateBinaryStream(int columnIndex,
                             java.io.InputStream x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -5790,7 +5790,7 @@
      */
     public void updateBinaryStream(String columnLabel,
                             java.io.InputStream x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -5816,7 +5816,7 @@
     public void updateCharacterStream(String columnLabel,
                              java.io.Reader reader,
                              long length) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5841,7 +5841,7 @@
      */
     public void updateCharacterStream(int columnIndex,
                              java.io.Reader x) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
     /**
@@ -5868,7 +5868,7 @@
      */
     public void updateCharacterStream(String columnLabel,
                              java.io.Reader reader) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -5885,7 +5885,7 @@
   * @since 1.4
   */
   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -5914,7 +5914,7 @@
   */
   public void setNClob(int parameterIndex, Reader reader)
     throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
    /**
@@ -5942,7 +5942,7 @@
             */
             public void setNClob(String parameterName, Reader reader, long length)
     throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -5969,7 +5969,7 @@
   */
   public void setNClob(String parameterName, Reader reader)
     throws SQLException{
-             throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+             throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -5996,7 +5996,7 @@
      */
      public void setNClob(int parameterIndex, Reader reader, long length)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6012,7 +6012,7 @@
      * @since 1.6
      */
      public void setNClob(int parameterIndex, NClob value) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6029,7 +6029,7 @@
   */
  public void setNString(String parameterName, String value)
          throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6046,7 +6046,7 @@
   * @since 1.6
   */
   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6066,7 +6066,7 @@
   */
  public void setNCharacterStream(String parameterName, Reader value, long length)
          throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
   /**
@@ -6092,7 +6092,7 @@
   * @since 1.6
   */
   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
   /**
@@ -6118,7 +6118,7 @@
     */
     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
     /**
@@ -6144,7 +6144,7 @@
               */
       public  void setClob(String parameterName, Reader reader, long length)
       throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6163,7 +6163,7 @@
     * @since 1.6
     */
     public void setClob (String parameterName, Clob x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6188,7 +6188,7 @@
     */
     public void setClob(String parameterName, Reader reader)
       throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6210,7 +6210,7 @@
     */
     public void setDate(String parameterName, java.sql.Date x)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
    /**
@@ -6236,7 +6236,7 @@
     */
    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6256,7 +6256,7 @@
     */
    public void setTime(String parameterName, java.sql.Time x)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6282,7 +6282,7 @@
     */
    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
    /**
@@ -6308,7 +6308,7 @@
    */
    public void setClob(int parameterIndex, Reader reader)
      throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6333,7 +6333,7 @@
    */
    public void setClob(int parameterIndex, Reader reader, long length)
      throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6363,7 +6363,7 @@
     */
     public void setBlob(int parameterIndex, InputStream inputStream, long length)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6395,7 +6395,7 @@
     */
     public void setBlob(int parameterIndex, InputStream inputStream)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6426,7 +6426,7 @@
       */
       public void setBlob(String parameterName, InputStream inputStream, long length)
          throws SQLException{
-         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
     }
 
 
@@ -6444,7 +6444,7 @@
     * @since 1.6
     */
    public void setBlob (String parameterName, Blob x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6470,7 +6470,7 @@
     */
     public void setBlob(String parameterName, InputStream inputStream)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
   /**
@@ -6516,7 +6516,7 @@
   */
   public void setObject(String parameterName, Object x, int targetSqlType, int scale)
      throws SQLException{
-      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  }
 
   /**
@@ -6542,7 +6542,7 @@
     */
     public void setObject(String parameterName, Object x, int targetSqlType)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6582,7 +6582,7 @@
    * @since 1.4
    */
    public void setObject(String parameterName, Object x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
   /**
@@ -6609,7 +6609,7 @@
   */
  public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
      throws SQLException{
-      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  }
 
 
@@ -6636,7 +6636,7 @@
   */
  public void setBinaryStream(String parameterName, java.io.InputStream x,
                       int length) throws SQLException{
-      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  }
 
  /**
@@ -6665,7 +6665,7 @@
   public void setCharacterStream(String parameterName,
                           java.io.Reader reader,
                           int length) throws SQLException{
-       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
   }
 
   /**
@@ -6692,7 +6692,7 @@
   */
   public void setAsciiStream(String parameterName, java.io.InputStream x)
           throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6719,7 +6719,7 @@
     */
    public void setBinaryStream(String parameterName, java.io.InputStream x)
    throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6748,7 +6748,7 @@
     */
    public void setCharacterStream(String parameterName,
                          java.io.Reader reader) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
    /**
@@ -6767,7 +6767,7 @@
     * @since 1.4
     */
    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6788,7 +6788,7 @@
     * @since 1.4
     */
    public void setString(String parameterName, String x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6810,7 +6810,7 @@
     * @since 1.4
     */
    public void setBytes(String parameterName, byte x[]) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6830,7 +6830,7 @@
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
     /**
@@ -6847,7 +6847,7 @@
     * @since 1.4
     */
    public void setNull(String parameterName, int sqlType) throws SQLException {
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6884,7 +6884,7 @@
     */
    public void setNull (String parameterName, int sqlType, String typeName)
        throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6902,7 +6902,7 @@
     * @since 1.4
     */
    public void setBoolean(String parameterName, boolean x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6922,7 +6922,7 @@
     * @since 1.4
     */
    public void setByte(String parameterName, byte x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6941,7 +6941,7 @@
     * @since 1.4
     */
    public void setShort(String parameterName, short x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6960,7 +6960,7 @@
     * @since 1.4
     */
    public void setInt(String parameterName, int x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -6978,7 +6978,7 @@
     * @since 1.4
     */
    public void setLong(String parameterName, long x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
 
@@ -6997,7 +6997,7 @@
     * @since 1.4
     */
    public void setFloat(String parameterName, float x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
  /**
@@ -7015,7 +7015,7 @@
     * @since 1.4
     */
    public void setDouble(String parameterName, double x) throws SQLException{
-        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
+        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
    }
 
     /**
@@ -7023,15 +7023,25 @@
      * during the deserialization process
      *
      */
-    protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
         // Default state initialization happens here
         ois.defaultReadObject();
         // Initialization of transient Res Bundle happens here .
         try {
-           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
         } catch(IOException ioe) {}
 
     }
 
    static final long serialVersionUID = -3591946023893483003L;
+
+ //------------------------- JDBC 4.1 -----------------------------------
+
+    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Not supported yet.");
+    }
+
+    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Not supported yet.");
+    }
 }
--- a/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,4 +153,5 @@
        return propResBundle.handleGetObject(key);
     }
 
+    static final long serialVersionUID = 436199386225359954L;
 }
--- a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -127,6 +127,11 @@
         strMatchKey = null;
         supportedJOINs =
               new boolean[] {false, true, false, false, false};
+       try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
 
     }
 
@@ -4306,5 +4311,22 @@
          return crsInternal.createCopySchema();
      }
 
-        static final long serialVersionUID = -5590501621560008453L;
+    /**
+     * This method re populates the resBundle
+     * during the deserialization process
+     *
+     */
+     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+     }
+
+     static final long serialVersionUID = -5590501621560008453L;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/rowset/RowSetFactoryImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.rowset;
+
+import java.sql.SQLException;
+import javax.sql.rowset.CachedRowSet;
+import javax.sql.rowset.FilteredRowSet;
+import javax.sql.rowset.JdbcRowSet;
+import javax.sql.rowset.JoinRowSet;
+import javax.sql.rowset.WebRowSet;
+import javax.sql.rowset.RowSetFactory;
+
+/**
+ * This is the implementation specific class for the
+ * <code>javax.sql.rowset.spi.RowSetFactory</code>. This is the platform
+ * default implementation for the Java SE platform.
+ *
+ * @author Lance Andersen
+ *
+ *
+ * @version 1.7
+ */
+public  final class RowSetFactoryImpl implements RowSetFactory {
+
+    public CachedRowSet createCachedRowSet() throws SQLException {
+        return new com.sun.rowset.CachedRowSetImpl();
+    }
+
+    public FilteredRowSet createFilteredRowSet() throws SQLException {
+        return new com.sun.rowset.FilteredRowSetImpl();
+    }
+
+
+    public JdbcRowSet createJdbcRowSet() throws SQLException {
+        return new com.sun.rowset.JdbcRowSetImpl();
+    }
+
+    public JoinRowSet createJoinRowSet() throws SQLException {
+        return new com.sun.rowset.JoinRowSetImpl();
+    }
+
+    public WebRowSet createWebRowSet() throws SQLException {
+        return new com.sun.rowset.WebRowSetImpl();
+    }
+
+}
--- a/src/share/classes/com/sun/rowset/WebRowSetImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/WebRowSetImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,12 @@
      */
     public WebRowSetImpl(Hashtable env) throws SQLException {
 
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
         if ( env == null) {
             throw new SQLException(resBundle.handleGetObject("webrowsetimpl.nullhash").toString());
         }
@@ -263,5 +269,23 @@
 
             this.writeXml(oStream);
     }
-static final long serialVersionUID = -8771775154092422943L;
+
+    /**
+     * This method re populates the resBundle
+     * during the deserialization process
+     *
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID = -8771775154092422943L;
 }
--- a/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -490,4 +490,17 @@
         startPosition = pos;
     }
 
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of  Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID =5049738185801363801L;
 }
--- a/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,13 @@
 import java.io.*;
 
 import com.sun.rowset.*;
+import java.text.MessageFormat;
 import javax.sql.rowset.*;
+import javax.sql.rowset.serial.SQLInputImpl;
+import javax.sql.rowset.serial.SerialArray;
+import javax.sql.rowset.serial.SerialBlob;
+import javax.sql.rowset.serial.SerialClob;
+import javax.sql.rowset.serial.SerialStruct;
 import javax.sql.rowset.spi.*;
 
 
@@ -53,6 +59,7 @@
  * Standard JDBC RowSet implementations provide an object instance of this
  * writer by invoking the <code>SyncProvider.getRowSetWriter()</code> method.
  *
+ * @version 0.2
  * @author Jonathan Bruce
  * @see javax.sql.rowset.spi.SyncProvider
  * @see javax.sql.rowset.spi.SyncFactory
@@ -508,10 +515,11 @@
 
             ResultSet rs = null;
             rs = pstmt.executeQuery();
-            if (rs.next() == true) {
+            ResultSetMetaData rsmd = rs.getMetaData();
 
+            if (rs.next()) {
                 if (rs.next()) {
-                  /**  More than one row conflict.
+                   /** More than one row conflict.
                     *  If rs has only one row we are able to
                     *  uniquely identify the row where update
                     *  have to happen else if more than one
@@ -528,7 +536,7 @@
                 // we require the record in rs to be used.
                 // rs.close();
                 // pstmt.close();
-                        rs.first();
+                rs.first();
 
                 // how many fields need to be updated
                 int colsNotChanged = 0;
@@ -552,6 +560,49 @@
                 orig = origVals.getObject(i);
                 curr = crs.getObject(i);
                 rsval = rs.getObject(i);
+                /*
+                 * the following block creates equivalent objects
+                 * that would have been created if this rs is populated
+                 * into a CachedRowSet so that comparison of the column values
+                 * from the ResultSet and CachedRowSet are possible
+                 */
+                Map map = (crs.getTypeMap() == null)?con.getTypeMap():crs.getTypeMap();
+                if (rsval instanceof Struct) {
+
+                    Struct s = (Struct)rsval;
+
+                    // look up the class in the map
+                    Class c = null;
+                    c = (Class)map.get(s.getSQLTypeName());
+                    if (c != null) {
+                        // create new instance of the class
+                        SQLData obj = null;
+                        try {
+                            obj = (SQLData)c.newInstance();
+                        } catch (java.lang.InstantiationException ex) {
+                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
+                            ex.getMessage()));
+                        } catch (java.lang.IllegalAccessException ex) {
+                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
+                            ex.getMessage()));
+                        }
+                        // get the attributes from the struct
+                        Object attribs[] = s.getAttributes(map);
+                        // create the SQLInput "stream"
+                        SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
+                        // read the values...
+                        obj.readSQL(sqlInput, s.getSQLTypeName());
+                        rsval = obj;
+                    }
+                } else if (rsval instanceof SQLData) {
+                    rsval = new SerialStruct((SQLData)rsval, map);
+                } else if (rsval instanceof Blob) {
+                    rsval = new SerialBlob((Blob)rsval);
+                } else if (rsval instanceof Clob) {
+                    rsval = new SerialClob((Clob)rsval);
+                } else if (rsval instanceof java.sql.Array) {
+                    rsval = new SerialArray((java.sql.Array)rsval, map);
+                }
 
                 // reset boolNull if it had been set
                 boolNull = true;
@@ -669,6 +720,9 @@
                                  }
                 } //end for
 
+                rs.close();
+                pstmt.close();
+
                this.crsResolve.insertRow();
                    this.crsResolve.moveToCurrentRow();
 
@@ -1179,11 +1233,22 @@
     private void buildKeyDesc(CachedRowSet crs) throws SQLException {
 
         keyCols = crs.getKeyColumns();
+        ResultSetMetaData resultsetmd = crs.getMetaData();
         if (keyCols == null || keyCols.length == 0) {
-            keyCols = new int[callerColumnCount];
-            for (int i = 0; i < keyCols.length; ) {
-                keyCols[i] = ++i;
+            ArrayList<Integer> listKeys = new ArrayList<Integer>();
+
+            for (int i = 0; i < callerColumnCount; i++ ) {
+                if(resultsetmd.getColumnType(i+1) != java.sql.Types.CLOB &&
+                        resultsetmd.getColumnType(i+1) != java.sql.Types.STRUCT &&
+                        resultsetmd.getColumnType(i+1) != java.sql.Types.SQLXML &&
+                        resultsetmd.getColumnType(i+1) != java.sql.Types.BLOB &&
+                        resultsetmd.getColumnType(i+1) != java.sql.Types.ARRAY &&
+                        resultsetmd.getColumnType(i+1) != java.sql.Types.OTHER )
+                    listKeys.add(i+1);
             }
+            keyCols = new int[listKeys.size()];
+            for (int i = 0; i < listKeys.size(); i++ )
+                keyCols[i] = listKeys.get(i);
         }
         params = new Object[keyCols.length];
     }
@@ -1359,4 +1424,17 @@
         }
     }
 
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of  Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID =-8506030970299413976L;
 }
--- a/src/share/classes/com/sun/rowset/internal/InsertRow.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/InsertRow.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -157,4 +157,23 @@
         origVals[idx - 1] = val;
         markColInserted(idx - 1);
     }
+
+    /**
+     * This method re populates the resBundle
+     * during the deserialization process
+     *
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID = 1066099658102869344L;
 }
--- a/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 
 import com.sun.rowset.*;
 import java.io.IOException;
+import java.io.ObjectInputStream;
 
 /**
  * There will be two sets of data which will be maintained by the rowset at the
@@ -4837,4 +4838,23 @@
                             throws SQLException {
           throw new UnsupportedOperationException("Operation not yet supported");
        }
+
+      /**
+       * This method re populates the resBundle
+       * during the deserialization process
+       *
+       */
+       private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+         // Default state initialization happens here
+         ois.defaultReadObject();
+         // Initialization of transient Res Bundle happens here .
+         try {
+            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+         } catch(IOException ioe) {
+             throw new RuntimeException(ioe);
+         }
+
+       }
+
+       static final long serialVersionUID = -3345004441725080251L;
 } //end class
--- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -216,4 +216,22 @@
     public void readData(RowSetInternal caller) {
     }
 
+    /**
+     * This method re populates the resBundle
+     * during the deserialization process
+     *
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID = -9127058392819008014L;
 }
--- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -663,4 +663,23 @@
         return s;
     }
 
+
+    /**
+     * This method re populates the resBundle
+     * during the deserialization process
+     *
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+
+    static final long serialVersionUID = 7163134986189677641L;
 }
--- a/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -245,4 +245,18 @@
     public String getVendor() {
         return this.vendorName;
     }
+
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        // Default state initialization happens here
+        ois.defaultReadObject();
+        // Initialization of transient Res Bundle happens here .
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+
+    }
+    static final long serialVersionUID =-3143367176751761936L;
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/ntlm/Client.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.ntlm;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * The NTLM client. Not multi-thread enabled.<p>
+ * Example:
+ * <pre>
+ * Client client = new Client(null, "host", "dummy",
+ *       "REALM", "t0pSeCr3t".toCharArray());
+ * byte[] type1 = client.type1();
+ * // Send type1 to server and receive response as type2
+ * byte[] type3 = client.type3(type2, nonce);
+ * // Send type3 to server
+ * </pre>
+ */
+public final class Client extends NTLM {
+    final private String hostname;
+    final private String username;
+
+    private String domain;    // might be updated by Type 2 msg
+    private byte[] pw1, pw2;
+
+    /**
+     * Creates an NTLM Client instance.
+     * @param version the NTLM version to use, which can be:
+     * <ul>
+     * <li>LM/NTLM: Original NTLM v1
+     * <li>LM: Original NTLM v1, LM only
+     * <li>NTLM: Original NTLM v1, NTLM only
+     * <li>NTLM2: NTLM v1 with Client Challenge
+     * <li>LMv2/NTLMv2: NTLM v2
+     * <li>LMv2: NTLM v2, LM only
+     * <li>NTLMv2: NTLM v2, NTLM only
+     * </ul>
+     * If null, "LMv2/NTLMv2" will be used.
+     * @param hostname hostname of the client, can be null
+     * @param username username to be authenticated, must not be null
+     * @param domain domain of {@code username}, can be null
+     * @param password password for {@code username}, must not be not null.
+     * This method does not make any modification to this parameter, it neither
+     * needs to access the content of this parameter after this method call,
+     * so you are free to modify or nullify this parameter after this call.
+     * @throws NullPointerException if {@code username} or {@code password} is null.
+     * @throws NTLMException if {@code version} is illegal
+     */
+    public Client(String version, String hostname, String username,
+            String domain, char[] password) throws NTLMException {
+        super(version);
+        if ((username == null || password == null)) {
+            throw new NullPointerException("username/password cannot be null");
+        }
+        this.hostname = hostname;
+        this.username = username;
+        this.domain = domain;
+        this.pw1 = getP1(password);
+        this.pw2 = getP2(password);
+        debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n",
+                    hostname, username, domain, version, v.toString());
+    }
+
+    /**
+     * Generates the Type 1 message
+     * @return the message generated
+     */
+    public byte[] type1() {
+        Writer p = new Writer(1, 32);
+        int flags = 0x8203;
+        if (hostname != null) {
+            flags |= 0x2000;
+        }
+        if (domain != null) {
+            flags |= 0x1000;
+        }
+        if (v != Version.NTLM) {
+            flags |= 0x80000;
+        }
+        p.writeInt(12, flags);
+        p.writeSecurityBuffer(24, hostname, false);
+        p.writeSecurityBuffer(16, domain, false);
+        debug("NTLM Client: Type 1 created\n");
+        debug(p.getBytes());
+        return p.getBytes();
+    }
+
+    /**
+     * Generates the Type 3 message
+     * @param type2 the responding Type 2 message from server, must not be null
+     * @param nonce random 8-byte array to be used in message generation,
+     * must not be null except for original NTLM v1
+     * @return the message generated
+     * @throws NullPointerException if {@code type2} or {@code nonce} is null
+     * for NTLM v1.
+     * @throws NTLMException if the incoming message is invalid
+     */
+    public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
+        if (type2 == null || (v != Version.NTLM && nonce == null)) {
+            throw new NullPointerException("type2 and nonce cannot be null");
+        }
+        debug("NTLM Client: Type 2 received\n");
+        debug(type2);
+        Reader r = new Reader(type2);
+        byte[] challenge = r.readBytes(24, 8);
+        int inputFlags = r.readInt(20);
+        boolean unicode = (inputFlags & 1) == 1;
+        String domainFromServer = r.readSecurityBuffer(12, unicode);
+        if (domainFromServer != null) {
+            domain = domainFromServer;
+        }
+        if (domain == null) {
+            throw new NTLMException(NTLMException.NO_DOMAIN_INFO,
+                    "No domain info");
+        }
+
+        int flags = 0x88200 | (inputFlags & 3);
+        Writer p = new Writer(3, 64);
+        byte[] lm = null, ntlm = null;
+
+        p.writeSecurityBuffer(28, domain, unicode);
+        p.writeSecurityBuffer(36, username, unicode);
+        p.writeSecurityBuffer(44, hostname, unicode);
+
+        if (v == Version.NTLM) {
+            byte[] lmhash = calcLMHash(pw1);
+            byte[] nthash = calcNTHash(pw2);
+            if (writeLM) lm = calcResponse (lmhash, challenge);
+            if (writeNTLM) ntlm = calcResponse (nthash, challenge);
+        } else if (v == Version.NTLM2) {
+            byte[] nthash = calcNTHash(pw2);
+            lm = ntlm2LM(nonce);
+            ntlm = ntlm2NTLM(nthash, nonce, challenge);
+        } else {
+            byte[] nthash = calcNTHash(pw2);
+            if (writeLM) lm = calcV2(nthash,
+                    username.toUpperCase(Locale.US)+domain, nonce, challenge);
+            if (writeNTLM) {
+                byte[] alist = type2.length > 48 ?
+                    r.readSecurityBuffer(40) : new byte[0];
+                byte[] blob = new byte[32+alist.length];
+                System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8);
+                // TS
+                byte[] time = BigInteger.valueOf(new Date().getTime())
+                        .add(new BigInteger("11644473600000"))
+                        .multiply(BigInteger.valueOf(10000))
+                        .toByteArray();
+                for (int i=0; i<time.length; i++) {
+                    blob[8+time.length-i-1] = time[i];
+                }
+                System.arraycopy(nonce, 0, blob, 16, 8);
+                System.arraycopy(new byte[]{0,0,0,0}, 0, blob, 24, 4);
+                System.arraycopy(alist, 0, blob, 28, alist.length);
+                System.arraycopy(new byte[]{0,0,0,0}, 0,
+                        blob, 28+alist.length, 4);
+                ntlm = calcV2(nthash, username.toUpperCase(Locale.US)+domain,
+                        blob, challenge);
+            }
+        }
+        p.writeSecurityBuffer(12, lm);
+        p.writeSecurityBuffer(20, ntlm);
+        p.writeSecurityBuffer(52, new byte[0]);
+
+        p.writeInt(60, flags);
+        debug("NTLM Client: Type 3 created\n");
+        debug(p.getBytes());
+        return p.getBytes();
+    }
+
+    /**
+     * Returns the domain value provided by server after the authentication
+     * is complete, or the domain value provided by the client before it.
+     * @return the domain
+     */
+    public String getDomain() {
+        return domain;
+    }
+
+    /**
+     * Disposes any password-derived information.
+     */
+    public void dispose() {
+        Arrays.fill(pw1, (byte)0);
+        Arrays.fill(pw2, (byte)0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/ntlm/NTLM.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.ntlm;
+
+import static com.sun.security.ntlm.Version.*;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * NTLM authentication implemented according to MS-NLMP, version 12.1
+ * @since 1.7
+ */
+class NTLM {
+
+    private final SecretKeyFactory fac;
+    private final Cipher cipher;
+    private final MessageDigest md4;
+    private final Mac hmac;
+    private final MessageDigest md5;
+    private static final boolean DEBUG =
+            System.getProperty("ntlm.debug") != null;
+
+    final Version v;
+
+    final boolean writeLM;
+    final boolean writeNTLM;
+
+    protected NTLM(String version) throws NTLMException {
+        if (version == null) version = "LMv2/NTLMv2";
+        switch (version) {
+            case "LM": v = NTLM; writeLM = true; writeNTLM = false; break;
+            case "NTLM": v = NTLM; writeLM = false; writeNTLM = true; break;
+            case "LM/NTLM": v = NTLM; writeLM = writeNTLM = true; break;
+            case "NTLM2": v = NTLM2; writeLM = writeNTLM = true; break;
+            case "LMv2": v = NTLMv2; writeLM = true; writeNTLM = false; break;
+            case "NTLMv2": v = NTLMv2; writeLM = false; writeNTLM = true; break;
+            case "LMv2/NTLMv2": v = NTLMv2; writeLM = writeNTLM = true; break;
+            default: throw new NTLMException(NTLMException.BAD_VERSION,
+                    "Unknown version " + version);
+        }
+        try {
+            fac = SecretKeyFactory.getInstance ("DES");
+            cipher = Cipher.getInstance ("DES/ECB/NoPadding");
+            md4 = sun.security.provider.MD4.getInstance();
+            hmac = Mac.getInstance("HmacMD5");
+            md5 = MessageDigest.getInstance("MD5");
+        } catch (NoSuchPaddingException e) {
+            throw new AssertionError();
+        } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Prints out a formatted string, called in various places inside then NTLM
+     * implementation for debugging/logging purposes. When the system property
+     * "ntlm.debug" is set, <code>System.out.printf(format, args)</code> is
+     * called. This method is designed to be overridden by child classes to
+     * match their own debugging/logging mechanisms.
+     * @param format a format string
+     * @param args the arguments referenced by <code>format</code>
+     * @see java.io.PrintStream#printf(java.lang.String, java.lang.Object[])
+     */
+    public void debug(String format, Object... args) {
+        if (DEBUG) {
+            System.out.printf(format, args);
+        }
+    }
+
+    /**
+     * Prints out the content of a byte array, called in various places inside
+     * the NTLM implementation for debugging/logging purposes. When the system
+     * property "ntlm.debug" is set, the hexdump of the array is printed into
+     * System.out. This method is designed to be overridden by child classes to
+     * match their own debugging/logging mechanisms.
+     * @param bytes the byte array to print out
+     */
+    public void debug(byte[] bytes) {
+        if (DEBUG) {
+            try {
+                new sun.misc.HexDumpEncoder().encodeBuffer(bytes, System.out);
+            } catch (IOException ioe) {
+                // Impossible
+            }
+        }
+    }
+
+    /**
+     * Reading an NTLM packet
+     */
+    static class Reader {
+
+        private final byte[] internal;
+
+        Reader(byte[] data) {
+            internal = data;
+        }
+
+        int readInt(int offset) throws NTLMException {
+            try {
+                return internal[offset] & 0xff +
+                        (internal[offset+1] & 0xff << 8) +
+                        (internal[offset+2] & 0xff << 16) +
+                        (internal[offset+3] & 0xff << 24);
+            } catch (ArrayIndexOutOfBoundsException ex) {
+                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
+                        "Input message incorrect size");
+            }
+        }
+
+        int readShort(int offset) throws NTLMException {
+            try {
+                return internal[offset] & 0xff +
+                        (internal[offset+1] & 0xff << 8);
+            } catch (ArrayIndexOutOfBoundsException ex) {
+                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
+                        "Input message incorrect size");
+            }
+        }
+
+        byte[] readBytes(int offset, int len) throws NTLMException {
+            try {
+                return Arrays.copyOfRange(internal, offset, offset + len);
+            } catch (ArrayIndexOutOfBoundsException ex) {
+                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
+                        "Input message incorrect size");
+            }
+        }
+
+        byte[] readSecurityBuffer(int offset) throws NTLMException {
+            int pos = readInt(offset+4);
+            if (pos == 0) return null;
+            try {
+                return Arrays.copyOfRange(
+                        internal, pos, pos + readShort(offset));
+            } catch (ArrayIndexOutOfBoundsException ex) {
+                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
+                        "Input message incorrect size");
+            }
+        }
+
+        String readSecurityBuffer(int offset, boolean unicode)
+                throws NTLMException {
+            byte[] raw = readSecurityBuffer(offset);
+            try {
+                return raw == null ? null : new String(
+                        raw, unicode ? "UnicodeLittleUnmarked" : "ISO8859_1");
+            } catch (UnsupportedEncodingException ex) {
+                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
+                        "Invalid input encoding");
+            }
+        }
+    }
+
+    /**
+     * Writing an NTLM packet
+     */
+    static class Writer {
+
+        private byte[] internal;    // buffer
+        private int current;        // current written content interface buffer
+
+        /**
+         * Starts writing a NTLM packet
+         * @param type NEGOTIATE || CHALLENGE || AUTHENTICATE
+         * @param len the base length, without security buffers
+         */
+        Writer(int type, int len) {
+            assert len < 256;
+            internal = new byte[256];
+            current = len;
+            System.arraycopy (
+                    new byte[] {'N','T','L','M','S','S','P',0,(byte)type},
+                    0, internal, 0, 9);
+        }
+
+        void writeShort(int offset, int number) {
+            internal[offset] = (byte)(number);
+            internal[offset+1] = (byte)(number >> 8);
+        }
+
+        void writeInt(int offset, int number) {
+            internal[offset] = (byte)(number);
+            internal[offset+1] = (byte)(number >> 8);
+            internal[offset+2] = (byte)(number >> 16);
+            internal[offset+3] = (byte)(number >> 24);
+        }
+
+        void writeBytes(int offset, byte[] data) {
+            System.arraycopy(data, 0, internal, offset, data.length);
+        }
+
+        void writeSecurityBuffer(int offset, byte[] data) {
+            if (data == null) {
+                writeShort(offset+4, current);
+            } else {
+                int len = data.length;
+                if (current + len > internal.length) {
+                    internal = Arrays.copyOf(internal, current + len + 256);
+                }
+                writeShort(offset, len);
+                writeShort(offset+2, len);
+                writeShort(offset+4, current);
+                System.arraycopy(data, 0, internal, current, len);
+                current += len;
+            }
+        }
+
+        void writeSecurityBuffer(int offset, String str, boolean unicode) {
+            try {
+                writeSecurityBuffer(offset, str == null ? null : str.getBytes(
+                        unicode ? "UnicodeLittleUnmarked" : "ISO8859_1"));
+            } catch (UnsupportedEncodingException ex) {
+                assert false;
+            }
+        }
+
+        byte[] getBytes() {
+            return Arrays.copyOf(internal, current);
+        }
+    }
+
+    // LM/NTLM
+
+    /* Convert a 7 byte array to an 8 byte array (for a des key with parity)
+     * input starts at offset off
+     */
+    byte[] makeDesKey (byte[] input, int off) {
+        int[] in = new int [input.length];
+        for (int i=0; i<in.length; i++ ) {
+            in[i] = input[i]<0 ? input[i]+256: input[i];
+        }
+        byte[] out = new byte[8];
+        out[0] = (byte)in[off+0];
+        out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
+        out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
+        out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
+        out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
+        out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
+        out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
+        out[7] = (byte)((in[off+6] << 1) & 0xFF);
+        return out;
+    }
+
+    byte[] calcLMHash (byte[] pwb) {
+        byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+        byte[] pwb1 = new byte [14];
+        int len = pwb.length;
+        if (len > 14)
+            len = 14;
+        System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
+
+        try {
+            DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
+            DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
+
+            SecretKey key1 = fac.generateSecret (dks1);
+            SecretKey key2 = fac.generateSecret (dks2);
+            cipher.init (Cipher.ENCRYPT_MODE, key1);
+            byte[] out1 = cipher.doFinal (magic, 0, 8);
+            cipher.init (Cipher.ENCRYPT_MODE, key2);
+            byte[] out2 = cipher.doFinal (magic, 0, 8);
+            byte[] result = new byte [21];
+            System.arraycopy (out1, 0, result, 0, 8);
+            System.arraycopy (out2, 0, result, 8, 8);
+            return result;
+        } catch (InvalidKeyException ive) {
+            // Will not happen, all key material are 8 bytes
+            assert false;
+        } catch (InvalidKeySpecException ikse) {
+            // Will not happen, we only feed DESKeySpec to DES factory
+            assert false;
+        } catch (IllegalBlockSizeException ibse) {
+            // Will not happen, we encrypt 8 bytes
+            assert false;
+        } catch (BadPaddingException bpe) {
+            // Will not happen, this is encryption
+            assert false;
+        }
+        return null;    // will not happen, we returned already
+    }
+
+    byte[] calcNTHash (byte[] pw) {
+        byte[] out = md4.digest (pw);
+        byte[] result = new byte [21];
+        System.arraycopy (out, 0, result, 0, 16);
+        return result;
+    }
+
+    /* key is a 21 byte array. Split it into 3 7 byte chunks,
+     * Convert each to 8 byte DES keys, encrypt the text arg with
+     * each key and return the three results in a sequential []
+     */
+    byte[] calcResponse (byte[] key, byte[] text) {
+        try {
+            assert key.length == 21;
+            DESKeySpec dks1 = new DESKeySpec(makeDesKey(key, 0));
+            DESKeySpec dks2 = new DESKeySpec(makeDesKey(key, 7));
+            DESKeySpec dks3 = new DESKeySpec(makeDesKey(key, 14));
+            SecretKey key1 = fac.generateSecret(dks1);
+            SecretKey key2 = fac.generateSecret(dks2);
+            SecretKey key3 = fac.generateSecret(dks3);
+            cipher.init(Cipher.ENCRYPT_MODE, key1);
+            byte[] out1 = cipher.doFinal(text, 0, 8);
+            cipher.init(Cipher.ENCRYPT_MODE, key2);
+            byte[] out2 = cipher.doFinal(text, 0, 8);
+            cipher.init(Cipher.ENCRYPT_MODE, key3);
+            byte[] out3 = cipher.doFinal(text, 0, 8);
+            byte[] result = new byte[24];
+            System.arraycopy(out1, 0, result, 0, 8);
+            System.arraycopy(out2, 0, result, 8, 8);
+            System.arraycopy(out3, 0, result, 16, 8);
+            return result;
+        } catch (IllegalBlockSizeException ex) {    // None will happen
+            assert false;
+        } catch (BadPaddingException ex) {
+            assert false;
+        } catch (InvalidKeySpecException ex) {
+            assert false;
+        } catch (InvalidKeyException ex) {
+            assert false;
+        }
+        return null;
+    }
+
+    // LMv2/NTLMv2
+
+    byte[] hmacMD5(byte[] key, byte[] text) {
+        try {
+            SecretKeySpec skey =
+                    new SecretKeySpec(Arrays.copyOf(key, 16), "HmacMD5");
+            hmac.init(skey);
+            return hmac.doFinal(text);
+        } catch (InvalidKeyException ex) {
+            assert false;
+        } catch (RuntimeException e) {
+            assert false;
+        }
+        return null;
+    }
+
+    byte[] calcV2(byte[] nthash, String text, byte[] blob, byte[] challenge) {
+        try {
+            byte[] ntlmv2hash = hmacMD5(nthash,
+                    text.getBytes("UnicodeLittleUnmarked"));
+            byte[] cn = new byte[blob.length+8];
+            System.arraycopy(challenge, 0, cn, 0, 8);
+            System.arraycopy(blob, 0, cn, 8, blob.length);
+            byte[] result = new byte[16+blob.length];
+            System.arraycopy(hmacMD5(ntlmv2hash, cn), 0, result, 0, 16);
+            System.arraycopy(blob, 0, result, 16, blob.length);
+            return result;
+        } catch (UnsupportedEncodingException ex) {
+            assert false;
+        }
+        return null;
+    }
+
+    // NTLM2 LM/NTLM
+
+    static byte[] ntlm2LM(byte[] nonce) {
+        return Arrays.copyOf(nonce, 24);
+    }
+
+    byte[] ntlm2NTLM(byte[] ntlmHash, byte[] nonce, byte[] challenge) {
+        byte[] b = Arrays.copyOf(challenge, 16);
+        System.arraycopy(nonce, 0, b, 8, 8);
+        byte[] sesshash = Arrays.copyOf(md5.digest(b), 8);
+        return calcResponse(ntlmHash, sesshash);
+    }
+
+    // Password in ASCII and UNICODE
+
+    static byte[] getP1(char[] password) {
+        try {
+            return new String(password).toUpperCase().getBytes("ISO8859_1");
+        } catch (UnsupportedEncodingException ex) {
+            return null;
+        }
+    }
+
+    static byte[] getP2(char[] password) {
+        try {
+            return new String(password).getBytes("UnicodeLittleUnmarked");
+        } catch (UnsupportedEncodingException ex) {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/ntlm/NTLMException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.ntlm;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * An NTLM-related Exception
+ */
+public final class NTLMException extends GeneralSecurityException {
+
+    /**
+     * If the incoming packet is invalid.
+     */
+    public final static int PACKET_READ_ERROR = 1;
+
+    /**
+     * If the client cannot get a domain value from the server and the
+     * caller has not provided one.
+     */
+    public final static int NO_DOMAIN_INFO = 2;
+
+    /**
+     * If the domain provided by the client does not match the one received
+     * from server.
+     */
+    //public final static int DOMAIN_UNMATCH = 3;
+
+    /**
+     * If the client name is not found on server's user database.
+     */
+    public final static int USER_UNKNOWN = 3;
+
+    /**
+     * If authentication fails.
+     */
+    public final static int AUTH_FAILED = 4;
+
+    /**
+     * If an illegal version string is provided.
+     */
+    public final static int BAD_VERSION = 5;
+
+    private int errorCode;
+
+    /**
+     * Constructs an NTLMException object.
+     * @param errorCode the error code, which can be retrieved by
+     * the {@link #errorCode() } method.
+     * @param msg the string message, which can be retrived by
+     * the {@link Exception#getMessage() } method.
+     */
+    public NTLMException(int errorCode, String msg) {
+        super(msg);
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Returns the error code associated with this NTLMException.
+     * @return the error code
+     */
+    public int errorCode() {
+        return errorCode;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/ntlm/Server.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.ntlm;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * The NTLM server, not multi-thread enabled.<p>
+ * Example:
+ * <pre>
+ * Server server = new Server(null, "REALM") {
+ *     public char[] getPassword(String ntdomain, String username) {
+ *         switch (username) {
+ *             case "dummy": return "t0pSeCr3t".toCharArray();
+ *             case "guest": return "".toCharArray();
+ *             default: return null;
+ *         }
+ *     }
+ * };
+ * // Receive client request as type1
+ * byte[] type2 = server.type2(type1, nonce);
+ * // Send type2 to client and receive type3
+ * verify(type3, nonce);
+ * </pre>
+ */
+public abstract class Server extends NTLM {
+    final private String domain;
+    final private boolean allVersion;
+    /**
+     * Creates a Server instance.
+     * @param version the NTLM version to use, which can be:
+     * <ul>
+     * <li>NTLM: Original NTLM v1
+     * <li>NTLM2: NTLM v1 with Client Challenge
+     * <li>NTLMv2: NTLM v2
+     * </ul>
+     * If null, all versions will be supported. Please note that unless NTLM2
+     * is selected, authentication succeeds if one of LM (or LMv2) or
+     * NTLM (or NTLMv2) is verified.
+     * @param domain the domain, must not be null
+     * @throws NullPointerException if {@code domain} is null.
+     */
+    public Server(String version, String domain) throws NTLMException {
+        super(version);
+        if (domain == null) {
+            throw new NullPointerException("domain cannot be null");
+        }
+        this.allVersion = (version == null);
+        this.domain = domain;
+        debug("NTLM Server: (t,version) = (%s,%s)\n", domain, version);
+    }
+
+    /**
+     * Generates the Type 2 message
+     * @param type1 the Type1 message received, must not be null
+     * @param nonce the random 8-byte array to be used in message generation,
+     * must not be null
+     * @return the message generated
+     * @throws NullPointerException if type1 or nonce is null
+     * @throws NTLMException if the incoming message is invalid
+     */
+    public byte[] type2(byte[] type1, byte[] nonce) {
+        if (nonce == null) {
+            throw new NullPointerException("nonce cannot be null");
+        }
+        debug("NTLM Server: Type 1 received\n");
+        if (type1 != null) debug(type1);
+        Writer p = new Writer(2, 32);
+        int flags = 0x80205;
+        p.writeSecurityBuffer(12, domain, true);
+        p.writeInt(20, flags);
+        p.writeBytes(24, nonce);
+        debug("NTLM Server: Type 2 created\n");
+        debug(p.getBytes());
+        return p.getBytes();
+    }
+
+    /**
+     * Verifies the Type3 message received from client and returns
+     * various negotiated information.
+     * @param type3 the incoming Type3 message from client, must not be null
+     * @param nonce the same nonce provided in {@link #type2}, must not be null
+     * @return username and hostname of the client in a byte array
+     * @throws NullPointerException if {@code type3} or {@code nonce} is null
+     * @throws NTLMException if the incoming message is invalid
+     */
+    public String[] verify(byte[] type3, byte[] nonce)
+            throws NTLMException {
+        if (type3 == null || nonce == null) {
+            throw new NullPointerException("type1 or nonce cannot be null");
+        }
+        debug("NTLM Server: Type 3 received\n");
+        if (type3 != null) debug(type3);
+        Reader r = new Reader(type3);
+        String username = r.readSecurityBuffer(36, true);
+        String hostname = r.readSecurityBuffer(44, true);
+        String incomingDomain = r.readSecurityBuffer(28, true);
+        /*if (incomingDomain != null && !incomingDomain.equals(domain)) {
+            throw new NTLMException(NTLMException.DOMAIN_UNMATCH,
+                    "Wrong domain: " + incomingDomain +
+                    " vs " + domain); // Needed?
+        }*/
+        boolean verified = false;
+        char[] password = getPassword(domain, username);
+        if (password == null) {
+            throw new NTLMException(NTLMException.USER_UNKNOWN,
+                    "Unknown user");
+        }
+        byte[] incomingLM = r.readSecurityBuffer(12);
+        byte[] incomingNTLM = r.readSecurityBuffer(20);
+
+        if (!verified && (allVersion || v == Version.NTLM)) {
+            if (incomingLM.length > 0) {
+                byte[] pw1 = getP1(password);
+                byte[] lmhash = calcLMHash(pw1);
+                byte[] lmresponse = calcResponse (lmhash, nonce);
+                if (Arrays.equals(lmresponse, incomingLM)) {
+                    verified = true;
+                }
+            }
+            if (incomingNTLM.length > 0) {
+                byte[] pw2 = getP2(password);
+                byte[] nthash = calcNTHash(pw2);
+                byte[] ntresponse = calcResponse (nthash, nonce);
+                if (Arrays.equals(ntresponse, incomingNTLM)) {
+                    verified = true;
+                }
+            }
+            debug("NTLM Server: verify using NTLM: " + verified  + "\n");
+        }
+        if (!verified && (allVersion || v == Version.NTLM2)) {
+            byte[] pw2 = getP2(password);
+            byte[] nthash = calcNTHash(pw2);
+            byte[] clientNonce = Arrays.copyOf(incomingLM, 8);
+            byte[] ntlmresponse = ntlm2NTLM(nthash, clientNonce, nonce);
+            if (Arrays.equals(incomingNTLM, ntlmresponse)) {
+                verified = true;
+            }
+            debug("NTLM Server: verify using NTLM2: " + verified + "\n");
+        }
+        if (!verified && (allVersion || v == Version.NTLMv2)) {
+            byte[] pw2 = getP2(password);
+            byte[] nthash = calcNTHash(pw2);
+            if (incomingLM.length > 0) {
+                byte[] clientNonce = Arrays.copyOfRange(
+                        incomingLM, 16, incomingLM.length);
+                byte[] lmresponse = calcV2(nthash,
+                        username.toUpperCase(Locale.US)+incomingDomain,
+                        clientNonce, nonce);
+                if (Arrays.equals(lmresponse, incomingLM)) {
+                    verified = true;
+                }
+            }
+            if (incomingNTLM.length > 0) {
+                byte[] clientBlob = Arrays.copyOfRange(
+                        incomingNTLM, 16, incomingNTLM.length);
+                byte[] ntlmresponse = calcV2(nthash,
+                        username.toUpperCase(Locale.US)+incomingDomain,
+                        clientBlob, nonce);
+                if (Arrays.equals(ntlmresponse, incomingNTLM)) {
+                    verified = true;
+                }
+            }
+            debug("NTLM Server: verify using NTLMv2: " + verified + "\n");
+        }
+        if (!verified) {
+            throw new NTLMException(NTLMException.AUTH_FAILED,
+                    "None of LM and NTLM verified");
+        }
+        return new String[] {username, hostname};
+    }
+
+    /**
+     * Retrieves the password for a given user. This method should be
+     * overridden in a concrete class.
+     * @param domain can be null
+     * @param username must not be null
+     * @return the password for the user, or null if unknown
+     */
+    public abstract char[] getPassword(String domain, String username);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/ntlm/Version.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.ntlm;
+
+enum Version {
+    NTLM, NTLM2, NTLMv2
+}
--- a/src/share/classes/com/sun/security/sasl/Provider.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/com/sun/security/sasl/Provider.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,10 +35,12 @@
  * - CRAM-MD5
  * - DIGEST-MD5
  * - GSSAPI/Kerberos v5
+ * - NTLM
  * And server support for
  * - CRAM-MD5
  * - DIGEST-MD5
  * - GSSAPI/Kerberos v5
+ * - NTLM
  */
 
 public final class Provider extends java.security.Provider {
@@ -47,8 +49,8 @@
 
     private static final String info = "Sun SASL provider" +
         "(implements client mechanisms for: " +
-        "DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5;" +
-        " server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
+        "DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM;" +
+        " server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)";
 
     public Provider() {
         super("SunSASL", 1.7d, info);
@@ -58,6 +60,8 @@
                 // Client mechanisms
                 put("SaslClientFactory.DIGEST-MD5",
                     "com.sun.security.sasl.digest.FactoryImpl");
+                put("SaslClientFactory.NTLM",
+                    "com.sun.security.sasl.ntlm.FactoryImpl");
                 put("SaslClientFactory.GSSAPI",
                     "com.sun.security.sasl.gsskerb.FactoryImpl");
 
@@ -75,6 +79,8 @@
                     "com.sun.security.sasl.gsskerb.FactoryImpl");
                 put("SaslServerFactory.DIGEST-MD5",
                     "com.sun.security.sasl.digest.FactoryImpl");
+                put("SaslServerFactory.NTLM",
+                    "com.sun.security.sasl.ntlm.FactoryImpl");
                 return null;
             }
         });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.ntlm;
+
+import java.util.Map;
+
+import javax.security.sasl.*;
+import javax.security.auth.callback.CallbackHandler;
+
+import com.sun.security.sasl.util.PolicyUtils;
+
+
+/**
+  * Client and server factory for NTLM SASL client/server mechanisms.
+  * See NTLMClient and NTLMServer for input requirements.
+  *
+  * @since 1.7
+  */
+
+public final class FactoryImpl implements SaslClientFactory,
+SaslServerFactory{
+
+    private static final String myMechs[] = { "NTLM" };
+    private static final int mechPolicies[] = {
+            PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS
+    };
+
+    /**
+      * Empty constructor.
+      */
+    public FactoryImpl() {
+    }
+
+    /**
+     * Returns a new instance of the NTLM SASL client mechanism.
+     * Argument checks are performed in SaslClient's constructor.
+     * @returns a new SaslClient ; otherwise null if unsuccessful.
+     * @throws SaslException If there is an error creating the NTLM
+     * SASL client.
+     */
+    public SaslClient createSaslClient(String[] mechs,
+         String authorizationId, String protocol, String serverName,
+         Map<String,?> props, CallbackHandler cbh)
+         throws SaslException {
+
+         for (int i=0; i<mechs.length; i++) {
+            if (mechs[i].equals("NTLM") &&
+                    PolicyUtils.checkPolicy(mechPolicies[0], props)) {
+
+                return new NTLMClient(mechs[i], authorizationId,
+                    protocol, serverName, props, cbh);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a new instance of the NTLM SASL server mechanism.
+     * Argument checks are performed in SaslServer's constructor.
+     * @returns a new SaslServer ; otherwise null if unsuccessful.
+     * @throws SaslException If there is an error creating the NTLM
+     * SASL server.
+     */
+    public SaslServer createSaslServer(String mech,
+         String protocol, String serverName, Map<String,?> props, CallbackHandler cbh)
+         throws SaslException {
+
+         if (mech.equals("NTLM") &&
+                 PolicyUtils.checkPolicy(mechPolicies[0], props)) {
+             if (props != null) {
+                 String qop = (String)props.get(Sasl.QOP);
+                 if (qop != null && !qop.equals("auth")) {
+                     throw new SaslException("NTLM only support auth");
+                 }
+             }
+             if (cbh == null) {
+                 throw new SaslException(
+                        "Callback handler with support for AuthorizeCallback, "+
+                        "RealmCallback, NameCallback, and PasswordCallback " +
+                        "required");
+             }
+             return new NTLMServer(mech, protocol, serverName, props, cbh);
+         }
+         return null;
+    }
+
+    /**
+      * Returns the authentication mechanisms that this factory can produce.
+      *
+      * @returns String[] {"NTLM"} if policies in env match those of this
+      * factory.
+      */
+    public String[] getMechanismNames(Map<String,?> env) {
+        return PolicyUtils.filterMechs(myMechs, mechPolicies, env);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.ntlm;
+
+import com.sun.security.ntlm.Client;
+import com.sun.security.ntlm.NTLMException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Random;
+import javax.security.auth.callback.Callback;
+
+
+import javax.security.sasl.*;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+  * Required callbacks:
+  * - RealmCallback
+  *    handle can provide domain info for authentication, optional
+  * - NameCallback
+  *    handler must enter username to use for authentication
+  * - PasswordCallback
+  *    handler must enter password for username to use for authentication
+  *
+  * Environment properties that affect behavior of implementation:
+  *
+  * javax.security.sasl.qop
+  *    String, quality of protection; only "auth" is accepted, default "auth"
+  *
+  * com.sun.security.sasl.ntlm.version
+  *    String, name a specific version to use; can be:
+  *      LM/NTLM: Original NTLM v1
+  *      LM: Original NTLM v1, LM only
+  *      NTLM: Original NTLM v1, NTLM only
+  *      NTLM2: NTLM v1 with Client Challenge
+  *      LMv2/NTLMv2: NTLM v2
+  *      LMv2: NTLM v2, LM only
+  *      NTLMv2: NTLM v2, NTLM only
+  *    If not specified, use system property "ntlm.version". If
+  *    still not specified, use default value "LMv2/NTLMv2".
+  *
+  * com.sun.security.sasl.ntlm.random
+  *    java.util.Random, the nonce source to be used in NTLM v2 or NTLM v1 with
+  *    Client Challenge. Default null, an internal java.util.Random object
+  *    will be used
+  *
+  * Negotiated Properties:
+  *
+  * javax.security.sasl.qop
+  *    Always "auth"
+  *
+  * com.sun.security.sasl.html.domain
+  *    The domain for the user, provided by the server
+  *
+  * @see <a href="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</a>
+  * - Simple Authentication and Security Layer (SASL)
+  *
+  */
+final class NTLMClient implements SaslClient {
+
+    private static final String NTLM_VERSION =
+            "com.sun.security.sasl.ntlm.version";
+    private static final String NTLM_RANDOM =
+            "com.sun.security.sasl.ntlm.random";
+    private final static String NTLM_DOMAIN =
+            "com.sun.security.sasl.ntlm.domain";
+    private final static String NTLM_HOSTNAME =
+            "com.sun.security.sasl.ntlm.hostname";
+
+    private final Client client;
+    private final String mech;
+    private final Random random;
+
+    private int step = 0;   // 0-start,1-nego,2-auth,3-done
+
+    /**
+     * @param mech non-null
+     * @param authorizationId can be null or empty and ignored
+     * @param protocol non-null for Sasl, useless for NTLM
+     * @param serverName non-null for Sasl, but can be null for NTLM
+     * @param props can be null
+     * @param cbh can be null for Sasl, but will throw NPE for NTLM
+     * @throws SaslException
+     */
+    NTLMClient(String mech, String authzid, String protocol, String serverName,
+            Map props, CallbackHandler cbh) throws SaslException {
+
+        this.mech = mech;
+        String version = null;
+        Random rtmp = null;
+        String hostname = null;
+
+        if (props != null) {
+            String qop = (String)props.get(Sasl.QOP);
+            if (qop != null && !qop.equals("auth")) {
+                throw new SaslException("NTLM only support auth");
+            }
+            version = (String)props.get(NTLM_VERSION);
+            rtmp = (Random)props.get(NTLM_RANDOM);
+            hostname = (String)props.get(NTLM_HOSTNAME);
+        }
+        this.random = rtmp != null ? rtmp : new Random();
+
+        if (version == null) {
+            version = System.getProperty("ntlm.version");
+        }
+
+        RealmCallback dcb = (serverName != null && !serverName.isEmpty())?
+            new RealmCallback("Realm: ", serverName) :
+            new RealmCallback("Realm: ");
+        NameCallback ncb = (authzid != null && !authzid.isEmpty()) ?
+            new NameCallback("User name: ", authzid) :
+            new NameCallback("User name: ");
+        PasswordCallback pcb =
+            new PasswordCallback("Password: ", false);
+
+        try {
+            cbh.handle(new Callback[] {dcb, ncb, pcb});
+        } catch (UnsupportedCallbackException e) {
+            throw new SaslException("NTLM: Cannot perform callback to " +
+                "acquire realm, username or password", e);
+        } catch (IOException e) {
+            throw new SaslException(
+                "NTLM: Error acquiring realm, username or password", e);
+        }
+
+        if (hostname == null) {
+            try {
+                hostname = InetAddress.getLocalHost().getCanonicalHostName();
+            } catch (UnknownHostException e) {
+                hostname = "localhost";
+            }
+        }
+        try {
+            client = new Client(version, hostname,
+                    ncb.getName(),
+                    dcb.getText(),
+                    pcb.getPassword());
+        } catch (NTLMException ne) {
+            throw new SaslException(
+                    "NTLM: Invalid version string: " + version, ne);
+        }
+    }
+
+    @Override
+    public String getMechanismName() {
+        return mech;
+    }
+
+    @Override
+    public boolean isComplete() {
+        return step >= 2;
+    }
+
+    @Override
+    public byte[] unwrap(byte[] incoming, int offset, int len)
+            throws SaslException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public byte[] wrap(byte[] outgoing, int offset, int len)
+            throws SaslException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public Object getNegotiatedProperty(String propName) {
+        if (propName.equals(Sasl.QOP)) {
+            return "auth";
+        } else if (propName.equals(NTLM_DOMAIN)) {
+            return client.getDomain();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void dispose() throws SaslException {
+        client.dispose();
+    }
+
+    @Override
+    public boolean hasInitialResponse() {
+        return true;
+    }
+
+    @Override
+    public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
+        step++;
+        if (step == 1) {
+            return client.type1();
+        } else {
+            try {
+                byte[] nonce = new byte[8];
+                random.nextBytes(nonce);
+                return client.type3(challenge, nonce);
+            } catch (NTLMException ex) {
+                throw new SaslException("Type3 creation failed", ex);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.ntlm;
+
+import com.sun.security.ntlm.NTLMException;
+import com.sun.security.ntlm.Server;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Map;
+import java.util.Random;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.*;
+
+/**
+  * Required callbacks:
+  * - RealmCallback
+  *      used as key by handler to fetch password, optional
+  * - NameCallback
+  *      used as key by handler to fetch password
+  * - PasswordCallback
+  *      handler must enter password for username/realm supplied
+  *
+  * Environment properties that affect the implementation:
+  *
+  * javax.security.sasl.qop
+  *    String, quality of protection; only "auth" is accepted, default "auth"
+  *
+  * com.sun.security.sasl.ntlm.version
+  *    String, name a specific version to accept:
+  *      LM/NTLM: Original NTLM v1
+  *      LM: Original NTLM v1, LM only
+  *      NTLM: Original NTLM v1, NTLM only
+  *      NTLM2: NTLM v1 with Client Challenge
+  *      LMv2/NTLMv2: NTLM v2
+  *      LMv2: NTLM v2, LM only
+  *      NTLMv2: NTLM v2, NTLM only
+  *    If not specified, use system property "ntlm.version". If also
+  *    not specfied, all versions are accepted.
+  *
+  * com.sun.security.sasl.ntlm.domain
+  *    String, the domain of the server, default is server name (fqdn parameter)
+  *
+  * com.sun.security.sasl.ntlm.random
+  *    java.util.Random, the nonce source. Default null, an internal
+  *    java.util.Random object will be used
+  *
+  * Negotiated Properties:
+  *
+  * javax.security.sasl.qop
+  *    Always "auth"
+  *
+  * com.sun.security.sasl.ntlm.hostname
+  *    The hostname for the user, provided by the client
+  *
+  */
+
+final class NTLMServer implements SaslServer {
+
+    private final static String NTLM_VERSION =
+            "com.sun.security.sasl.ntlm.version";
+    private final static String NTLM_DOMAIN =
+            "com.sun.security.sasl.ntlm.domain";
+    private final static String NTLM_HOSTNAME =
+            "com.sun.security.sasl.ntlm.hostname";
+    private static final String NTLM_RANDOM =
+            "com.sun.security.sasl.ntlm.random";
+
+    private final Random random;
+    private final Server server;
+    private byte[] nonce;
+    private int step = 0;
+    private String authzId;
+    private final String mech;
+    private String hostname;
+
+    /**
+     * @param mech not null
+     * @param protocol not null for Sasl, ignored in NTLM
+     * @param serverName not null for Sasl, can be null in NTLM. If non-null,
+     * might be used as domain if not provided in props
+     * @param props can be null
+     * @param cbh can be null for Sasl, but will throw NPE in auth for NTLM
+     * @throws SaslException
+     */
+    NTLMServer(String mech, String protocol, String serverName,
+            Map props, final CallbackHandler cbh) throws SaslException {
+
+        this.mech = mech;
+        String version = null;
+        String domain = null;
+        Random rtmp = null;
+
+        if (props != null) {
+            domain = (String) props.get(NTLM_DOMAIN);
+            version = (String)props.get(NTLM_VERSION);
+            rtmp = (Random)props.get(NTLM_RANDOM);
+        }
+        random = rtmp != null ? rtmp : new Random();
+
+        if (version == null) {
+            version = System.getProperty("ntlm.version");
+        }
+        if (domain == null) {
+            domain = serverName;
+        }
+        if (domain == null) {
+            throw new NullPointerException("Domain must be provided as"
+                    + " the serverName argument or in props");
+        }
+
+        try {
+            server = new Server(version, domain) {
+                public char[] getPassword(String ntdomain, String username) {
+                    try {
+                        RealmCallback rcb = new RealmCallback(
+                                "Domain: ", ntdomain);
+                        NameCallback ncb = new NameCallback(
+                                "Name: ", username);
+                        PasswordCallback pcb = new PasswordCallback(
+                                "Password: ", false);
+                        cbh.handle(new Callback[] { rcb, ncb, pcb });
+                        char[] passwd = pcb.getPassword();
+                        pcb.clearPassword();
+                        return passwd;
+                    } catch (IOException ioe) {
+                        return null;
+                    } catch (UnsupportedCallbackException uce) {
+                        return null;
+                    }
+                }
+            };
+        } catch (NTLMException ne) {
+            throw new SaslException(
+                    "NTLM: Invalid version string: " + version, ne);
+        }
+        nonce = new byte[8];
+    }
+
+    @Override
+    public String getMechanismName() {
+        return mech;
+    }
+
+    @Override
+    public byte[] evaluateResponse(byte[] response) throws SaslException {
+        try {
+            step++;
+            if (step == 1) {
+                random.nextBytes(nonce);
+                return server.type2(response, nonce);
+            } else {
+                String[] out = server.verify(response, nonce);
+                authzId = out[0];
+                hostname = out[1];
+                return null;
+            }
+        } catch (GeneralSecurityException ex) {
+            throw new SaslException("", ex);
+        }
+    }
+
+    @Override
+    public boolean isComplete() {
+        return step >= 2;
+    }
+
+    @Override
+    public String getAuthorizationID() {
+        return authzId;
+    }
+
+    @Override
+    public byte[] unwrap(byte[] incoming, int offset, int len)
+            throws SaslException {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public byte[] wrap(byte[] outgoing, int offset, int len)
+            throws SaslException {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Object getNegotiatedProperty(String propName) {
+        if (propName.equals(Sasl.QOP)) {
+            return "auth";
+        } else if (propName.equals(NTLM_HOSTNAME)) {
+            return hostname;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void dispose() throws SaslException {
+        return;
+    }
+}
--- a/src/share/classes/java/lang/AutoCloseable.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/lang/AutoCloseable.java	Thu Sep 16 11:19:43 2010 -0700
@@ -34,8 +34,8 @@
 public interface AutoCloseable {
     /**
      * Close this resource, relinquishing any underlying resources.
-     * This method is invoked automatically by the automatic resource
-     * management block construct.
+     * This method is invoked automatically by the {@code
+     * try}-with-resources statement.
      *
      * <p>Classes implementing this method are strongly encouraged to
      * be declared to throw more specific exceptions (or no exception
--- a/src/share/classes/java/lang/ClassLoader.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/lang/ClassLoader.java	Thu Sep 16 11:19:43 2010 -0700
@@ -823,7 +823,7 @@
      * </tt></blockquote>
      *
      * @param  name
-     *         The expected <a href="#name">binary name</a. of the class, or
+     *         The expected <a href="#name">binary name</a>. of the class, or
      *         <tt>null</tt> if not known
      *
      * @param  b
--- a/src/share/classes/java/lang/Object.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/lang/Object.java	Thu Sep 16 11:19:43 2010 -0700
@@ -189,7 +189,9 @@
      * specific cloning operation. First, if the class of this object does
      * not implement the interface {@code Cloneable}, then a
      * {@code CloneNotSupportedException} is thrown. Note that all arrays
-     * are considered to implement the interface {@code Cloneable}.
+     * are considered to implement the interface {@code Cloneable} and that
+     * the return type of the {@code clone} method of an array type {@code T[]}
+     * is {@code T[]} where T is any reference or primitive type.
      * Otherwise, this method creates a new instance of the class of this
      * object and initializes all its fields with exactly the contents of
      * the corresponding fields of this object, as if by assignment; the
--- a/src/share/classes/java/lang/Throwable.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/lang/Throwable.java	Thu Sep 16 11:19:43 2010 -0700
@@ -498,8 +498,8 @@
      * }
      * </pre>
      * As of release 7, the platform supports the notion of
-     * <i>suppressed exceptions</i> (in conjunction with automatic
-     * resource management blocks). Any exceptions that were
+     * <i>suppressed exceptions</i> (in conjunction with the {@code
+     * try}-with-resources statement). Any exceptions that were
      * suppressed in order to deliver an exception are printed out
      * beneath the stack trace.  The format of this information
      * depends on the implementation, but the following example may be
@@ -805,7 +805,7 @@
 
     /**
      * Adds the specified exception to the list of exceptions that
-     * were suppressed, typically by the automatic resource management
+     * were suppressed, typically by the {@code try}-with-resources
      * statement, in order to deliver this exception.
      *
      * <p>Note that when one exception {@linkplain
@@ -839,7 +839,7 @@
 
     /**
      * Returns an array containing all of the exceptions that were
-     * suppressed, typically by the automatic resource management
+     * suppressed, typically by the {@code try}-with-resources
      * statement, in order to deliver this exception.
      *
      * @return an array containing all of the exceptions that were
--- a/src/share/classes/java/lang/reflect/Constructor.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/lang/reflect/Constructor.java	Thu Sep 16 11:19:43 2010 -0700
@@ -166,8 +166,7 @@
 
     /**
      * Returns the name of this constructor, as a string.  This is
-     * always the same as the simple name of the constructor's declaring
-     * class.
+     * the binary name of the constructor's declaring class.
      */
     public String getName() {
         return getDeclaringClass().getName();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/net/SdpSocketImpl.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.FileDescriptor;
+
+import sun.net.sdp.SdpSupport;
+
+/**
+ * SocketImpl that supports the SDP protocol
+ */
+class SdpSocketImpl extends PlainSocketImpl {
+    SdpSocketImpl() { }
+
+    @Override
+    protected void create(boolean stream) throws IOException {
+        if (!stream)
+            throw new UnsupportedOperationException("Must be a stream socket");
+        fd = SdpSupport.createSocket();
+        if (socket != null)
+            socket.setCreated();
+        if (serverSocket != null)
+            serverSocket.setCreated();
+    }
+}
--- a/src/share/classes/java/net/ServerSocket.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/net/ServerSocket.java	Thu Sep 16 11:19:43 2010 -0700
@@ -69,6 +69,15 @@
     private boolean oldImpl = false;
 
     /**
+     * Package-private constructor to create a ServerSocket associated with
+     * the given SocketImpl.
+     */
+    ServerSocket(SocketImpl impl) {
+        this.impl = impl;
+        impl.setServerSocket(this);
+    }
+
+    /**
      * Creates an unbound server socket.
      *
      * @exception IOException IO error when opening the socket.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/file/DirectoryIteratorException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.file;
+
+import java.util.ConcurrentModificationException;
+import java.util.Objects;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.InvalidObjectException;
+
+/**
+ * Runtime exception thrown if an I/O error is encountered when iterating over
+ * the entries in a directory. The I/O error is retrieved as an {@link
+ * IOException} using the {@link #getCause() getCause()} method.
+ *
+ * @since 1.7
+ * @see DirectoryStream
+ */
+
+public final class DirectoryIteratorException
+    extends ConcurrentModificationException
+{
+    private static final long serialVersionUID = -6012699886086212874L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   cause
+     *          the {@code IOException} that caused the directory iteration
+     *          to fail
+     *
+     * @throws  NullPointerException
+     *          if the cause is {@code null}
+     */
+    public DirectoryIteratorException(IOException cause) {
+        super(Objects.nonNull(cause));
+    }
+
+    /**
+     * Returns the cause of this exception.
+     *
+     * @return  the cause
+     */
+    @Override
+    public IOException getCause() {
+        return (IOException)super.getCause();
+    }
+
+    /**
+     * Called to read the object from a stream.
+     *
+     * @throws  InvalidObjectException
+     *          if the object is invalid or has a cause that is not
+     *          an {@code IOException}
+     */
+    private void readObject(ObjectInputStream s)
+        throws IOException, ClassNotFoundException
+    {
+        s.defaultReadObject();
+        Throwable cause = super.getCause();
+        if (!(cause instanceof IOException))
+            throw new InvalidObjectException("Cause must be an IOException");
+    }
+}
--- a/src/share/classes/java/nio/file/DirectoryStream.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/nio/file/DirectoryStream.java	Thu Sep 16 11:19:43 2010 -0700
@@ -31,60 +31,84 @@
 
 /**
  * An object to iterate over the entries in a directory. A directory stream
- * allows for convenient use of the for-each construct:
+ * allows for the convenient use of the for-each construct to iterate over a
+ * directory.
+ *
+ * <p> <b> While {@code DirectoryStream} extends {@code Iterable}, it is not a
+ * general-purpose {@code Iterable} as it supports only a single {@code
+ * Iterator}; invoking the {@link #iterator iterator} method to obtain a second
+ * or subsequent iterator throws {@code IllegalStateException}. </b>
+ *
+ * <p> An important property of the directory stream's {@code Iterator} is that
+ * its {@link Iterator#hasNext() hasNext} method is guaranteed to read-ahead by
+ * at least one element. If {@code hasNext} method returns {@code true}, and is
+ * followed by a call to the {@code next} method, it is guaranteed that the
+ * {@code next} method will not throw an exception due to an I/O error, or
+ * because the stream has been {@link #close closed}. The {@code Iterator} does
+ * not support the {@link Iterator#remove remove} operation.
+ *
+ * <p> A {@code DirectoryStream} is opened upon creation and is closed by
+ * invoking the {@code close} method. Closing a directory stream releases any
+ * resources associated with the stream. Failure to close the stream may result
+ * in a resource leak. The try-with-resources statement provides a useful
+ * construct to ensure that the stream is closed:
  * <pre>
  *   Path dir = ...
- *   DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream();
- *   try {
+ *   try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream()) {
  *       for (Path entry: stream) {
- *         ..
+ *           ...
  *       }
- *   } finally {
- *       stream.close();
  *   }
  * </pre>
  *
- * <p><b> A {@code DirectoryStream} is not a general-purpose {@code Iterable}.
- * While this interface extends {@code Iterable}, the {@code iterator} method
- * may only be invoked once to obtain the iterator; a second, or subsequent,
- * call to the {@code iterator} method throws {@code IllegalStateException}. </b>
- *
- * <p> A {@code DirectoryStream} is opened upon creation and is closed by
- * invoking the {@link #close close} method. Closing the directory stream
- * releases any resources associated with the stream. Once a directory stream
- * is closed, all further method invocations on the iterator throw {@link
- * java.util.ConcurrentModificationException} with cause {@link
- * ClosedDirectoryStreamException}.
+ * <p> Once a directory stream is closed, then further access to the directory,
+ * using the {@code Iterator}, behaves as if the end of stream has been reached.
+ * Due to read-ahead, the {@code Iterator} may return one or more elements
+ * after the directory stream has been closed. Once these buffered elements
+ * have been read, then subsequent calls to the {@code hasNext} method returns
+ * {@code false}, and subsequent calls to the {@code next} method will throw
+ * {@code NoSuchElementException}.
  *
  * <p> A directory stream is not required to be <i>asynchronously closeable</i>.
  * If a thread is blocked on the directory stream's iterator reading from the
  * directory, and another thread invokes the {@code close} method, then the
  * second thread may block until the read operation is complete.
  *
- * <p> The {@link Iterator#hasNext() hasNext} and {@link Iterator#next() next}
- * methods can encounter an I/O error when iterating over the directory in which
- * case {@code ConcurrentModificationException} is thrown with cause
- * {@link java.io.IOException}. The {@code hasNext} method is guaranteed to
- * read-ahead by at least one element. This means that if the {@code hasNext}
- * method returns {@code true} and is followed by a call to the {@code next}
- * method then it is guaranteed not to fail with a {@code
- * ConcurrentModificationException}.
+ * <p> If an I/O error is encountered when accessing the directory then it
+ * causes the {@code Iterator}'s {@code hasNext} or {@code next} methods to
+ * throw {@link DirectoryIteratorException} with the {@link IOException} as the
+ * cause. As stated above, the {@code hasNext} method is guaranteed to
+ * read-ahead by at least one element. This means that if {@code hasNext} method
+ * returns {@code true}, and is followed by a call to the {@code next} method,
+ * then it is guaranteed that the {@code next} method will not fail with a
+ * {@code DirectoryIteratorException}.
  *
  * <p> The elements returned by the iterator are in no specific order. Some file
  * systems maintain special links to the directory itself and the directory's
  * parent directory. Entries representing these links are not returned by the
  * iterator.
  *
- * <p> The iterator's {@link Iterator#remove() remove} method removes the
- * directory entry for the last element returned by the iterator, as if by
- * invoking the {@link Path#delete delete} method. If an I/O error or
- * security exception occurs then {@code ConcurrentModificationException} is
- * thrown with the cause.
- *
  * <p> The iterator is <i>weakly consistent</i>. It is thread safe but does not
  * freeze the directory while iterating, so it may (or may not) reflect updates
  * to the directory that occur after the {@code DirectoryStream} is created.
  *
+ * <p> <b>Usage Examples:</b>
+ * Suppose we want a list of the source files in a directory. This example uses
+ * both the for-each and try-with-resources constructs.
+ * <pre>
+ *   List&lt;Path&gt; listSourceFiles(Path dir) throws IOException {
+ *       List&lt;Path&gt; result = new ArrayList&lt;Path&gt;();
+ *       try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
+ *           for (Path entry: stream) {
+ *               result.add(entry);
+ *           }
+ *       } catch (DirectoryIteratorException ex) {
+ *           // I/O error encounted during the iteration, the cause is an IOException
+ *           throw ex.getCause();
+ *       }
+ *       return result;
+ *   }
+ * </pre>
  * @param   <T>     The type of element returned by the iterator
  *
  * @since 1.7
--- a/src/share/classes/java/nio/file/Path.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/nio/file/Path.java	Thu Sep 16 11:19:43 2010 -0700
@@ -984,11 +984,11 @@
      * directory.
      *
      * <p> Where the filter terminates due to an uncaught error or runtime
-     * exception then it is propogated to the iterator's {@link Iterator#hasNext()
+     * exception then it is propagated to the {@link Iterator#hasNext()
      * hasNext} or {@link Iterator#next() next} method. Where an {@code
-     * IOException} is thrown, it is propogated as a {@link
-     * java.util.ConcurrentModificationException} with the {@code
-     * IOException} as the cause.
+     * IOException} is thrown, it results in the {@code hasNext} or {@code
+     * next} method throwing a {@link DirectoryIteratorException} with the
+     * {@code IOException} as the cause.
      *
      * <p> When an implementation supports operations on entries in the
      * directory that execute in a race-free manner then the returned directory
--- a/src/share/classes/java/nio/file/SecureDirectoryStream.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/nio/file/SecureDirectoryStream.java	Thu Sep 16 11:19:43 2010 -0700
@@ -47,15 +47,6 @@
  * newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
  * be cast to that type in order to invoke the methods defined by this interface.
  *
- * <p> As specified by {@code DirectoryStream}, the iterator's {@link
- * java.util.Iterator#remove() remove} method removes the directory entry for
- * the last element returned by the iterator. In the case of a {@code
- * SecureDirectoryStream} the {@code remove} method behaves as if by invoking
- * the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
- * methods defined by this interface. The {@code remove} may require to examine
- * the file to determine if the file is a directory, and consequently, it may
- * not be atomic with respect to other file system operations.
- *
  * <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
  * provider}, and a security manager is set, then the permission checks are
  * performed using the path obtained by resolving the given relative path
--- a/src/share/classes/java/sql/CallableStatement.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/CallableStatement.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2436,4 +2436,64 @@
      */
      void setNClob(String parameterName, Reader reader)
        throws SQLException;
+
+    //------------------------- JDBC 4.1 -----------------------------------
+
+
+    /**
+     *<p>Returns an object representing the value of OUT parameter
+     * {@code parameterIndex} and will convert from the
+     * SQL type of the parameter to the requested Java data type, if the
+     * conversion is supported. If the conversion is not
+     * supported or null is specified for the type, a
+     * <code>SQLException</code> is thrown.
+     *<p>
+     * At a minimum, an implementation must support the conversions defined in
+     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
+     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
+     * Additional conversions may be supported and are vendor defined.
+     *
+     * @param parameterIndex the first parameter is 1, the second is 2, and so on
+     * @param type Class representing the Java data type to convert the
+     * designated parameter to.
+     * @return an instance of {@code type} holding the OUT parameter value
+     * @throws SQLException if conversion is not supported, type is null or
+     *         another error occurs. The getCause() method of the
+     * exception may provide a more detailed exception, for example, if
+     * a conversion error occurs
+     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @since 1.7
+     */
+     public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException;
+
+
+    /**
+     *<p>Returns an object representing the value of OUT parameter
+     * {@code parameterName} and will convert from the
+     * SQL type of the parameter to the requested Java data type, if the
+     * conversion is supported. If the conversion is not
+     * supported  or null is specified for the type, a
+     * <code>SQLException</code> is thrown.
+     *<p>
+     * At a minimum, an implementation must support the conversions defined in
+     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
+     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
+     * Additional conversions may be supported and are vendor defined.
+     *
+     * @param parameterName the name of the parameter
+     * @param type Class representing the Java data type to convert
+     * the designated parameter to.
+     * @return an instance of {@code type} holding the OUT parameter
+     * value
+     * @throws SQLException if conversion is not supported, type is null or
+     *         another error occurs. The getCause() method of the
+     * exception may provide a more detailed exception, for example, if
+     * a conversion error occurs
+     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @since 1.7
+     */
+     public <T> T getObject(String parameterName, Class<T> type) throws SQLException;
+
 }
--- a/src/share/classes/java/sql/Connection.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/Connection.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package java.sql;
 
 import java.util.Properties;
+import java.util.concurrent.Executor;
 
 /**
  * <P>A connection (session) with a specific
@@ -38,7 +39,7 @@
  * information is obtained with the <code>getMetaData</code> method.
  *
  * <P><B>Note:</B> When configuring a <code>Connection</code>, JDBC applications
- *  should use the appropritate <code>Connection</code> method such as
+ *  should use the appropriate <code>Connection</code> method such as
  *  <code>setAutoCommit</code> or <code>setTransactionIsolation</code>.
  *  Applications should not invoke SQL commands directly to change the connection's
  *   configuration when there is a JDBC method available.  By default a <code>Connection</code> object is in
@@ -80,7 +81,7 @@
  * @see ResultSet
  * @see DatabaseMetaData
  */
-public interface Connection  extends Wrapper {
+public interface Connection  extends Wrapper, AutoCloseable {
 
     /**
      * Creates a <code>Statement</code> object for sending
@@ -347,6 +348,13 @@
      * <P>
      * If the driver does not support catalogs, it will
      * silently ignore this request.
+     * <p>
+     * Calling {@code setCatalog} has no effect on previously created or prepared
+     * {@code Statement} objects. It is implementation defined whether a DBMS
+     * prepare operation takes place immediately when the {@code Connection}
+     * method {@code prepareStatement} or {@code prepareCall} is invoked.
+     * For maximum portability, {@code setCatalog} should be called before a
+     * {@code Statement} is created or prepared.
      *
      * @param catalog the name of a catalog (subspace in this
      *        <code>Connection</code> object's database) in which to work
@@ -598,7 +606,17 @@
      * <code>Connection</code> object.
      * Unless the application has added an entry, the type map returned
      * will be empty.
-     *
+     * <p>
+     * You must invoke <code>setTypeMap</code> after making changes to the
+     * <code>Map</code> object returned from
+     *  <code>getTypeMap</code> as a JDBC driver may create an internal
+     * copy of the <code>Map</code> object passed to <code>setTypeMap</code>:
+     * <p>
+     * <pre>
+     *      Map&lt;String,Class&lt;?&gt;&gt; myMap = con.getTypeMap();
+     *      myMap.put("mySchemaName.ATHLETES", Athletes.class);
+     *      con.setTypeMap(myMap);
+     * </pre>
      * @return the <code>java.util.Map</code> object associated
      *         with this <code>Connection</code> object
      * @exception SQLException if a database access error occurs
@@ -614,7 +632,16 @@
      * Installs the given <code>TypeMap</code> object as the type map for
      * this <code>Connection</code> object.  The type map will be used for the
      * custom mapping of SQL structured types and distinct types.
-     *
+     *<p>
+     * You must set the the values for the <code>TypeMap</code> prior to
+     * callng <code>setMap</code> as a JDBC driver may create an internal copy
+     * of the <code>TypeMap</code>:
+     * <p>
+     * <pre>
+     *      Map myMap&lt;String,Class&lt;?&gt;&gt; = new HashMap&lt;String,Class&lt;?&gt;&gt;();
+     *      myMap.put("mySchemaName.ATHLETES", Athletes.class);
+     *      con.setTypeMap(myMap);
+     * </pre>
      * @param map the <code>java.util.Map</code> object to install
      *        as the replacement for this <code>Connection</code>
      *        object's default type map
@@ -1274,4 +1301,186 @@
   */
  Struct createStruct(String typeName, Object[] attributes)
 throws SQLException;
+
+   //--------------------------JDBC 4.1 -----------------------------
+
+   /**
+    * Sets the given schema name to access.
+    * <P>
+    * If the driver does not support schemas, it will
+    * silently ignore this request.
+    * <p>
+    * Calling {@code setSchema} has no effect on previously created or prepared
+    * {@code Statement} objects. It is implementation defined whether a DBMS
+    * prepare operation takes place immediately when the {@code Connection}
+    * method {@code prepareStatement} or {@code prepareCall} is invoked.
+    * For maximum portability, {@code setSchema} should be called before a
+    * {@code Statement} is created or prepared.
+    *
+    * @param schema the name of a schema  in which to work
+    * @exception SQLException if a database access error occurs
+    * or this method is called on a closed connection
+    * @see #getSchema
+    * @since 1.7
+    */
+    void setSchema(String schema) throws SQLException;
+
+    /**
+     * Retrieves this <code>Connection</code> object's current schema name.
+     *
+     * @return the current schema name or <code>null</code> if there is none
+     * @exception SQLException if a database access error occurs
+     * or this method is called on a closed connection
+     * @see #setSchema
+     * @since 1.7
+     */
+    String getSchema() throws SQLException;
+
+    /**
+     * Terminates an open connection.  Calling <code>abort</code> results in:
+     * <ul>
+     * <li>The connection marked as closed
+     * <li>Closes any physical connection to the database
+     * <li>Releases resources used by the connection
+     * <li>Insures that any thread that is currently accessing the connection
+     * will either progress to completion or throw an <code>SQLException</code>.
+     * </ul>
+     * <p>
+     * Calling <code>abort</code> marks the connection closed and releases any
+     * resources. Calling <code>abort</code> on a closed connection is a
+     * no-op.
+     * <p>
+     * It is possible that the aborting and releasing of the resources that are
+     * held by the connection can take an extended period of time.  When the
+     * <code>abort</code> method returns, the connection will have been marked as
+     * closed and the <code>Executor</code> that was passed as a parameter to abort
+     * may still be executing tasks to release resources.
+     * <p>
+     * This method checks to see that there is an <code>SQLPermission</code>
+     * object before allowing the method to proceed.  If a
+     * <code>SecurityManager</code> exists and its
+     * <code>checkPermission</code> method denies calling <code>abort</code>,
+     * this method throws a
+     * <code>java.lang.SecurityException</code>.
+     * @param executor  The <code>Executor</code>  implementation which will
+     * be used by <code>abort</code>.
+     * @throws java.sql.SQLException if a database access error occurs or
+     * the {@code executor} is {@code null},
+     * @throws java.lang.SecurityException if a security manager exists and its
+     *    <code>checkPermission</code> method denies calling <code>abort</code>
+     * @see SecurityManager#checkPermission
+     * @see Executor
+     * @since 1.7
+     */
+    void abort(Executor executor) throws SQLException;
+
+    /**
+     *
+     * Sets the maximum period a <code>Connection</code> or
+     * objects created from the <code>Connection</code>
+     * will wait for the database to reply to any one request. If any
+     *  request remains unanswered, the waiting method will
+     * return with a <code>SQLException</code>, and the <code>Connection</code>
+     * or objects created from the <code>Connection</code>  will be marked as
+     * closed. Any subsequent use of
+     * the objects, with the exception of the <code>close</code>,
+     * <code>isClosed</code> or <code>Connection.isValid</code>
+     * methods, will result in  a <code>SQLException</code>.
+     * <p>
+     * <b>Note</b>: This method is intended to address a rare but serious
+     * condition where network partitions can cause threads issuing JDBC calls
+     * to hang uninterruptedly in socket reads, until the OS TCP-TIMEOUT
+     * (typically 10 minutes). This method is related to the
+     * {@link #abort abort() } method which provides an administrator
+     * thread a means to free any such threads in cases where the
+     * JDBC connection is accessible to the administrator thread.
+     * The <code>setNetworkTimeout</code> method will cover cases where
+     * there is no administrator thread, or it has no access to the
+     * connection. This method is severe in it's effects, and should be
+     * given a high enough value so it is never triggered before any more
+     * normal timeouts, such as transaction timeouts.
+     * <p>
+     * JDBC driver implementations  may also choose to support the
+     * {@code setNetworkTimeout} method to impose a limit on database
+     * response time, in environments where no network is present.
+     * <p>
+     * Drivers may internally implement some or all of their API calls with
+     * multiple internal driver-database transmissions, and it is left to the
+     * driver implementation to determine whether the limit will be
+     * applied always to the response to the API call, or to any
+     * single  request made during the API call.
+     * <p>
+     *
+     * This method can be invoked more than once, such as to set a limit for an
+     * area of JDBC code, and to reset to the default on exit from this area.
+     * Invocation of this method has no impact on already outstanding
+     * requests.
+     * <p>
+     * The {@code Statement.setQueryTimeout()} timeout value is independent of the
+     * timeout value specified in {@code setNetworkTimeout}. If the query timeout
+     * expires  before the network timeout then the
+     * statement execution will be canceled. If the network is still
+     * active the result will be that both the statement and connection
+     * are still usable. However if the network timeout expires before
+     * the query timeout or if the statement timeout fails due to network
+     * problems, the connection will be marked as closed, any resources held by
+     * the connection will be released and both the connection and
+     * statement will be unusable.
+     *<p>
+     * When the driver determines that the {@code setNetworkTimeout} timeout
+     * value has expired, the JDBC driver marks the connection
+     * closed and releases any resources held by the connection.
+     * <p>
+     *
+     * This method checks to see that there is an <code>SQLPermission</code>
+     * object before allowing the method to proceed.  If a
+     * <code>SecurityManager</code> exists and its
+     * <code>checkPermission</code> method denies calling
+     * <code>setNetworkTimeout</code>, this method throws a
+     * <code>java.lang.SecurityException</code>.
+     *
+     * @param executor  The <code>Executor</code>  implementation which will
+     * be used by <code>setNetworkTimeout</code>.
+     * @param milliseconds The time in milliseconds to wait for the database
+     * operation
+     *  to complete.  If the JDBC driver does not support milliseconds, the
+     * JDBC driver will round the value up to the nearest second.  If the
+     * timeout period expires before the operation
+     * completes, a SQLException will be thrown.
+     * A value of 0 indicates that there is not timeout for database operations.
+     * @throws java.sql.SQLException if a database access error occurs, this
+     * method is called on a closed connection,
+     * the {@code executor} is {@code null},
+     * or the value specified for <code>seconds</code> is less than 0.
+     * @throws java.lang.SecurityException if a security manager exists and its
+     *    <code>checkPermission</code> method denies calling
+     * <code>setNetworkTimeout</code>.
+     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @see SecurityManager#checkPermission
+     * @see Statement#setQueryTimeout
+     * @see #getNetworkTimeout
+     * @see #abort
+     * @see Executor
+     * @since 1.7
+     */
+    void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException;
+
+
+    /**
+     * Retrieves the number of milliseconds the driver will
+     * wait for a database request to complete.
+     * If the limit is exceeded, a
+     * <code>SQLException</code> is thrown.
+     *
+     * @return the current timeout limit in milliseconds; zero means there is
+     *         no limit
+     * @throws SQLException if a database access error occurs or
+     * this method is called on a closed <code>Connection</code>
+     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @see #setNetworkTimeout
+     * @since 1.7
+     */
+    int getNetworkTimeout() throws SQLException;
 }
--- a/src/share/classes/java/sql/DatabaseMetaData.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/DatabaseMetaData.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1342,10 +1342,10 @@
      * defined.
      *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
      *       <UL>
-     *       <LI> YES           --- if the parameter can include NULLs
-     *       <LI> NO            --- if the parameter cannot include NULLs
+     *       <LI> YES           --- if the column can include NULLs
+     *       <LI> NO            --- if the column cannot include NULLs
      *       <LI> empty string  --- if the nullability for the
-     * parameter is unknown
+     * column is unknown
      *       </UL>
      *  <LI><B>SPECIFIC_NAME</B> String  => the name which uniquely identifies this procedure within its schema.
      *  </OL>
@@ -1610,17 +1610,17 @@
      *      (starting at 1)
      *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
      *       <UL>
-     *       <LI> YES           --- if the parameter can include NULLs
-     *       <LI> NO            --- if the parameter cannot include NULLs
+     *       <LI> YES           --- if the column can include NULLs
+     *       <LI> NO            --- if the column cannot include NULLs
      *       <LI> empty string  --- if the nullability for the
-     * parameter is unknown
+     * column is unknown
      *       </UL>
-     *  <LI><B>SCOPE_CATLOG</B> String => catalog of table that is the scope
+     *  <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the scope
      *      of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
      *  <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the scope
      *      of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
      *  <LI><B>SCOPE_TABLE</B> String => table name that this the scope
-     *      of a reference attribure (<code>null</code> if the DATA_TYPE isn't REF)
+     *      of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
      *  <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated
      *      Ref type, SQL type from java.sql.Types (<code>null</code> if DATA_TYPE
      *      isn't DISTINCT or user-generated REF)
@@ -1629,11 +1629,16 @@
      *       <LI> YES           --- if the column is auto incremented
      *       <LI> NO            --- if the column is not auto incremented
      *       <LI> empty string  --- if it cannot be determined whether the column is auto incremented
-     * parameter is unknown
+     *       </UL>
+     *   <LI><B>IS_GENERATEDCOLUMN</B> String  => Indicates whether this is a generated column
+     *       <UL>
+     *       <LI> YES           --- if this a generated column
+     *       <LI> NO            --- if this not a generated column
+     *       <LI> empty string  --- if it cannot be determined whether this is a generated column
      *       </UL>
      *  </OL>
      *
-     * <p>The COLUMN_SIZE column the specified column size for the given column.
+     * <p>The COLUMN_SIZE column specifies the column size for the given column.
      * For numeric data, this is the maximum precision.  For character data, this is the length in characters.
      * For datetime datatypes, this is the length in characters of the String representation (assuming the
      * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes.  For the ROWID datatype,
@@ -3186,7 +3191,7 @@
      * Retrieves whether this database supports statement pooling.
      *
      * @return <code>true</code> if so; <code>false</code> otherwise
-     * @throws SQLExcpetion if a database access error occurs
+     * @throws SQLException if a database access error occurs
      * @since 1.4
      */
     boolean supportsStatementPooling() throws SQLException;
@@ -3568,4 +3573,83 @@
      */
     int functionReturnsTable    = 2;
 
+    //--------------------------JDBC 4.1 -----------------------------
+
+    /**
+     * Retrieves a description of the pseudo or hidden columns available
+     * in a given table within the specified catalog and schema.
+     * Pseudo or hidden columns may not always be stored within
+     * a table and are not visible in a ResultSet unless they are
+     * specified in the query's outermost SELECT list. Pseudo or hidden
+     * columns may not necessarily be able to be modified. If there are
+     * no pseudo or hidden columns, an empty ResultSet is returned.
+     *
+     * <P>Only column descriptions matching the catalog, schema, table
+     * and column name criteria are returned.  They are ordered by
+     * <code>TABLE_CAT</code>,<code>TABLE_SCHEM</code>, <code>TABLE_NAME</code>
+     * and <code>COLUMN_NAME</code>.
+     *
+     * <P>Each column description has the following columns:
+     *  <OL>
+     *  <LI><B>TABLE_CAT</B> String => table catalog (may be <code>null</code>)
+     *  <LI><B>TABLE_SCHEM</B> String => table schema (may be <code>null</code>)
+     *  <LI><B>TABLE_NAME</B> String => table name
+     *  <LI><B>COLUMN_NAME</B> String => column name
+     *  <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
+     *  <LI><B>COLUMN_SIZE</B> int => column size.
+     *  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits. Null is returned for data types where
+     * DECIMAL_DIGITS is not applicable.
+     *  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
+     *  <LI><B>COLUMN_USAGE</B> String => The allowed usage for the column.  The
+     *  value returned will correspond to the enum name returned by {@link PseudoColumnUsage#name PseudoColumnUsage.name()}
+     *  <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>)
+     *  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
+     *       maximum number of bytes in the column
+     *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
+     *       <UL>
+     *       <LI> YES           --- if the column can include NULLs
+     *       <LI> NO            --- if the column cannot include NULLs
+     *       <LI> empty string  --- if the nullability for the column is unknown
+     *       </UL>
+     *  </OL>
+     *
+     * <p>The COLUMN_SIZE column specifies the column size for the given column.
+     * For numeric data, this is the maximum precision.  For character data, this is the length in characters.
+     * For datetime datatypes, this is the length in characters of the String representation (assuming the
+     * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes.  For the ROWID datatype,
+     * this is the length in bytes. Null is returned for data types where the
+     * column size is not applicable.
+     *
+     * @param catalog a catalog name; must match the catalog name as it
+     *        is stored in the database; "" retrieves those without a catalog;
+     *        <code>null</code> means that the catalog name should not be used to narrow
+     *        the search
+     * @param schemaPattern a schema name pattern; must match the schema name
+     *        as it is stored in the database; "" retrieves those without a schema;
+     *        <code>null</code> means that the schema name should not be used to narrow
+     *        the search
+     * @param tableNamePattern a table name pattern; must match the
+     *        table name as it is stored in the database
+     * @param columnNamePattern a column name pattern; must match the column
+     *        name as it is stored in the database
+     * @return <code>ResultSet</code> - each row is a column description
+     * @exception SQLException if a database access error occurs
+     * @see PseudoColumnUsage
+     * @since 1.7
+     */
+    ResultSet getPseudoColumns(String catalog, String schemaPattern,
+                         String tableNamePattern, String columnNamePattern)
+        throws SQLException;
+
+    /**
+     * Retrieves whether a generated key will always be returned if the column
+     * name(s) or indexe(s) specified for the auto generated key column(s)
+     * are valid and the statement succeeds.  The key that is returned may or
+     * may not be based on the column(s) for the auto generated key.
+     * Consult your JDBC driver documentation for additional details.
+     * @return <code>true</code> if so; <code>false</code> otherwise
+     * @exception SQLException if a database access error occurs
+     * @since 1.7
+     */
+    boolean  generatedKeyAlwaysReturned() throws SQLException;
 }
--- a/src/share/classes/java/sql/Date.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/Date.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -96,11 +96,12 @@
      * a <code>Date</code> value.
      *
      * @param s a <code>String</code> object representing a date in
-     *        in the format "yyyy-mm-dd"
+     *        in the format "yyyy-[m]m-[d]d". The leading zero for <code>mm</code>
+     * and <code>dd</code> may also be omitted.
      * @return a <code>java.sql.Date</code> object representing the
      *         given date
      * @throws IllegalArgumentException if the date given is not in the
-     *         JDBC date escape format (yyyy-mm-dd)
+     *         JDBC date escape format (yyyy-[m]m-[d]d)
      */
     public static Date valueOf(String s) {
         final int YEAR_LENGTH = 4;
@@ -123,8 +124,9 @@
             String yyyy = s.substring(0, firstDash);
             String mm = s.substring(firstDash + 1, secondDash);
             String dd = s.substring(secondDash + 1);
-            if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
-                    dd.length() == DAY_LENGTH) {
+            if (yyyy.length() == YEAR_LENGTH &&
+                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
+                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
                 int year = Integer.parseInt(yyyy);
                 int month = Integer.parseInt(mm);
                 int day = Integer.parseInt(dd);
--- a/src/share/classes/java/sql/Driver.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/Driver.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package java.sql;
 
+import java.util.logging.Logger;
+
 /**
  * The interface that every driver class must implement.
  * <P>The Java SQL framework allows for multiple database drivers.
@@ -150,4 +152,19 @@
      *         otherwise
      */
     boolean jdbcCompliant();
+
+    //------------------------- JDBC 4.1 -----------------------------------
+
+    /**
+     * Return the parent Logger of all the Loggers used by this driver. This
+     * should be the Logger farthest from the root Logger that is
+     * still an ancestor of all of the Loggers used by this driver. Configuring
+     * this Logger will affect all of the log messages generated by the driver.
+     * In the worst case, this may be the root Logger.
+     *
+     * @return the parent Logger for this driver
+     * @throws SQLFeatureNotSupportedException if the driver does not use <code>java.util.logging<code>.
+     * @since 1.7
+     */
+    public Logger getParentLogger() throws SQLFeatureNotSupportedException;
 }
--- a/src/share/classes/java/sql/PreparedStatement.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/PreparedStatement.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,10 @@
      * @exception SQLException if a database access error occurs;
      * this method is called on a closed  <code>PreparedStatement</code> or the SQL
      *            statement does not return a <code>ResultSet</code> object
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      */
     ResultSet executeQuery() throws SQLException;
 
@@ -82,8 +86,11 @@
      *         or (2) 0 for SQL statements that return nothing
      * @exception SQLException if a database access error occurs;
      * this method is called on a closed  <code>PreparedStatement</code>
-     * or the SQL
-     *            statement returns a <code>ResultSet</code> object
+     * or the SQL statement returns a <code>ResultSet</code> object
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      */
     int executeUpdate() throws SQLException;
 
@@ -463,6 +470,10 @@
      * @exception SQLException if a database access error occurs;
      * this method is called on a closed <code>PreparedStatement</code>
      * or an argument is supplied to this method
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @see Statement#execute
      * @see Statement#getResultSet
      * @see Statement#getUpdateCount
@@ -1208,4 +1219,5 @@
      void setNClob(int parameterIndex, Reader reader)
        throws SQLException;
 
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/sql/PseudoColumnUsage.java	Thu Sep 16 11:19:43 2010 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.sql;
+
+
+/**
+ * Enumeration for pseudo/hidden column usage.
+ *
+ * @since 1.7
+ * @see DatabaseMetaData#getPseudoColumns
+ */
+public enum PseudoColumnUsage {
+
+    /**
+     * The pseudo/hidden column may only be used in a SELECT list.
+     */
+    SELECT_LIST_ONLY,
+
+    /**
+     * The pseudo/hidden column may only be used in a WHERE clause.
+     */
+    WHERE_CLAUSE_ONLY,
+
+    /**
+     * There are no restrictions on the usage of the pseudo/hidden columns.
+     */
+    NO_USAGE_RESTRICTIONS,
+
+    /**
+     * The usage of the pseudo/hidden column cannot be determined.
+     */
+    USAGE_UNKNOWN
+
+}
--- a/src/share/classes/java/sql/ResultSet.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/ResultSet.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -145,7 +145,7 @@
  * @see ResultSetMetaData
  */
 
-public interface ResultSet extends Wrapper {
+public interface ResultSet extends Wrapper, AutoCloseable {
 
     /**
      * Moves the cursor froward one row from its current position.
@@ -1187,6 +1187,9 @@
      * cursor on the last row; calling the method <code>absolute(-2)</code>
      * moves the cursor to the next-to-last row, and so on.
      *
+     * <p>If the row number specified is zero, the cursor is moved to
+     * before the first row.
+     *
      * <p>An attempt to position the cursor beyond the first/last row in
      * the result set leaves the cursor before the first row or after
      * the last row.
@@ -1196,9 +1199,10 @@
      * is the same as calling <code>last()</code>.
      *
      * @param row the number of the row to which the cursor should move.
-     *        A positive number indicates the row number counting from the
-     *        beginning of the result set; a negative number indicates the
-     *        row number counting from the end of the result set
+     *        A value of zero indicates that the cursor will be positioned
+     *        before the first row; a positive number indicates the row number
+     *        counting from the beginning of the result set; a negative number
+     *        indicates the row number counting from the end of the result set
      * @return <code>true</code> if the cursor is moved to a position in this
      * <code>ResultSet</code> object;
      * <code>false</code> if the cursor is before the first row or after the
@@ -2529,7 +2533,7 @@
      * @exception SQLException if the columnLabel is not valid;
      * if a database access error occurs
      * or this method is called on a closed result set
-      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method
      * @since 1.2
      */
@@ -4072,4 +4076,64 @@
      */
     void updateNClob(String columnLabel,  Reader reader) throws SQLException;
 
+    //------------------------- JDBC 4.1 -----------------------------------
+
+
+    /**
+     *<p>Retrieves the value of the designated column in the current row
+     * of this <code>ResultSet</code> object and will convert from the
+     * SQL type of the column to the requested Java data type, if the
+     * conversion is supported. If the conversion is not
+     * supported  or null is specified for the type, a
+     * <code>SQLException</code> is thrown.
+     *<p>
+     * At a minimum, an implementation must support the conversions defined in
+     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
+     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
+     * Additional conversions may be supported and are vendor defined.
+     *
+     * @param columnIndex the first column is 1, the second is 2, ...
+     * @param type Class representing the Java data type to convert the designated
+     * column to.
+     * @return an instance of {@code type} holding the column value
+     * @throws SQLException if conversion is not supported, type is null or
+     *         another error occurs. The getCause() method of the
+     * exception may provide a more detailed exception, for example, if
+     * a conversion error occurs
+     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @since 1.7
+     */
+     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException;
+
+
+    /**
+     *<p>Retrieves the value of the designated column in the current row
+     * of this <code>ResultSet</code> object and will convert from the
+     * SQL type of the column to the requested Java data type, if the
+     * conversion is supported. If the conversion is not
+     * supported  or null is specified for the type, a
+     * <code>SQLException</code> is thrown.
+     *<p>
+     * At a minimum, an implementation must support the conversions defined in
+     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
+     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
+     * Additional conversions may be supported and are vendor defined.
+     *
+     * @param columnLabel the label for the column specified with the SQL AS clause.
+     * If the SQL AS clause was not specified, then the label is the name
+     * of the column
+     * @param type Class representing the Java data type to convert the designated
+     * column to.
+     * @return an instance of {@code type} holding the column value
+     * @throws SQLException if conversion is not supported, type is null or
+     *         another error occurs. The getCause() method of the
+     * exception may provide a more detailed exception, for example, if
+     * a conversion error occurs
+     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
+     * this method
+     * @since 1.7
+     */
+     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException;
+
 }
--- a/src/share/classes/java/sql/SQLDataException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLDataException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,13 @@
 package java.sql;
 
 /**
- * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>22</i>'. This indicates
- * various data errors, including but not limited to not-allowed conversion, division by 0
- * and invalid arguments to functions.
- *
+ * The subclass of {@link SQLException} thrown when the SQLState class value
+ * is '<i>22</i>', or under vendor-specified conditions.  This indicates
+ * various data errors, including but not limited to data conversion errors,
+ * division by 0, and invalid arguments to functions.
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLDataException extends SQLNonTransientException {
--- a/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,13 @@
 package java.sql;
 
 /**
- * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>23</i>'. This indicates that an integrity
+ * The subclass of {@link SQLException} thrown when the SQLState class value
+ * is '<i>23</i>', or under vendor-specified conditions.
+ * This indicates that an integrity
  * constraint (foreign key, primary key or unique key) has been violated.
- *
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLIntegrityConstraintViolationException extends SQLNonTransientException {
--- a/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,13 @@
 package java.sql;
 
 /**
- * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>28</i>'. This indicated that the
- * authorization credentials presented during connection establishment are not valid.
- *
+ * The subclass of {@link SQLException} thrown when the SQLState class value
+ * is '<i>28</i>', or under vendor-specified conditions. This indicates that
+ * the authorization credentials presented during connection establishment
+ * are not valid.
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLInvalidAuthorizationSpecException extends SQLNonTransientException {
--- a/src/share/classes/java/sql/SQLNonTransientConnectionException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLNonTransientConnectionException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,13 @@
 package java.sql;
 
 /**
- * <P> The subclass of {@link SQLException} thrown for the SQLState
- * class value '<i>08</i>', representing
- * that the connection operation that failed will not succeed when
+ * The subclass of {@link SQLException} thrown for the SQLState
+ * class value '<i>08</i>', or under vendor-specified conditions.  This
+ * indicates that the connection operation that failed will not succeed if
  * the operation is retried without the cause of the failure being corrected.
  * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLNonTransientConnectionException extends java.sql.SQLNonTransientException {
--- a/src/share/classes/java/sql/SQLPermission.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLPermission.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,9 +30,14 @@
 
 /**
  * The permission for which the <code>SecurityManager</code> will check
- * when code that is running in an applet calls the
- * <code>DriverManager.setLogWriter</code> method or the
- * <code>DriverManager.setLogStream</code> (deprecated) method.
+ * when code that is running in an applet, or an application with a
+ * <code>SecurityManager</code> enabled, calls the
+ * <code>DriverManager.setLogWriter</code> method,
+ * <code>DriverManager.setLogStream</code> (deprecated) method,
+ * {@code SyncFactory.setJNDIContext} method,
+ * {@code SyncFactory.setLogger} method,
+ * {@code Connection.setNetworktimeout} method,
+ * or the <code>Connection.abort</code> method.
  * If there is no <code>SQLPermission</code> object, these methods
  * throw a <code>java.lang.SecurityException</code> as a runtime exception.
  * <P>
@@ -48,7 +53,6 @@
  * but <code>*loadLibrary</code> or <code>a*b</code> is not valid.
  * <P>
  * The following table lists all the possible <code>SQLPermission</code> target names.
- * Currently, the only name allowed is <code>setLog</code>.
  * The table gives a description of what the permission allows
  * and a discussion of the risks of granting code the permission.
  * <P>
@@ -67,9 +71,33 @@
  * The contents of the log may contain usernames and passwords,
  * SQL statements, and SQL data.</td>
  * </tr>
+ * <tr>
+ * <td>callAbort</td>
+ *   <td>Allows the invocation of the {@code Connection} method
+ *   {@code abort}</td>
+ *   <td>Permits an application to terminate a physical connection to a
+ *  database.</td>
+ * </tr>
+ * <tr>
+ * <td>setSyncFactory</td>
+ *   <td>Allows the invocation of the {@code SyncFactory} methods
+ *   {@code setJNDIContext} and {@code setLogger}</td>
+ *   <td>Permits an application to specify the JNDI context from which the
+ *   {@code SyncProvider} implementations can be retrieved from and the logging
+ *   object to be used by the{@codeSyncProvider} implementation.</td>
+ * </tr>
  *
+ * <tr>
+ * <td>setNetworkTimeout</td>
+ *   <td>Allows the invocation of the {@code Connection} method
+ *   {@code setNetworkTimeout}</td>
+ *   <td>Permits an application to specify the maximum period a
+ * <code>Connection</code> or
+ * objects created from the <code>Connection</code>
+ * will wait for the database to reply to any one request.</td>
+ * </tr>
  * </table>
- *
+ *<p>
  * The person running an applet decides what permissions to allow
  * and will run the <code>Policy Tool</code> to create an
  * <code>SQLPermission</code> in a policy file.  A programmer does
--- a/src/share/classes/java/sql/SQLSyntaxErrorException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLSyntaxErrorException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,12 @@
 package java.sql;
 
 /**
- * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>42</i>'. This indicates that the
+ * The subclass of {@link SQLException} thrown when the SQLState class value
+ * is '<i>42</i>', or under vendor-specified conditions. This indicates that the
  * in-progress query has violated SQL syntax rules.
- *
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLSyntaxErrorException extends SQLNonTransientException {
--- a/src/share/classes/java/sql/SQLTransactionRollbackException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLTransactionRollbackException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,13 @@
 package java.sql;
 
 /**
- * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>40</i>'. This indicates that the
- * current statement was automatically rolled back by the database becuase of deadlock or other
- * transaction serialization failures.
- *
+ * The subclass of {@link SQLException} thrown when the SQLState class value
+ * is '<i>40</i>', or under vendor-specified conditions. This indicates that the
+ * current statement was automatically rolled back by the database because
+ * of deadlock or other transaction serialization failures.
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLTransactionRollbackException extends SQLTransientException {
--- a/src/share/classes/java/sql/SQLTransientConnectionException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/SQLTransientConnectionException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,12 @@
 
 /**
  * The subclass of {@link SQLException} for the SQLState class
- * value '<i>08</i>', representing
- * that the connection operation that failed might be able to succeed when
+ * value '<i>08</i>', or under vendor-specified conditions.  This indicates
+ * that the connection operation that failed might be able to succeed if
  * the operation is retried without any application-level changes.
- *<p>
- *
+ * <p>
+ * Please consult your driver vendor documentation for the vendor-specified
+ * conditions for which this <code>Exception</code> may be thrown.
  * @since 1.6
  */
 public class SQLTransientConnectionException extends java.sql.SQLTransientException {
--- a/src/share/classes/java/sql/Statement.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/Statement.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,20 +40,27 @@
  * @see Connection#createStatement
  * @see ResultSet
  */
-public interface Statement extends Wrapper {
+public interface Statement extends Wrapper, AutoCloseable {
 
     /**
      * Executes the given SQL statement, which returns a single
      * <code>ResultSet</code> object.
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql an SQL statement to be sent to the database, typically a
      *        static SQL <code>SELECT</code> statement
      * @return a <code>ResultSet</code> object that contains the data produced
      *         by the given query; never <code>null</code>
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the given
+     * this method is called on a closed <code>Statement</code>, the given
      *            SQL statement produces anything other than a single
-     *            <code>ResultSet</code> object
+     *            <code>ResultSet</code> object, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      */
     ResultSet executeQuery(String sql) throws SQLException;
 
@@ -61,7 +68,9 @@
      * Executes the given SQL statement, which may be an <code>INSERT</code>,
      * <code>UPDATE</code>, or <code>DELETE</code> statement or an
      * SQL statement that returns nothing, such as an SQL DDL statement.
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
      * <code>DELETE</code>; or an SQL statement that returns nothing,
      * such as a DDL statement.
@@ -70,8 +79,13 @@
      *         or (2) 0 for SQL statements that return nothing
      *
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the given
-     *            SQL statement produces a <code>ResultSet</code> object
+     * this method is called on a closed <code>Statement</code>, the given
+     * SQL statement produces a <code>ResultSet</code> object, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      */
     int executeUpdate(String sql) throws SQLException;
 
@@ -198,11 +212,21 @@
     /**
      * Sets the number of seconds the driver will wait for a
      * <code>Statement</code> object to execute to the given number of seconds.
-     * If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC
-     * driver must apply this limit to the <code>execute</code>,
-     * <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver
-     * implementations may also apply this limit to <code>ResultSet</code> methods
+     *By default there is no limit on the amount of time allowed for a running
+     * statement to complete. If the limit is exceeded, an
+     * <code>SQLTimeoutException</code> is thrown.
+     * A JDBC driver must apply this limit to the <code>execute</code>,
+     * <code>executeQuery</code> and <code>executeUpdate</code> methods.
+     * <p>
+     * <strong>Note:</strong> JDBC driver implementations may also apply this
+     * limit to {@code ResultSet} methods
      * (consult your driver vendor documentation for details).
+     * <p>
+     * <strong>Note:</strong> In the case of {@code Statement} batching, it is
+     * implementation defined as to whether the time-out is applied to
+     * individual SQL commands added via the {@code addBatch} method or to
+     * the entire batch of SQL commands invoked by the {@code executeBatch}
+     * method (consult your driver vendor documentation for details).
      *
      * @param seconds the new query timeout limit in seconds; zero means
      *        there is no limit
@@ -300,13 +324,21 @@
      * <code>getResultSet</code> or <code>getUpdateCount</code>
      * to retrieve the result, and <code>getMoreResults</code> to
      * move to any subsequent result(s).
-     *
+     * <p>
+     *<strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql any SQL statement
      * @return <code>true</code> if the first result is a <code>ResultSet</code>
      *         object; <code>false</code> if it is an update count or there are
      *         no results
-     * @exception SQLException if a database access error occurs or
-     * this method is called on a closed <code>Statement</code>
+     * @exception SQLException if a database access error occurs,
+     * this method is called on a closed <code>Statement</code>,
+     * the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @see #getResultSet
      * @see #getUpdateCount
      * @see #getMoreResults
@@ -465,12 +497,14 @@
      * <code>Statement</code> object. The commands in this list can be
      * executed as a batch by calling the method <code>executeBatch</code>.
      * <P>
-     *
+     *<strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql typically this is a SQL <code>INSERT</code> or
      * <code>UPDATE</code> statement
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the
-     * driver does not support batch updates
+     * this method is called on a closed <code>Statement</code>, the
+     * driver does not support batch updates, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @see #executeBatch
      * @see DatabaseMetaData#supportsBatchUpdates
      * @since 1.2
@@ -536,7 +570,10 @@
      * driver does not support batch statements. Throws {@link BatchUpdateException}
      * (a subclass of <code>SQLException</code>) if one of the commands sent to the
      * database fails to execute properly or attempts to return a result set.
-     *
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      *
      * @see #addBatch
      * @see DatabaseMetaData#supportsBatchUpdates
@@ -678,7 +715,9 @@
      * flag if the SQL statement
      * is not an <code>INSERT</code> statement, or an SQL statement able to return
      * auto-generated keys (the list of such statements is vendor-specific).
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
      * <code>DELETE</code>; or an SQL statement that returns nothing,
      * such as a DDL statement.
@@ -693,10 +732,15 @@
      *
      * @exception SQLException if a database access error occurs,
      *  this method is called on a closed <code>Statement</code>, the given
-     *            SQL statement returns a <code>ResultSet</code> object, or
-     *            the given constant is not one of those allowed
+     *            SQL statement returns a <code>ResultSet</code> object,
+     *            the given constant is not one of those allowed, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method with a constant of Statement.RETURN_GENERATED_KEYS
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @since 1.4
      */
     int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException;
@@ -709,7 +753,9 @@
      * available. The driver will ignore the array if the SQL statement
      * is not an <code>INSERT</code> statement, or an SQL statement able to return
      * auto-generated keys (the list of such statements is vendor-specific).
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
      * <code>DELETE</code>; or an SQL statement that returns nothing,
      * such as a DDL statement.
@@ -721,10 +767,15 @@
      *
      * @exception SQLException if a database access error occurs,
      * this method is called on a closed <code>Statement</code>, the SQL
-     *            statement returns a <code>ResultSet</code> object, or the
-     *            second argument supplied to this method is not an <code>int</code> array
-     *            whose elements are valid column indexes
+     * statement returns a <code>ResultSet</code> object,the second argument
+     * supplied to this method is not an
+     * <code>int</code> array whose elements are valid column indexes, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @since 1.4
      */
     int executeUpdate(String sql, int columnIndexes[]) throws SQLException;
@@ -737,7 +788,9 @@
      * available. The driver will ignore the array if the SQL statement
      * is not an <code>INSERT</code> statement, or an SQL statement able to return
      * auto-generated keys (the list of such statements is vendor-specific).
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
      * <code>DELETE</code>; or an SQL statement that returns nothing,
      * such as a DDL statement.
@@ -748,11 +801,15 @@
      *         that return nothing
      * @exception SQLException if a database access error occurs,
      *  this method is called on a closed <code>Statement</code>, the SQL
-     *            statement returns a <code>ResultSet</code> object, or the
+     *            statement returns a <code>ResultSet</code> object, the
      *            second argument supplied to this method is not a <code>String</code> array
-     *            whose elements are valid column names
-     *
+     *            whose elements are valid column names, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @since 1.4
      */
     int executeUpdate(String sql, String columnNames[]) throws SQLException;
@@ -776,7 +833,9 @@
      * <code>getResultSet</code> or <code>getUpdateCount</code>
      * to retrieve the result, and <code>getMoreResults</code> to
      * move to any subsequent result(s).
-     *
+     *<p>
+     *<strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql any SQL statement
      * @param autoGeneratedKeys a constant indicating whether auto-generated
      *        keys should be made available for retrieval using the method
@@ -787,12 +846,18 @@
      *         object; <code>false</code> if it is an update count or there are
      *         no results
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the second
+     * this method is called on a closed <code>Statement</code>, the second
      *         parameter supplied to this method is not
      *         <code>Statement.RETURN_GENERATED_KEYS</code> or
-     *         <code>Statement.NO_GENERATED_KEYS</code>.
+     *         <code>Statement.NO_GENERATED_KEYS</code>,
+     * the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method with a constant of Statement.RETURN_GENERATED_KEYS
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @see #getResultSet
      * @see #getUpdateCount
      * @see #getMoreResults
@@ -823,7 +888,9 @@
      * <code>getResultSet</code> or <code>getUpdateCount</code>
      * to retrieve the result, and <code>getMoreResults</code> to
      * move to any subsequent result(s).
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql any SQL statement
      * @param columnIndexes an array of the indexes of the columns in the
      *        inserted row that should be  made available for retrieval by a
@@ -832,10 +899,15 @@
      *         object; <code>false</code> if it is an update count or there
      *         are no results
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the
+     * this method is called on a closed <code>Statement</code>, the
      *            elements in the <code>int</code> array passed to this method
-     *            are not valid column indexes
+     *            are not valid column indexes, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @see #getResultSet
      * @see #getUpdateCount
      * @see #getMoreResults
@@ -865,7 +937,9 @@
      * <code>getResultSet</code> or <code>getUpdateCount</code>
      * to retrieve the result, and <code>getMoreResults</code> to
      * move to any subsequent result(s).
-     *
+     *<p>
+     * <strong>Note:</strong>This method cannot be called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
      * @param sql any SQL statement
      * @param columnNames an array of the names of the columns in the inserted
      *        row that should be made available for retrieval by a call to the
@@ -874,10 +948,15 @@
      *         object; <code>false</code> if it is an update count or there
      *         are no more results
      * @exception SQLException if a database access error occurs,
-     * this method is called on a closed <code>Statement</code> or the
+     * this method is called on a closed <code>Statement</code>,the
      *          elements of the <code>String</code> array passed to this
-     *          method are not valid column names
+     *          method are not valid column names, the method is called on a
+     * <code>PreparedStatement</code> or <code>CallableStatement</code>
      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
+     * @throws SQLTimeoutException when the driver has determined that the
+     * timeout value that was specified by the {@code setQueryTimeout}
+     * method has been exceeded and has at least attempted to cancel
+     * the currently running {@code Statement}
      * @see #getResultSet
      * @see #getUpdateCount
      * @see #getMoreResults
@@ -951,4 +1030,34 @@
         boolean isPoolable()
                 throws SQLException;
 
+    //--------------------------JDBC 4.1 -----------------------------
+
+    /**
+     * Specifies that this {@code Statement} will be closed when all its
+     * dependent result sets are closed. If execution of the {@code Statement}
+     * does not produce any result sets, this method has no effect.
+     * <p>
+     * <strong>Note:</strong> Multiple calls to {@code closeOnCompletion} do
+     * not toggle the effect on this {@code Statement}. However, a call to
+     * {@code closeOnCompletion} does effect both the subsequent execution of
+     * statements, and statements that currently have open, dependent,
+     * result sets.
+     *
+     * @throws SQLException if this method is called on a closed
+     * {@code Statement}
+     * @since 1.7
+     */
+    public void closeOnCompletion() throws SQLException;
+
+    /**
+     * Returns a value indicating whether this {@code Statement} will be
+     * closed when all dependent objects such as resultsets are closed.
+     * @return {@code true} if the {@code Statement} will be closed when all
+     * of its dependent objects are closed; {@code false} otherwise
+     * @throws SQLException if this method is called on a closed
+     * {@code Statement}
+     * @since 1.7
+     */
+    public boolean isCloseOnCompletion() throws SQLException;
+
 }
--- a/src/share/classes/java/sql/Timestamp.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/sql/Timestamp.java	Thu Sep 16 11:19:43 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -155,19 +155,26 @@
      * Converts a <code>String</code> object in JDBC timestamp escape format to a
      * <code>Timestamp</code> value.
      *
-     * @param s timestamp in format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>.  The
-     * fractional seconds may be omitted.
+     * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>.  The
+     * fractional seconds may be omitted. The leading zero for <code>mm</code>
+     * and <code>dd</code> may also be omitted.
+     *
      * @return corresponding <code>Timestamp</code> value
      * @exception java.lang.IllegalArgumentException if the given argument
-     * does not have the format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>
+     * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
      */
     public static Timestamp valueOf(String s) {
+        final int YEAR_LENGTH = 4;
+        final int MONTH_LENGTH = 2;
+        final int DAY_LENGTH = 2;
+        final int MAX_MONTH = 12;
+        final int MAX_DAY = 31;
         String date_s;
         String time_s;
         String nanos_s;
-        int year;
-        int month;
-        int day;
+        int year = 0;
+        int month = 0;
+        int day = 0;
         int hour;
         int minute;
         int second;
@@ -182,17 +189,9 @@
         String zeros = "000000000";
         String delimiterDate = "-";
         String delimiterTime = ":";
-        StringTokenizer stringTokeninzerDate;
-        StringTokenizer stringTokeninzerTime;
 
         if (s == null) throw new java.lang.IllegalArgumentException("null string");
 
-        int counterD = 0;
-        int intDate[] = {4,2,2};
-
-        int counterT = 0;
-        int intTime[] = {2,2,12};
-
         // Split the string into date and time components
         s = s.trim();
         dividingSpace = s.indexOf(' ');
@@ -203,30 +202,6 @@
             throw new java.lang.IllegalArgumentException(formatError);
         }
 
-        stringTokeninzerTime = new StringTokenizer(time_s, delimiterTime);
-        stringTokeninzerDate = new StringTokenizer(date_s, delimiterDate);
-
-        while(stringTokeninzerDate.hasMoreTokens()) {
-             String tokenDate = stringTokeninzerDate.nextToken();
-             if(tokenDate.length() != intDate[counterD] ) {
-                throw new java.lang.IllegalArgumentException(formatError);
-             }
-             counterD++;
-        }
-
-        /*
-         //Commenting this portion out for checking of time
-
-        while(stringTokeninzerTime.hasMoreTokens()) {
-             String tokenTime = stringTokeninzerTime.nextToken();
-
-             if (counterT < 2 && tokenTime.length() != intTime[counterT]  ) {
-                throw new java.lang.IllegalArgumentException(formatError);
-             }
-             counterT++;
-        }
-        */
-
         // Parse the date
         firstDash = date_s.indexOf('-');
         secondDash = date_s.indexOf('-', firstDash+1);
@@ -239,14 +214,24 @@
         period = time_s.indexOf('.', secondColon+1);
 
         // Convert the date
-        if ((firstDash > 0) && (secondDash > 0) &&
-            (secondDash < date_s.length()-1)) {
-            year = Integer.parseInt(date_s.substring(0, firstDash)) - 1900;
-            month =
-                Integer.parseInt(date_s.substring
-                                 (firstDash+1, secondDash)) - 1;
-            day = Integer.parseInt(date_s.substring(secondDash+1));
-        } else {
+        boolean parsedDate = false;
+        if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
+            String yyyy = date_s.substring(0, firstDash);
+            String mm = date_s.substring(firstDash + 1, secondDash);
+            String dd = date_s.substring(secondDash + 1);
+            if (yyyy.length() == YEAR_LENGTH &&
+                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
+                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
+                 year = Integer.parseInt(yyyy);
+                 month = Integer.parseInt(mm);
+                 day = Integer.parseInt(dd);
+
+                if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
+                    parsedDate = true;
+                }
+            }
+        }
+        if (! parsedDate) {
             throw new java.lang.IllegalArgumentException(formatError);
         }
 
@@ -272,10 +257,10 @@
                 second = Integer.parseInt(time_s.substring(secondColon+1));
             }
         } else {
-            throw new java.lang.IllegalArgumentException();
+            throw new java.lang.IllegalArgumentException(formatError);
         }
 
-        return new Timestamp(year, month, day, hour, minute, second, a_nanos);
+        return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
     }
 
     /**
@@ -502,14 +487,10 @@
 
     /**
      * Compares this <code>Timestamp</code> object to the given
-     * <code>Date</code>, which must be a <code>Timestamp</code>
-     * object. If the argument is not a <code>Timestamp</code> object,
-     * this method throws a <code>ClassCastException</code> object.
-     * (<code>Timestamp</code> objects are
-     * comparable only to other <code>Timestamp</code> objects.)
+     * <code>Date</code> object.
      *
-     * @param o the <code>Date</code> to be compared, which must be a
-     *        <code>Timestamp</code> object
+     * @param o the <code>Date</code> to be compared to
+     *          this <code>Timestamp</code> object
      * @return  the value <code>0</code> if this <code>Timestamp</code> object
      *          and the given object are equal; a value less than <code>0</code>
      *          if this  <code>Timestamp</code> object is before the given argument;
--- a/src/share/classes/java/util/ConcurrentModificationException.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/util/ConcurrentModificationException.java	Thu Sep 16 11:19:43 2010 -0700
@@ -49,9 +49,9 @@
  * <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
  * speaking, impossible to make any hard guarantees in the presence of
  * unsynchronized concurrent modification.  Fail-fast operations
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
  * Therefore, it would be wrong to write a program that depended on this
- * exception for its correctness: <i><tt>ConcurrentModificationException</tt>
+ * exception for its correctness: <i>{@code ConcurrentModificationException}
  * should be used only to detect bugs.</i>
  *
  * @author  Josh Bloch
@@ -77,7 +77,7 @@
     }
 
     /**
-     * Constructs a <tt>ConcurrentModificationException</tt> with the
+     * Constructs a {@code ConcurrentModificationException} with the
      * specified detail message.
      *
      * @param message the detail message pertaining to this exception.
@@ -85,4 +85,39 @@
     public ConcurrentModificationException(String message) {
         super(message);
     }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}.
+     *
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link Throwable#getCause()} method).  (A {@code null} value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     * @since  1.7
+     */
+    public ConcurrentModificationException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.
+     *
+     * <p>Note that the detail message associated with <code>cause</code> is
+     * <i>not</i> automatically incorporated in this exception's detail
+     * message.
+     *
+     * @param  message the detail message (which is saved for later retrieval
+     *         by the {@link Throwable#getMessage()} method).
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link Throwable#getCause()} method).  (A {@code null} value
+     *         is permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     * @since 1.7
+     */
+    public ConcurrentModificationException(String message, Throwable cause) {
+        super(message, cause);
+    }
 }
--- a/src/share/classes/java/util/Properties.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/util/Properties.java	Thu Sep 16 11:19:43 2010 -0700
@@ -912,9 +912,13 @@
      *
      * <p>The specified stream remains open after this method returns.
      *
-     * @param os the output stream on which to emit the XML document.
-     * @param comment a description of the property list, or <code>null</code>
-     *        if no comment is desired.
+     * @param os        the output stream on which to emit the XML document.
+     * @param comment   a description of the property list, or <code>null</code>
+     *                  if no comment is desired.
+     * @param  encoding the name of a supported
+     *                  <a href="../lang/package-summary.html#charenc">
+     *                  character encoding</a>
+     *
      * @throws IOException if writing to the specified output stream
      *         results in an <tt>IOException</tt>.
      * @throws NullPointerException if <code>os</code> is <code>null</code>,
--- a/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Sep 16 11:19:43 2010 -0700
@@ -40,16 +40,23 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.locks.Condition;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.LockSupport;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * An {@link ExecutorService} for running {@link ForkJoinTask}s.
  * A {@code ForkJoinPool} provides the entry point for submissions
- * from non-{@code ForkJoinTask}s, as well as management and
+ * from non-{@code ForkJoinTask} clients, as well as management and
  * monitoring operations.
  *
  * <p>A {@code ForkJoinPool} differs from other kinds of {@link
@@ -58,29 +65,19 @@
  * execute subtasks created by other active tasks (eventually blocking
  * waiting for work if none exist). This enables efficient processing
  * when most tasks spawn other subtasks (as do most {@code
- * ForkJoinTask}s). A {@code ForkJoinPool} may also be used for mixed
- * execution of some plain {@code Runnable}- or {@code Callable}-
- * based activities along with {@code ForkJoinTask}s. When setting
- * {@linkplain #setAsyncMode async mode}, a {@code ForkJoinPool} may
- * also be appropriate for use with fine-grained tasks of any form
- * that are never joined. Otherwise, other {@code ExecutorService}
- * implementations are typically more appropriate choices.
+ * ForkJoinTask}s). When setting <em>asyncMode</em> to true in
+ * constructors, {@code ForkJoinPool}s may also be appropriate for use
+ * with event-style tasks that are never joined.
  *
  * <p>A {@code ForkJoinPool} is constructed with a given target
  * parallelism level; by default, equal to the number of available
- * processors. Unless configured otherwise via {@link
- * #setMaintainsParallelism}, the pool attempts to maintain this
- * number of active (or available) threads by dynamically adding,
- * suspending, or resuming internal worker threads, even if some tasks
- * are stalled waiting to join others. However, no such adjustments
- * are performed in the face of blocked IO or other unmanaged
- * synchronization. The nested {@link ManagedBlocker} interface
- * enables extension of the kinds of synchronization accommodated.
- * The target parallelism level may also be changed dynamically
- * ({@link #setParallelism}). The total number of threads may be
- * limited using method {@link #setMaximumPoolSize}, in which case it
- * may become possible for the activities of a pool to stall due to
- * the lack of available threads to process new tasks.
+ * processors. The pool attempts to maintain enough active (or
+ * available) threads by dynamically adding, suspending, or resuming
+ * internal worker threads, even if some tasks are stalled waiting to
+ * join others. However, no such adjustments are guaranteed in the
+ * face of blocked IO or other unmanaged synchronization. The nested
+ * {@link ManagedBlocker} interface enables extension of the kinds of
+ * synchronization accommodated.
  *
  * <p>In addition to execution and lifecycle control methods, this
  * class provides status check methods (for example
@@ -89,6 +86,40 @@
  * {@link #toString} returns indications of pool state in a
  * convenient form for informal monitoring.
  *
+ * <p> As is the case with other ExecutorServices, there are three
+ * main task execution methods summarized in the following
+ * table. These are designed to be used by clients not already engaged
+ * in fork/join computations in the current pool.  The main forms of
+ * these methods accept instances of {@code ForkJoinTask}, but
+ * overloaded forms also allow mixed execution of plain {@code
+ * Runnable}- or {@code Callable}- based activities as well.  However,
+ * tasks that are already executing in a pool should normally
+ * <em>NOT</em> use these pool execution methods, but instead use the
+ * within-computation forms listed in the table.
+ *
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ *  <tr>
+ *    <td></td>
+ *    <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td>
+ *    <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td>
+ *  </tr>
+ *  <tr>
+ *    <td> <b>Arrange async execution</td>
+ *    <td> {@link #execute(ForkJoinTask)}</td>
+ *    <td> {@link ForkJoinTask#fork}</td>
+ *  </tr>
+ *  <tr>
+ *    <td> <b>Await and obtain result</td>
+ *    <td> {@link #invoke(ForkJoinTask)}</td>
+ *    <td> {@link ForkJoinTask#invoke}</td>
+ *  </tr>
+ *  <tr>
+ *    <td> <b>Arrange exec and obtain Future</td>
+ *    <td> {@link #submit(ForkJoinTask)}</td>
+ *    <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td>
+ *  </tr>
+ * </table>
+ *
  * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
  * used for all parallel task execution in a program or subsystem.
  * Otherwise, use would not usually outweigh the construction and
@@ -113,7 +144,8 @@
  * {@code IllegalArgumentException}.
  *
  * <p>This implementation rejects submitted tasks (that is, by throwing
- * {@link RejectedExecutionException}) only when the pool is shut down.
+ * {@link RejectedExecutionException}) only when the pool is shut down
+ * or internal resources have been exhausted.
  *
  * @since 1.7
  * @author Doug Lea
@@ -121,16 +153,247 @@
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
-     * See the extended comments interspersed below for design,
-     * rationale, and walkthroughs.
+     * Implementation Overview
+     *
+     * This class provides the central bookkeeping and control for a
+     * set of worker threads: Submissions from non-FJ threads enter
+     * into a submission queue. Workers take these tasks and typically
+     * split them into subtasks that may be stolen by other workers.
+     * The main work-stealing mechanics implemented in class
+     * ForkJoinWorkerThread give first priority to processing tasks
+     * from their own queues (LIFO or FIFO, depending on mode), then
+     * to randomized FIFO steals of tasks in other worker queues, and
+     * lastly to new submissions. These mechanics do not consider
+     * affinities, loads, cache localities, etc, so rarely provide the
+     * best possible performance on a given machine, but portably
+     * provide good throughput by averaging over these factors.
+     * (Further, even if we did try to use such information, we do not
+     * usually have a basis for exploiting it. For example, some sets
+     * of tasks profit from cache affinities, but others are harmed by
+     * cache pollution effects.)
+     *
+     * Beyond work-stealing support and essential bookkeeping, the
+     * main responsibility of this framework is to take actions when
+     * one worker is waiting to join a task stolen (or always held by)
+     * another.  Because we are multiplexing many tasks on to a pool
+     * of workers, we can't just let them block (as in Thread.join).
+     * We also cannot just reassign the joiner's run-time stack with
+     * another and replace it later, which would be a form of
+     * "continuation", that even if possible is not necessarily a good
+     * idea. Given that the creation costs of most threads on most
+     * systems mainly surrounds setting up runtime stacks, thread
+     * creation and switching is usually not much more expensive than
+     * stack creation and switching, and is more flexible). Instead we
+     * combine two tactics:
+     *
+     *   Helping: Arranging for the joiner to execute some task that it
+     *      would be running if the steal had not occurred.  Method
+     *      ForkJoinWorkerThread.helpJoinTask tracks joining->stealing
+     *      links to try to find such a task.
+     *
+     *   Compensating: Unless there are already enough live threads,
+     *      method helpMaintainParallelism() may create or
+     *      re-activate a spare thread to compensate for blocked
+     *      joiners until they unblock.
+     *
+     * It is impossible to keep exactly the target (parallelism)
+     * number of threads running at any given time.  Determining
+     * existence of conservatively safe helping targets, the
+     * availability of already-created spares, and the apparent need
+     * to create new spares are all racy and require heuristic
+     * guidance, so we rely on multiple retries of each.  Compensation
+     * occurs in slow-motion. It is triggered only upon timeouts of
+     * Object.wait used for joins. This reduces poor decisions that
+     * would otherwise be made when threads are waiting for others
+     * that are stalled because of unrelated activities such as
+     * garbage collection.
+     *
+     * The ManagedBlocker extension API can't use helping so relies
+     * only on compensation in method awaitBlocker.
+     *
+     * The main throughput advantages of work-stealing stem from
+     * decentralized control -- workers mostly steal tasks from each
+     * other. We do not want to negate this by creating bottlenecks
+     * implementing other management responsibilities. So we use a
+     * collection of techniques that avoid, reduce, or cope well with
+     * contention. These entail several instances of bit-packing into
+     * CASable fields to maintain only the minimally required
+     * atomicity. To enable such packing, we restrict maximum
+     * parallelism to (1<<15)-1 (enabling twice this (to accommodate
+     * unbalanced increments and decrements) to fit into a 16 bit
+     * field, which is far in excess of normal operating range.  Even
+     * though updates to some of these bookkeeping fields do sometimes
+     * contend with each other, they don't normally cache-contend with
+     * updates to others enough to warrant memory padding or
+     * isolation. So they are all held as fields of ForkJoinPool
+     * objects.  The main capabilities are as follows:
+     *
+     * 1. Creating and removing workers. Workers are recorded in the
+     * "workers" array. This is an array as opposed to some other data
+     * structure to support index-based random steals by workers.
+     * Updates to the array recording new workers and unrecording
+     * terminated ones are protected from each other by a lock
+     * (workerLock) but the array is otherwise concurrently readable,
+     * and accessed directly by workers. To simplify index-based
+     * operations, the array size is always a power of two, and all
+     * readers must tolerate null slots. Currently, all worker thread
+     * creation is on-demand, triggered by task submissions,
+     * replacement of terminated workers, and/or compensation for
+     * blocked workers. However, all other support code is set up to
+     * work with other policies.
+     *
+     * To ensure that we do not hold on to worker references that
+     * would prevent GC, ALL accesses to workers are via indices into
+     * the workers array (which is one source of some of the unusual
+     * code constructions here). In essence, the workers array serves
+     * as a WeakReference mechanism. Thus for example the event queue
+     * stores worker indices, not worker references. Access to the
+     * workers in associated methods (for example releaseEventWaiters)
+     * must both index-check and null-check the IDs. All such accesses
+     * ignore bad IDs by returning out early from what they are doing,
+     * since this can only be associated with shutdown, in which case
+     * it is OK to give up. On termination, we just clobber these
+     * data structures without trying to use them.
+     *
+     * 2. Bookkeeping for dynamically adding and removing workers. We
+     * aim to approximately maintain the given level of parallelism.
+     * When some workers are known to be blocked (on joins or via
+     * ManagedBlocker), we may create or resume others to take their
+     * place until they unblock (see below). Implementing this
+     * requires counts of the number of "running" threads (i.e., those
+     * that are neither blocked nor artificially suspended) as well as
+     * the total number.  These two values are packed into one field,
+     * "workerCounts" because we need accurate snapshots when deciding
+     * to create, resume or suspend.  Note however that the
+     * correspondence of these counts to reality is not guaranteed. In
+     * particular updates for unblocked threads may lag until they
+     * actually wake up.
+     *
+     * 3. Maintaining global run state. The run state of the pool
+     * consists of a runLevel (SHUTDOWN, TERMINATING, etc) similar to
+     * those in other Executor implementations, as well as a count of
+     * "active" workers -- those that are, or soon will be, or
+     * recently were executing tasks. The runLevel and active count
+     * are packed together in order to correctly trigger shutdown and
+     * termination. Without care, active counts can be subject to very
+     * high contention.  We substantially reduce this contention by
+     * relaxing update rules.  A worker must claim active status
+     * prospectively, by activating if it sees that a submitted or
+     * stealable task exists (it may find after activating that the
+     * task no longer exists). It stays active while processing this
+     * task (if it exists) and any other local subtasks it produces,
+     * until it cannot find any other tasks. It then tries
+     * inactivating (see method preStep), but upon update contention
+     * instead scans for more tasks, later retrying inactivation if it
+     * doesn't find any.
+     *
+     * 4. Managing idle workers waiting for tasks. We cannot let
+     * workers spin indefinitely scanning for tasks when none are
+     * available. On the other hand, we must quickly prod them into
+     * action when new tasks are submitted or generated.  We
+     * park/unpark these idle workers using an event-count scheme.
+     * Field eventCount is incremented upon events that may enable
+     * workers that previously could not find a task to now find one:
+     * Submission of a new task to the pool, or another worker pushing
+     * a task onto a previously empty queue.  (We also use this
+     * mechanism for configuration and termination actions that
+     * require wakeups of idle workers).  Each worker maintains its
+     * last known event count, and blocks when a scan for work did not
+     * find a task AND its lastEventCount matches the current
+     * eventCount. Waiting idle workers are recorded in a variant of
+     * Treiber stack headed by field eventWaiters which, when nonzero,
+     * encodes the thread index and count awaited for by the worker
+     * thread most recently calling eventSync. This thread in turn has
+     * a record (field nextEventWaiter) for the next waiting worker.
+     * In addition to allowing simpler decisions about need for
+     * wakeup, the event count bits in eventWaiters serve the role of
+     * tags to avoid ABA errors in Treiber stacks. Upon any wakeup,
+     * released threads also try to release at most two others.  The
+     * net effect is a tree-like diffusion of signals, where released
+     * threads (and possibly others) help with unparks.  To further
+     * reduce contention effects a bit, failed CASes to increment
+     * field eventCount are tolerated without retries in signalWork.
+     * Conceptually they are merged into the same event, which is OK
+     * when their only purpose is to enable workers to scan for work.
+     *
+     * 5. Managing suspension of extra workers. When a worker notices
+     * (usually upon timeout of a wait()) that there are too few
+     * running threads, we may create a new thread to maintain
+     * parallelism level, or at least avoid starvation. Usually, extra
+     * threads are needed for only very short periods, yet join
+     * dependencies are such that we sometimes need them in
+     * bursts. Rather than create new threads each time this happens,
+     * we suspend no-longer-needed extra ones as "spares". For most
+     * purposes, we don't distinguish "extra" spare threads from
+     * normal "core" threads: On each call to preStep (the only point
+     * at which we can do this) a worker checks to see if there are
+     * now too many running workers, and if so, suspends itself.
+     * Method helpMaintainParallelism looks for suspended threads to
+     * resume before considering creating a new replacement. The
+     * spares themselves are encoded on another variant of a Treiber
+     * Stack, headed at field "spareWaiters".  Note that the use of
+     * spares is intrinsically racy.  One thread may become a spare at
+     * about the same time as another is needlessly being created. We
+     * counteract this and related slop in part by requiring resumed
+     * spares to immediately recheck (in preStep) to see whether they
+     * should re-suspend.
+     *
+     * 6. Killing off unneeded workers. A timeout mechanism is used to
+     * shed unused workers: The oldest (first) event queue waiter uses
+     * a timed rather than hard wait. When this wait times out without
+     * a normal wakeup, it tries to shutdown any one (for convenience
+     * the newest) other spare or event waiter via
+     * tryShutdownUnusedWorker. This eventually reduces the number of
+     * worker threads to a minimum of one after a long enough period
+     * without use.
+     *
+     * 7. Deciding when to create new workers. The main dynamic
+     * control in this class is deciding when to create extra threads
+     * in method helpMaintainParallelism. We would like to keep
+     * exactly #parallelism threads running, which is an impossible
+     * task. We always need to create one when the number of running
+     * threads would become zero and all workers are busy. Beyond
+     * this, we must rely on heuristics that work well in the
+     * presence of transient phenomena such as GC stalls, dynamic
+     * compilation, and wake-up lags. These transients are extremely
+     * common -- we are normally trying to fully saturate the CPUs on
+     * a machine, so almost any activity other than running tasks
+     * impedes accuracy. Our main defense is to allow parallelism to
+     * lapse for a while during joins, and use a timeout to see if,
+     * after the resulting settling, there is still a need for
+     * additional workers.  This also better copes with the fact that
+     * some of the methods in this class tend to never become compiled
+     * (but are interpreted), so some components of the entire set of
+     * controls might execute 100 times faster than others. And
+     * similarly for cases where the apparent lack of work is just due
+     * to GC stalls and other transient system activity.
+     *
+     * Beware that there is a lot of representation-level coupling
+     * among classes ForkJoinPool, ForkJoinWorkerThread, and
+     * ForkJoinTask.  For example, direct access to "workers" array by
+     * workers, and direct access to ForkJoinTask.status by both
+     * ForkJoinPool and ForkJoinWorkerThread.  There is little point
+     * trying to reduce this, since any associated future changes in
+     * representations will need to be accompanied by algorithmic
+     * changes anyway.
+     *
+     * Style notes: There are lots of inline assignments (of form
+     * "while ((local = field) != 0)") which are usually the simplest
+     * way to ensure the required read orderings (which are sometimes
+     * critical). Also several occurrences of the unusual "do {}
+     * while (!cas...)" which is the simplest way to force an update of
+     * a CAS'ed variable. There are also other coding oddities that
+     * help some methods perform reasonably even when interpreted (not
+     * compiled), at the expense of some messy constructions that
+     * reduce byte code counts.
+     *
+     * The order of declarations in this file is: (1) statics (2)
+     * fields (along with constants used when unpacking some of them)
+     * (3) internal control methods (4) callbacks and other support
+     * for ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
+     * methods (plus a few little helpers).
      */
 
-    /** Mask for packing and unpacking shorts */
-    private static final int  shortMask = 0xffff;
-
-    /** Max pool size -- must be a power of two minus 1 */
-    private static final int MAX_THREADS =  0x7FFF;
-
     /**
      * Factory for creating new {@link ForkJoinWorkerThread}s.
      * A {@code ForkJoinWorkerThreadFactory} must be defined and used
@@ -151,14 +414,10 @@
      * Default ForkJoinWorkerThreadFactory implementation; creates a
      * new ForkJoinWorkerThread.
      */
-    static class  DefaultForkJoinWorkerThreadFactory
+    static class DefaultForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
         public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            try {
-                return new ForkJoinWorkerThread(pool);
-            } catch (OutOfMemoryError oom)  {
-                return null;
-            }
+            return new ForkJoinWorkerThread(pool);
         }
     }
 
@@ -194,29 +453,59 @@
         new AtomicInteger();
 
     /**
-     * Array holding all worker threads in the pool. Initialized upon
-     * first use. Array size must be a power of two.  Updates and
-     * replacements are protected by workerLock, but it is always kept
-     * in a consistent enough state to be randomly accessed without
-     * locking by workers performing work-stealing.
+     * The time to block in a join (see awaitJoin) before checking if
+     * a new worker should be (re)started to maintain parallelism
+     * level. The value should be short enough to maintain global
+     * responsiveness and progress but long enough to avoid
+     * counterproductive firings during GC stalls or unrelated system
+     * activity, and to not bog down systems with continual re-firings
+     * on GCs or legitimately long waits.
+     */
+    private static final long JOIN_TIMEOUT_MILLIS = 250L; // 4 per second
+
+    /**
+     * The wakeup interval (in nanoseconds) for the oldest worker
+     * waiting for an event to invoke tryShutdownUnusedWorker to
+     * shrink the number of workers.  The exact value does not matter
+     * too much. It must be short enough to release resources during
+     * sustained periods of idleness, but not so short that threads
+     * are continually re-created.
+     */
+    private static final long SHRINK_RATE_NANOS =
+        30L * 1000L * 1000L * 1000L; // 2 per minute
+
+    /**
+     * Absolute bound for parallelism level. Twice this number plus
+     * one (i.e., 0xfff) must fit into a 16bit field to enable
+     * word-packing for some counts and indices.
+     */
+    private static final int MAX_WORKERS   = 0x7fff;
+
+    /**
+     * Array holding all worker threads in the pool.  Array size must
+     * be a power of two.  Updates and replacements are protected by
+     * workerLock, but the array is always kept in a consistent enough
+     * state to be randomly accessed without locking by workers
+     * performing work-stealing, as well as other traversal-based
+     * methods in this class. All readers must tolerate that some
+     * array slots may be null.
      */
     volatile ForkJoinWorkerThread[] workers;
 
     /**
-     * Lock protecting access to workers.
+     * Queue for external submissions.
+     */
+    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
+
+    /**
+     * Lock protecting updates to workers array.
      */
     private final ReentrantLock workerLock;
 
     /**
-     * Condition for awaitTermination.
+     * Latch released upon termination.
      */
-    private final Condition termination;
-
-    /**
-     * The uncaught exception handler used when any worker
-     * abruptly terminates
-     */
-    private Thread.UncaughtExceptionHandler ueh;
+    private final Phaser termination;
 
     /**
      * Creation factory for worker threads.
@@ -224,178 +513,717 @@
     private final ForkJoinWorkerThreadFactory factory;
 
     /**
-     * Head of stack of threads that were created to maintain
-     * parallelism when other threads blocked, but have since
-     * suspended when the parallelism level rose.
-     */
-    private volatile WaitQueueNode spareStack;
-
-    /**
      * Sum of per-thread steal counts, updated only when threads are
      * idle or terminating.
      */
-    private final AtomicLong stealCount;
+    private volatile long stealCount;
 
     /**
-     * Queue for external submissions.
+     * Encoded record of top of Treiber stack of threads waiting for
+     * events. The top 32 bits contain the count being waited for. The
+     * bottom 16 bits contains one plus the pool index of waiting
+     * worker thread. (Bits 16-31 are unused.)
      */
-    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
+    private volatile long eventWaiters;
+
+    private static final int  EVENT_COUNT_SHIFT = 32;
+    private static final long WAITER_ID_MASK    = (1L << 16) - 1L;
 
     /**
-     * Head of Treiber stack for barrier sync. See below for explanation.
+     * A counter for events that may wake up worker threads:
+     *   - Submission of a new task to the pool
+     *   - A worker pushing a task on an empty queue
+     *   - termination
      */
-    private volatile WaitQueueNode syncStack;
+    private volatile int eventCount;
 
     /**
-     * The count for event barrier
+     * Encoded record of top of Treiber stack of spare threads waiting
+     * for resumption. The top 16 bits contain an arbitrary count to
+     * avoid ABA effects. The bottom 16bits contains one plus the pool
+     * index of waiting worker thread.
      */
-    private volatile long eventCount;
+    private volatile int spareWaiters;
+
+    private static final int SPARE_COUNT_SHIFT = 16;
+    private static final int SPARE_ID_MASK     = (1 << 16) - 1;
+
+    /**
+     * Lifecycle control. The low word contains the number of workers
+     * that are (probably) executing tasks. This value is atomically
+     * incremented before a worker gets a task to run, and decremented
+     * when a worker has no tasks and cannot find any.  Bits 16-18
+     * contain runLevel value. When all are zero, the pool is
+     * running. Level transitions are monotonic (running -> shutdown
+     * -> terminating -> terminated) so each transition adds a bit.
+     * These are bundled together to ensure consistent read for
+     * termination checks (i.e., that runLevel is at least SHUTDOWN
+     * and active threads is zero).
+     *
+     * Notes: Most direct CASes are dependent on these bitfield
+     * positions.  Also, this field is non-private to enable direct
+     * performance-sensitive CASes in ForkJoinWorkerThread.
+     */
+    volatile int runState;
+
+    // Note: The order among run level values matters.
+    private static final int RUNLEVEL_SHIFT     = 16;
+    private static final int SHUTDOWN           = 1 << RUNLEVEL_SHIFT;
+    private static final int TERMINATING        = 1 << (RUNLEVEL_SHIFT + 1);
+    private static final int TERMINATED         = 1 << (RUNLEVEL_SHIFT + 2);
+    private static final int ACTIVE_COUNT_MASK  = (1 << RUNLEVEL_SHIFT) - 1;
+
+    /**
+     * Holds number of total (i.e., created and not yet terminated)
+     * and running (i.e., not blocked on joins or other managed sync)
+     * threads, packed together to ensure consistent snapshot when
+     * making decisions about creating and suspending spare
+     * threads. Updated only by CAS. Note that adding a new worker
+     * requires incrementing both counts, since workers start off in
+     * running state.
+     */
+    private volatile int workerCounts;
+
+    private static final int TOTAL_COUNT_SHIFT  = 16;
+    private static final int RUNNING_COUNT_MASK = (1 << TOTAL_COUNT_SHIFT) - 1;
+    private static final int ONE_RUNNING        = 1;
+    private static final int ONE_TOTAL          = 1 << TOTAL_COUNT_SHIFT;
+
+    /**
+     * The target parallelism level.
+     * Accessed directly by ForkJoinWorkerThreads.
+     */
+    final int parallelism;
+
+    /**
+     * True if use local fifo, not default lifo, for local polling
+     * Read by, and replicated by ForkJoinWorkerThreads
+     */
+    final boolean locallyFifo;
+
+    /**
+     * The uncaught exception handler used when any worker abruptly
+     * terminates.
+     */
+    private final Thread.UncaughtExceptionHandler ueh;
 
     /**
      * Pool number, just for assigning useful names to worker threads
      */
     private final int poolNumber;
 
-    /**
-     * The maximum allowed pool size
-     */
-    private volatile int maxPoolSize;
+    // Utilities for CASing fields. Note that most of these
+    // are usually manually inlined by callers
 
     /**
-     * The desired parallelism level, updated only under workerLock.
+     * Increments running count part of workerCounts
      */
-    private volatile int parallelism;
-
-    /**
-     * True if use local fifo, not default lifo, for local polling
-     */
-    private volatile boolean locallyFifo;
-
-    /**
-     * Holds number of total (i.e., created and not yet terminated)
-     * and running (i.e., not blocked on joins or other managed sync)
-     * threads, packed into one int to ensure consistent snapshot when
-     * making decisions about creating and suspending spare
-     * threads. Updated only by CAS.  Note: CASes in
-     * updateRunningCount and preJoin assume that running active count
-     * is in low word, so need to be modified if this changes.
-     */
-    private volatile int workerCounts;
-
-    private static int totalCountOf(int s)           { return s >>> 16;  }
-    private static int runningCountOf(int s)         { return s & shortMask; }
-    private static int workerCountsFor(int t, int r) { return (t << 16) + r; }
-
-    /**
-     * Adds delta (which may be negative) to running count.  This must
-     * be called before (with negative arg) and after (with positive)
-     * any managed synchronization (i.e., mainly, joins).
-     *
-     * @param delta the number to add
-     */
-    final void updateRunningCount(int delta) {
-        int s;
-        do {} while (!casWorkerCounts(s = workerCounts, s + delta));
+    final void incrementRunningCount() {
+        int c;
+        do {} while (!UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                               c = workerCounts,
+                                               c + ONE_RUNNING));
     }
 
     /**
-     * Adds delta (which may be negative) to both total and running
-     * count.  This must be called upon creation and termination of
-     * worker threads.
-     *
-     * @param delta the number to add
+     * Tries to decrement running count unless already zero
      */
-    private void updateWorkerCount(int delta) {
-        int d = delta + (delta << 16); // add to both lo and hi parts
-        int s;
-        do {} while (!casWorkerCounts(s = workerCounts, s + d));
+    final boolean tryDecrementRunningCount() {
+        int wc = workerCounts;
+        if ((wc & RUNNING_COUNT_MASK) == 0)
+            return false;
+        return UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                        wc, wc - ONE_RUNNING);
     }
 
     /**
-     * Lifecycle control. High word contains runState, low word
-     * contains the number of workers that are (probably) executing
-     * tasks. This value is atomically incremented before a worker
-     * gets a task to run, and decremented when worker has no tasks
-     * and cannot find any. These two fields are bundled together to
-     * support correct termination triggering.  Note: activeCount
-     * CAS'es cheat by assuming active count is in low word, so need
-     * to be modified if this changes
+     * Forces decrement of encoded workerCounts, awaiting nonzero if
+     * (rarely) necessary when other count updates lag.
+     *
+     * @param dr -- either zero or ONE_RUNNING
+     * @param dt -- either zero or ONE_TOTAL
      */
-    private volatile int runControl;
-
-    // RunState values. Order among values matters
-    private static final int RUNNING     = 0;
-    private static final int SHUTDOWN    = 1;
-    private static final int TERMINATING = 2;
-    private static final int TERMINATED  = 3;
-
-    private static int runStateOf(int c)             { return c >>> 16; }
-    private static int activeCountOf(int c)          { return c & shortMask; }
-    private static int runControlFor(int r, int a)   { return (r << 16) + a; }
-
-    /**
-     * Tries incrementing active count; fails on contention.
-     * Called by workers before/during executing tasks.
-     *
-     * @return true on success
-     */
-    final boolean tryIncrementActiveCount() {
-        int c = runControl;
-        return casRunControl(c, c+1);
+    private void decrementWorkerCounts(int dr, int dt) {
+        for (;;) {
+            int wc = workerCounts;
+            if ((wc & RUNNING_COUNT_MASK)  - dr < 0 ||
+                (wc >>> TOTAL_COUNT_SHIFT) - dt < 0) {
+                if ((runState & TERMINATED) != 0)
+                    return; // lagging termination on a backout
+                Thread.yield();
+            }
+            if (UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                         wc, wc - (dr + dt)))
+                return;
+        }
     }
 
     /**
      * Tries decrementing active count; fails on contention.
-     * Possibly triggers termination on success.
-     * Called by workers when they can't find tasks.
-     *
-     * @return true on success
+     * Called when workers cannot find tasks to run.
      */
     final boolean tryDecrementActiveCount() {
-        int c = runControl;
-        int nextc = c - 1;
-        if (!casRunControl(c, nextc))
+        int c;
+        return UNSAFE.compareAndSwapInt(this, runStateOffset,
+                                        c = runState, c - 1);
+    }
+
+    /**
+     * Advances to at least the given level. Returns true if not
+     * already in at least the given level.
+     */
+    private boolean advanceRunLevel(int level) {
+        for (;;) {
+            int s = runState;
+            if ((s & level) != 0)
+                return false;
+            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, s | level))
+                return true;
+        }
+    }
+
+    // workers array maintenance
+
+    /**
+     * Records and returns a workers array index for new worker.
+     */
+    private int recordWorker(ForkJoinWorkerThread w) {
+        // Try using slot totalCount-1. If not available, scan and/or resize
+        int k = (workerCounts >>> TOTAL_COUNT_SHIFT) - 1;
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            int n = ws.length;
+            if (k < 0 || k >= n || ws[k] != null) {
+                for (k = 0; k < n && ws[k] != null; ++k)
+                    ;
+                if (k == n)
+                    ws = Arrays.copyOf(ws, n << 1);
+            }
+            ws[k] = w;
+            workers = ws; // volatile array write ensures slot visibility
+        } finally {
+            lock.unlock();
+        }
+        return k;
+    }
+
+    /**
+     * Nulls out record of worker in workers array.
+     */
+    private void forgetWorker(ForkJoinWorkerThread w) {
+        int idx = w.poolIndex;
+        // Locking helps method recordWorker avoid unnecessary expansion
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (idx >= 0 && idx < ws.length && ws[idx] == w) // verify
+                ws[idx] = null;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Final callback from terminating worker.  Removes record of
+     * worker from array, and adjusts counts. If pool is shutting
+     * down, tries to complete termination.
+     *
+     * @param w the worker
+     */
+    final void workerTerminated(ForkJoinWorkerThread w) {
+        forgetWorker(w);
+        decrementWorkerCounts(w.isTrimmed()? 0 : ONE_RUNNING, ONE_TOTAL);
+        while (w.stealCount != 0) // collect final count
+            tryAccumulateStealCount(w);
+        tryTerminate(false);
+    }
+
+    // Waiting for and signalling events
+
+    /**
+     * Releases workers blocked on a count not equal to current count.
+     * Normally called after precheck that eventWaiters isn't zero to
+     * avoid wasted array checks. Gives up upon a change in count or
+     * upon releasing two workers, letting others take over.
+     */
+    private void releaseEventWaiters() {
+        ForkJoinWorkerThread[] ws = workers;
+        int n = ws.length;
+        long h = eventWaiters;
+        int ec = eventCount;
+        boolean releasedOne = false;
+        ForkJoinWorkerThread w; int id;
+        while ((id = ((int)(h & WAITER_ID_MASK)) - 1) >= 0 &&
+               (int)(h >>> EVENT_COUNT_SHIFT) != ec &&
+               id < n && (w = ws[id]) != null) {
+            if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
+                                          h,  w.nextWaiter)) {
+                LockSupport.unpark(w);
+                if (releasedOne) // exit on second release
+                    break;
+                releasedOne = true;
+            }
+            if (eventCount != ec)
+                break;
+            h = eventWaiters;
+        }
+    }
+
+    /**
+     * Tries to advance eventCount and releases waiters. Called only
+     * from workers.
+     */
+    final void signalWork() {
+        int c; // try to increment event count -- CAS failure OK
+        UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
+        if (eventWaiters != 0L)
+            releaseEventWaiters();
+    }
+
+    /**
+     * Adds the given worker to event queue and blocks until
+     * terminating or event count advances from the given value
+     *
+     * @param w the calling worker thread
+     * @param ec the count
+     */
+    private void eventSync(ForkJoinWorkerThread w, int ec) {
+        long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1));
+        long h;
+        while ((runState < SHUTDOWN || !tryTerminate(false)) &&
+               (((int)((h = eventWaiters) & WAITER_ID_MASK)) == 0 ||
+                (int)(h >>> EVENT_COUNT_SHIFT) == ec) &&
+               eventCount == ec) {
+            if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
+                                          w.nextWaiter = h, nh)) {
+                awaitEvent(w, ec);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Blocks the given worker (that has already been entered as an
+     * event waiter) until terminating or event count advances from
+     * the given value. The oldest (first) waiter uses a timed wait to
+     * occasionally one-by-one shrink the number of workers (to a
+     * minimum of one) if the pool has not been used for extended
+     * periods.
+     *
+     * @param w the calling worker thread
+     * @param ec the count
+     */
+    private void awaitEvent(ForkJoinWorkerThread w, int ec) {
+        while (eventCount == ec) {
+            if (tryAccumulateStealCount(w)) { // transfer while idle
+                boolean untimed = (w.nextWaiter != 0L ||
+                                   (workerCounts & RUNNING_COUNT_MASK) <= 1);
+                long startTime = untimed? 0 : System.nanoTime();
+                Thread.interrupted();         // clear/ignore interrupt
+                if (eventCount != ec || w.runState != 0 ||
+                    runState >= TERMINATING)  // recheck after clear
+                    break;
+                if (untimed)
+                    LockSupport.park(w);
+                else {
+                    LockSupport.parkNanos(w, SHRINK_RATE_NANOS);
+                    if (eventCount != ec || w.runState != 0 ||
+                        runState >= TERMINATING)
+                        break;
+                    if (System.nanoTime() - startTime >= SHRINK_RATE_NANOS)
+                        tryShutdownUnusedWorker(ec);
+                }
+            }
+        }
+    }
+
+    // Maintaining parallelism
+
+    /**
+     * Pushes worker onto the spare stack.
+     */
+    final void pushSpare(ForkJoinWorkerThread w) {
+        int ns = (++w.spareCount << SPARE_COUNT_SHIFT) | (w.poolIndex + 1);
+        do {} while (!UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
+                                               w.nextSpare = spareWaiters,ns));
+    }
+
+    /**
+     * Tries (once) to resume a spare if the number of running
+     * threads is less than target.
+     */
+    private void tryResumeSpare() {
+        int sw, id;
+        ForkJoinWorkerThread[] ws = workers;
+        int n = ws.length;
+        ForkJoinWorkerThread w;
+        if ((sw = spareWaiters) != 0 &&
+            (id = (sw & SPARE_ID_MASK) - 1) >= 0 &&
+            id < n && (w = ws[id]) != null &&
+            (workerCounts & RUNNING_COUNT_MASK) < parallelism &&
+            spareWaiters == sw &&
+            UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
+                                     sw, w.nextSpare)) {
+            int c; // increment running count before resume
+            do {} while (!UNSAFE.compareAndSwapInt
+                         (this, workerCountsOffset,
+                          c = workerCounts, c + ONE_RUNNING));
+            if (w.tryUnsuspend())
+                LockSupport.unpark(w);
+            else   // back out if w was shutdown
+                decrementWorkerCounts(ONE_RUNNING, 0);
+        }
+    }
+
+    /**
+     * Tries to increase the number of running workers if below target
+     * parallelism: If a spare exists tries to resume it via
+     * tryResumeSpare.  Otherwise, if not enough total workers or all
+     * existing workers are busy, adds a new worker. In all cases also
+     * helps wake up releasable workers waiting for work.
+     */
+    private void helpMaintainParallelism() {
+        int pc = parallelism;
+        int wc, rs, tc;
+        while (((wc = workerCounts) & RUNNING_COUNT_MASK) < pc &&
+               (rs = runState) < TERMINATING) {
+            if (spareWaiters != 0)
+                tryResumeSpare();
+            else if ((tc = wc >>> TOTAL_COUNT_SHIFT) >= MAX_WORKERS ||
+                     (tc >= pc && (rs & ACTIVE_COUNT_MASK) != tc))
+                break;   // enough total
+            else if (runState == rs && workerCounts == wc &&
+                     UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc,
+                                              wc + (ONE_RUNNING|ONE_TOTAL))) {
+                ForkJoinWorkerThread w = null;
+                try {
+                    w = factory.newThread(this);
+                } finally { // adjust on null or exceptional factory return
+                    if (w == null) {
+                        decrementWorkerCounts(ONE_RUNNING, ONE_TOTAL);
+                        tryTerminate(false); // handle failure during shutdown
+                    }
+                }
+                if (w == null)
+                    break;
+                w.start(recordWorker(w), ueh);
+                if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) {
+                    int c; // advance event count
+                    UNSAFE.compareAndSwapInt(this, eventCountOffset,
+                                             c = eventCount, c+1);
+                    break; // add at most one unless total below target
+                }
+            }
+        }
+        if (eventWaiters != 0L)
+            releaseEventWaiters();
+    }
+
+    /**
+     * Callback from the oldest waiter in awaitEvent waking up after a
+     * period of non-use. If all workers are idle, tries (once) to
+     * shutdown an event waiter or a spare, if one exists. Note that
+     * we don't need CAS or locks here because the method is called
+     * only from one thread occasionally waking (and even misfires are
+     * OK). Note that until the shutdown worker fully terminates,
+     * workerCounts will overestimate total count, which is tolerable.
+     *
+     * @param ec the event count waited on by caller (to abort
+     * attempt if count has since changed).
+     */
+    private void tryShutdownUnusedWorker(int ec) {
+        if (runState == 0 && eventCount == ec) { // only trigger if all idle
+            ForkJoinWorkerThread[] ws = workers;
+            int n = ws.length;
+            ForkJoinWorkerThread w = null;
+            boolean shutdown = false;
+            int sw;
+            long h;
+            if ((sw = spareWaiters) != 0) { // prefer killing spares
+                int id = (sw & SPARE_ID_MASK) - 1;
+                if (id >= 0 && id < n && (w = ws[id]) != null &&
+                    UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
+                                             sw, w.nextSpare))
+                    shutdown = true;
+            }
+            else if ((h = eventWaiters) != 0L) {
+                long nh;
+                int id = ((int)(h & WAITER_ID_MASK)) - 1;
+                if (id >= 0 && id < n && (w = ws[id]) != null &&
+                    (nh = w.nextWaiter) != 0L && // keep at least one worker
+                    UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh))
+                    shutdown = true;
+            }
+            if (w != null && shutdown) {
+                w.shutdown();
+                LockSupport.unpark(w);
+            }
+        }
+        releaseEventWaiters(); // in case of interference
+    }
+
+    /**
+     * Callback from workers invoked upon each top-level action (i.e.,
+     * stealing a task or taking a submission and running it).
+     * Performs one or more of the following:
+     *
+     * 1. If the worker is active and either did not run a task
+     *    or there are too many workers, try to set its active status
+     *    to inactive and update activeCount. On contention, we may
+     *    try again in this or a subsequent call.
+     *
+     * 2. If not enough total workers, help create some.
+     *
+     * 3. If there are too many running workers, suspend this worker
+     *    (first forcing inactive if necessary).  If it is not needed,
+     *    it may be shutdown while suspended (via
+     *    tryShutdownUnusedWorker).  Otherwise, upon resume it
+     *    rechecks running thread count and need for event sync.
+     *
+     * 4. If worker did not run a task, await the next task event via
+     *    eventSync if necessary (first forcing inactivation), upon
+     *    which the worker may be shutdown via
+     *    tryShutdownUnusedWorker.  Otherwise, help release any
+     *    existing event waiters that are now releasable,
+     *
+     * @param w the worker
+     * @param ran true if worker ran a task since last call to this method
+     */
+    final void preStep(ForkJoinWorkerThread w, boolean ran) {
+        int wec = w.lastEventCount;
+        boolean active = w.active;
+        boolean inactivate = false;
+        int pc = parallelism;
+        int rs;
+        while (w.runState == 0 && (rs = runState) < TERMINATING) {
+            if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) &&
+                UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1))
+                inactivate = active = w.active = false;
+            int wc = workerCounts;
+            if ((wc & RUNNING_COUNT_MASK) > pc) {
+                if (!(inactivate |= active) && // must inactivate to suspend
+                    workerCounts == wc &&      // try to suspend as spare
+                    UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                             wc, wc - ONE_RUNNING))
+                    w.suspendAsSpare();
+            }
+            else if ((wc >>> TOTAL_COUNT_SHIFT) < pc)
+                helpMaintainParallelism();     // not enough workers
+            else if (!ran) {
+                long h = eventWaiters;
+                int ec = eventCount;
+                if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec)
+                    releaseEventWaiters();     // release others before waiting
+                else if (ec != wec) {
+                    w.lastEventCount = ec;     // no need to wait
+                    break;
+                }
+                else if (!(inactivate |= active))
+                    eventSync(w, wec);         // must inactivate before sync
+            }
+            else
+                break;
+        }
+    }
+
+    /**
+     * Helps and/or blocks awaiting join of the given task.
+     * See above for explanation.
+     *
+     * @param joinMe the task to join
+     * @param worker the current worker thread
+     */
+    final void awaitJoin(ForkJoinTask<?> joinMe, ForkJoinWorkerThread worker) {
+        int retries = 2 + (parallelism >> 2); // #helpJoins before blocking
+        while (joinMe.status >= 0) {
+            int wc;
+            worker.helpJoinTask(joinMe);
+            if (joinMe.status < 0)
+                break;
+            else if (retries > 0)
+                --retries;
+            else if (((wc = workerCounts) & RUNNING_COUNT_MASK) != 0 &&
+                     UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                              wc, wc - ONE_RUNNING)) {
+                int stat, c; long h;
+                while ((stat = joinMe.status) >= 0 &&
+                       (h = eventWaiters) != 0L && // help release others
+                       (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
+                    releaseEventWaiters();
+                if (stat >= 0 &&
+                    ((workerCounts & RUNNING_COUNT_MASK) == 0 ||
+                     (stat =
+                      joinMe.internalAwaitDone(JOIN_TIMEOUT_MILLIS)) >= 0))
+                    helpMaintainParallelism(); // timeout or no running workers
+                do {} while (!UNSAFE.compareAndSwapInt
+                             (this, workerCountsOffset,
+                              c = workerCounts, c + ONE_RUNNING));
+                if (stat < 0)
+                    break;   // else restart
+            }
+        }
+    }
+
+    /**
+     * Same idea as awaitJoin, but no helping, retries, or timeouts.
+     */
+    final void awaitBlocker(ManagedBlocker blocker)
+        throws InterruptedException {
+        while (!blocker.isReleasable()) {
+            int wc = workerCounts;
+            if ((wc & RUNNING_COUNT_MASK) != 0 &&
+                UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+                                         wc, wc - ONE_RUNNING)) {
+                try {
+                    while (!blocker.isReleasable()) {
+                        long h = eventWaiters;
+                        if (h != 0L &&
+                            (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
+                            releaseEventWaiters();
+                        else if ((workerCounts & RUNNING_COUNT_MASK) == 0 &&
+                                 runState < TERMINATING)
+                            helpMaintainParallelism();
+                        else if (blocker.block())
+                            break;
+                    }
+                } finally {
+                    int c;
+                    do {} while (!UNSAFE.compareAndSwapInt
+                                 (this, workerCountsOffset,
+                                  c = workerCounts, c + ONE_RUNNING));
+                }
+                break;
+            }
+        }
+    }
+
+    /**
+     * Possibly initiates and/or completes termination.
+     *
+     * @param now if true, unconditionally terminate, else only
+     * if shutdown and empty queue and no active workers
+     * @return true if now terminating or terminated
+     */
+    private boolean tryTerminate(boolean now) {
+        if (now)
+            advanceRunLevel(SHUTDOWN); // ensure at least SHUTDOWN
+        else if (runState < SHUTDOWN ||
+                 !submissionQueue.isEmpty() ||
+                 (runState & ACTIVE_COUNT_MASK) != 0)
             return false;
-        if (canTerminateOnShutdown(nextc))
-            terminateOnShutdown();
+
+        if (advanceRunLevel(TERMINATING))
+            startTerminating();
+
+        // Finish now if all threads terminated; else in some subsequent call
+        if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) {
+            advanceRunLevel(TERMINATED);
+            termination.arrive();
+        }
         return true;
     }
 
     /**
-     * Returns {@code true} if argument represents zero active count
-     * and nonzero runstate, which is the triggering condition for
-     * terminating on shutdown.
+     * Actions on transition to TERMINATING
+     *
+     * Runs up to four passes through workers: (0) shutting down each
+     * (without waking up if parked) to quickly spread notifications
+     * without unnecessary bouncing around event queues etc (1) wake
+     * up and help cancel tasks (2) interrupt (3) mop up races with
+     * interrupted workers
      */
-    private static boolean canTerminateOnShutdown(int c) {
-        // i.e. least bit is nonzero runState bit
-        return ((c & -c) >>> 16) != 0;
-    }
-
-    /**
-     * Transition run state to at least the given state. Return true
-     * if not already at least given state.
-     */
-    private boolean transitionRunStateTo(int state) {
-        for (;;) {
-            int c = runControl;
-            if (runStateOf(c) >= state)
-                return false;
-            if (casRunControl(c, runControlFor(state, activeCountOf(c))))
-                return true;
+    private void startTerminating() {
+        cancelSubmissions();
+        for (int passes = 0; passes < 4 && workerCounts != 0; ++passes) {
+            int c; // advance event count
+            UNSAFE.compareAndSwapInt(this, eventCountOffset,
+                                     c = eventCount, c+1);
+            eventWaiters = 0L; // clobber lists
+            spareWaiters = 0;
+            for (ForkJoinWorkerThread w : workers) {
+                if (w != null) {
+                    w.shutdown();
+                    if (passes > 0 && !w.isTerminated()) {
+                        w.cancelTasks();
+                        LockSupport.unpark(w);
+                        if (passes > 1) {
+                            try {
+                                w.interrupt();
+                            } catch (SecurityException ignore) {
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
 
     /**
-     * Controls whether to add spares to maintain parallelism
+     * Clears out and cancels submissions, ignoring exceptions.
      */
-    private volatile boolean maintainsParallelism;
+    private void cancelSubmissions() {
+        ForkJoinTask<?> task;
+        while ((task = submissionQueue.poll()) != null) {
+            try {
+                task.cancel(false);
+            } catch (Throwable ignore) {
+            }
+        }
+    }
+
+    // misc support for ForkJoinWorkerThread
+
+    /**
+     * Returns pool number.
+     */
+    final int getPoolNumber() {
+        return poolNumber;
+    }
+
+    /**
+     * Tries to accumulate steal count from a worker, clearing
+     * the worker's value if successful.
+     *
+     * @return true if worker steal count now zero
+     */
+    final boolean tryAccumulateStealCount(ForkJoinWorkerThread w) {
+        int sc = w.stealCount;
+        long c = stealCount;
+        // CAS even if zero, for fence effects
+        if (UNSAFE.compareAndSwapLong(this, stealCountOffset, c, c + sc)) {
+            if (sc != 0)
+                w.stealCount = 0;
+            return true;
+        }
+        return sc == 0;
+    }
+
+    /**
+     * Returns the approximate (non-atomic) number of idle threads per
+     * active thread.
+     */
+    final int idlePerActive() {
+        int pc = parallelism; // use parallelism, not rc
+        int ac = runState;    // no mask -- artificially boosts during shutdown
+        // Use exact results for small values, saturate past 4
+        return ((pc <= ac) ? 0 :
+                (pc >>> 1 <= ac) ? 1 :
+                (pc >>> 2 <= ac) ? 3 :
+                pc >>> 3);
+    }
+
+    // Public and protected methods
 
     // Constructors
 
     /**
      * Creates a {@code ForkJoinPool} with parallelism equal to {@link
-     * java.lang.Runtime#availableProcessors}, and using the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     * java.lang.Runtime#availableProcessors}, using the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory},
+     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
      *
      * @throws SecurityException if a security manager exists and
      *         the caller is not permitted to modify threads
@@ -404,13 +1232,14 @@
      */
     public ForkJoinPool() {
         this(Runtime.getRuntime().availableProcessors(),
-             defaultForkJoinWorkerThreadFactory);
+             defaultForkJoinWorkerThreadFactory, null, false);
     }
 
     /**
      * Creates a {@code ForkJoinPool} with the indicated parallelism
-     * level and using the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     * level, the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory},
+     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
      *
      * @param parallelism the parallelism level
      * @throws IllegalArgumentException if parallelism less than or
@@ -421,31 +1250,25 @@
      *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool(int parallelism) {
-        this(parallelism, defaultForkJoinWorkerThreadFactory);
+        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
     }
 
     /**
-     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
-     * java.lang.Runtime#availableProcessors}, and using the given
-     * thread factory.
+     * Creates a {@code ForkJoinPool} with the given parameters.
      *
-     * @param factory the factory for creating new threads
-     * @throws NullPointerException if the factory is null
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
-     */
-    public ForkJoinPool(ForkJoinWorkerThreadFactory factory) {
-        this(Runtime.getRuntime().availableProcessors(), factory);
-    }
-
-    /**
-     * Creates a {@code ForkJoinPool} with the given parallelism and
-     * thread factory.
-     *
-     * @param parallelism the parallelism level
-     * @param factory the factory for creating new threads
+     * @param parallelism the parallelism level. For default value,
+     * use {@link java.lang.Runtime#availableProcessors}.
+     * @param factory the factory for creating new threads. For default value,
+     * use {@link #defaultForkJoinWorkerThreadFactory}.
+     * @param handler the handler for internal worker threads that
+     * terminate due to unrecoverable errors encountered while executing
+     * tasks. For default value, use {@code null}.
+     * @param asyncMode if true,
+     * establishes local first-in-first-out scheduling mode for forked
+     * tasks that are never joined. This mode may be more appropriate
+     * than default locally stack-based mode in applications in which
+     * worker threads only process event-style asynchronous tasks.
+     * For default value, use {@code false}.
      * @throws IllegalArgumentException if parallelism less than or
      *         equal to zero, or greater than implementation limit
      * @throws NullPointerException if the factory is null
@@ -454,153 +1277,40 @@
      *         because it does not hold {@link
      *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
-    public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory) {
-        if (parallelism <= 0 || parallelism > MAX_THREADS)
-            throw new IllegalArgumentException();
+    public ForkJoinPool(int parallelism,
+                        ForkJoinWorkerThreadFactory factory,
+                        Thread.UncaughtExceptionHandler handler,
+                        boolean asyncMode) {
+        checkPermission();
         if (factory == null)
             throw new NullPointerException();
-        checkPermission();
+        if (parallelism <= 0 || parallelism > MAX_WORKERS)
+            throw new IllegalArgumentException();
+        this.parallelism = parallelism;
         this.factory = factory;
-        this.parallelism = parallelism;
-        this.maxPoolSize = MAX_THREADS;
-        this.maintainsParallelism = true;
+        this.ueh = handler;
+        this.locallyFifo = asyncMode;
+        int arraySize = initialArraySizeFor(parallelism);
+        this.workers = new ForkJoinWorkerThread[arraySize];
+        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
+        this.workerLock = new ReentrantLock();
+        this.termination = new Phaser(1);
         this.poolNumber = poolNumberGenerator.incrementAndGet();
-        this.workerLock = new ReentrantLock();
-        this.termination = workerLock.newCondition();
-        this.stealCount = new AtomicLong();
-        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
-        // worker array and workers are lazily constructed
     }
 
     /**
-     * Creates a new worker thread using factory.
-     *
-     * @param index the index to assign worker
-     * @return new worker, or null if factory failed
+     * Returns initial power of two size for workers array.
+     * @param pc the initial parallelism level
      */
-    private ForkJoinWorkerThread createWorker(int index) {
-        Thread.UncaughtExceptionHandler h = ueh;
-        ForkJoinWorkerThread w = factory.newThread(this);
-        if (w != null) {
-            w.poolIndex = index;
-            w.setDaemon(true);
-            w.setAsyncMode(locallyFifo);
-            w.setName("ForkJoinPool-" + poolNumber + "-worker-" + index);
-            if (h != null)
-                w.setUncaughtExceptionHandler(h);
-        }
-        return w;
-    }
-
-    /**
-     * Returns a good size for worker array given pool size.
-     * Currently requires size to be a power of two.
-     */
-    private static int arraySizeFor(int poolSize) {
-        if (poolSize <= 1)
-            return 1;
-        // See Hackers Delight, sec 3.2
-        int c = poolSize >= MAX_THREADS ? MAX_THREADS : (poolSize - 1);
-        c |= c >>>  1;
-        c |= c >>>  2;
-        c |= c >>>  4;
-        c |= c >>>  8;
-        c |= c >>> 16;
-        return c + 1;
-    }
-
-    /**
-     * Creates or resizes array if necessary to hold newLength.
-     * Call only under exclusion.
-     *
-     * @return the array
-     */
-    private ForkJoinWorkerThread[] ensureWorkerArrayCapacity(int newLength) {
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws == null)
-            return workers = new ForkJoinWorkerThread[arraySizeFor(newLength)];
-        else if (newLength > ws.length)
-            return workers = Arrays.copyOf(ws, arraySizeFor(newLength));
-        else
-            return ws;
-    }
-
-    /**
-     * Tries to shrink workers into smaller array after one or more terminate.
-     */
-    private void tryShrinkWorkerArray() {
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws != null) {
-            int len = ws.length;
-            int last = len - 1;
-            while (last >= 0 && ws[last] == null)
-                --last;
-            int newLength = arraySizeFor(last+1);
-            if (newLength < len)
-                workers = Arrays.copyOf(ws, newLength);
-        }
-    }
-
-    /**
-     * Initializes workers if necessary.
-     */
-    final void ensureWorkerInitialization() {
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws == null) {
-            final ReentrantLock lock = this.workerLock;
-            lock.lock();
-            try {
-                ws = workers;
-                if (ws == null) {
-                    int ps = parallelism;
-                    ws = ensureWorkerArrayCapacity(ps);
-                    for (int i = 0; i < ps; ++i) {
-                        ForkJoinWorkerThread w = createWorker(i);
-                        if (w != null) {
-                            ws[i] = w;
-                            w.start();
-                            updateWorkerCount(1);
-                        }
-                    }
-                }
-            } finally {
-                lock.unlock();
-            }
-        }
-    }
-
-    /**
-     * Worker creation and startup for threads added via setParallelism.
-     */
-    private void createAndStartAddedWorkers() {
-        resumeAllSpares();  // Allow spares to convert to nonspare
-        int ps = parallelism;
-        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(ps);
-        int len = ws.length;
-        // Sweep through slots, to keep lowest indices most populated
-        int k = 0;
-        while (k < len) {
-            if (ws[k] != null) {
-                ++k;
-                continue;
-            }
-            int s = workerCounts;
-            int tc = totalCountOf(s);
-            int rc = runningCountOf(s);
-            if (rc >= ps || tc >= ps)
-                break;
-            if (casWorkerCounts (s, workerCountsFor(tc+1, rc+1))) {
-                ForkJoinWorkerThread w = createWorker(k);
-                if (w != null) {
-                    ws[k++] = w;
-                    w.start();
-                }
-                else {
-                    updateWorkerCount(-1); // back out on failed creation
-                    break;
-                }
-            }
-        }
+    private static int initialArraySizeFor(int pc) {
+        // If possible, initially allocate enough space for one spare
+        int size = pc < MAX_WORKERS ? pc + 1 : MAX_WORKERS;
+        // See Hackers Delight, sec 3.2. We know MAX_WORKERS < (1 >>> 16)
+        size |= size >>> 1;
+        size |= size >>> 2;
+        size |= size >>> 4;
+        size |= size >>> 8;
+        return size + 1;
     }
 
     // Execution methods
@@ -611,12 +1321,12 @@
     private <T> void doSubmit(ForkJoinTask<T> task) {
         if (task == null)
             throw new NullPointerException();
-        if (isShutdown())
+        if (runState >= SHUTDOWN)
             throw new RejectedExecutionException();
-        if (workers == null)
-            ensureWorkerInitialization();
         submissionQueue.offer(task);
-        signalIdleWorkers();
+        int c; // try to increment event count -- CAS failure OK
+        UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
+        helpMaintainParallelism(); // create, start, or resume some workers
     }
 
     /**
@@ -662,6 +1372,20 @@
     }
 
     /**
+     * Submits a ForkJoinTask for execution.
+     *
+     * @param task the task to submit
+     * @return the task
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
+        doSubmit(task);
+        return task;
+    }
+
+    /**
      * @throws NullPointerException if the task is null
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
@@ -699,21 +1423,6 @@
     }
 
     /**
-     * Submits a ForkJoinTask for execution.
-     *
-     * @param task the task to submit
-     * @return the task
-     * @throws NullPointerException if the task is null
-     * @throws RejectedExecutionException if the task cannot be
-     *         scheduled for execution
-     */
-    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
-        doSubmit(task);
-        return task;
-    }
-
-
-    /**
      * @throws NullPointerException       {@inheritDoc}
      * @throws RejectedExecutionException {@inheritDoc}
      */
@@ -725,7 +1434,7 @@
         invoke(new InvokeAll<T>(forkJoinTasks));
 
         @SuppressWarnings({"unchecked", "rawtypes"})
-        List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
+            List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
         return futures;
     }
 
@@ -739,8 +1448,6 @@
         private static final long serialVersionUID = -7914297376763021607L;
     }
 
-    // Configuration and status settings and queries
-
     /**
      * Returns the factory used for constructing new workers.
      *
@@ -757,84 +1464,7 @@
      * @return the handler, or {@code null} if none
      */
     public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
-        Thread.UncaughtExceptionHandler h;
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            h = ueh;
-        } finally {
-            lock.unlock();
-        }
-        return h;
-    }
-
-    /**
-     * Sets the handler for internal worker threads that terminate due
-     * to unrecoverable errors encountered while executing tasks.
-     * Unless set, the current default or ThreadGroup handler is used
-     * as handler.
-     *
-     * @param h the new handler
-     * @return the old handler, or {@code null} if none
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
-     */
-    public Thread.UncaughtExceptionHandler
-        setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler h) {
-        checkPermission();
-        Thread.UncaughtExceptionHandler old = null;
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            old = ueh;
-            ueh = h;
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                for (int i = 0; i < ws.length; ++i) {
-                    ForkJoinWorkerThread w = ws[i];
-                    if (w != null)
-                        w.setUncaughtExceptionHandler(h);
-                }
-            }
-        } finally {
-            lock.unlock();
-        }
-        return old;
-    }
-
-
-    /**
-     * Sets the target parallelism level of this pool.
-     *
-     * @param parallelism the target parallelism
-     * @throws IllegalArgumentException if parallelism less than or
-     * equal to zero or greater than maximum size bounds
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
-     */
-    public void setParallelism(int parallelism) {
-        checkPermission();
-        if (parallelism <= 0 || parallelism > maxPoolSize)
-            throw new IllegalArgumentException();
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            if (isProcessingTasks()) {
-                int p = this.parallelism;
-                this.parallelism = parallelism;
-                if (parallelism > p)
-                    createAndStartAddedWorkers();
-                else
-                    trimSpares();
-            }
-        } finally {
-            lock.unlock();
-        }
-        signalIdleWorkers();
+        return ueh;
     }
 
     /**
@@ -848,92 +1478,14 @@
 
     /**
      * Returns the number of worker threads that have started but not
-     * yet terminated.  This result returned by this method may differ
+     * yet terminated.  The result returned by this method may differ
      * from {@link #getParallelism} when threads are created to
      * maintain parallelism when others are cooperatively blocked.
      *
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return totalCountOf(workerCounts);
-    }
-
-    /**
-     * Returns the maximum number of threads allowed to exist in the
-     * pool. Unless set using {@link #setMaximumPoolSize}, the
-     * maximum is an implementation-defined value designed only to
-     * prevent runaway growth.
-     *
-     * @return the maximum
-     */
-    public int getMaximumPoolSize() {
-        return maxPoolSize;
-    }
-
-    /**
-     * Sets the maximum number of threads allowed to exist in the
-     * pool. The given value should normally be greater than or equal
-     * to the {@link #getParallelism parallelism} level. Setting this
-     * value has no effect on current pool size. It controls
-     * construction of new threads.
-     *
-     * @throws IllegalArgumentException if negative or greater than
-     * internal implementation limit
-     */
-    public void setMaximumPoolSize(int newMax) {
-        if (newMax < 0 || newMax > MAX_THREADS)
-            throw new IllegalArgumentException();
-        maxPoolSize = newMax;
-    }
-
-
-    /**
-     * Returns {@code true} if this pool dynamically maintains its
-     * target parallelism level. If false, new threads are added only
-     * to avoid possible starvation.  This setting is by default true.
-     *
-     * @return {@code true} if maintains parallelism
-     */
-    public boolean getMaintainsParallelism() {
-        return maintainsParallelism;
-    }
-
-    /**
-     * Sets whether this pool dynamically maintains its target
-     * parallelism level. If false, new threads are added only to
-     * avoid possible starvation.
-     *
-     * @param enable {@code true} to maintain parallelism
-     */
-    public void setMaintainsParallelism(boolean enable) {
-        maintainsParallelism = enable;
-    }
-
-    /**
-     * Establishes local first-in-first-out scheduling mode for forked
-     * tasks that are never joined. This mode may be more appropriate
-     * than default locally stack-based mode in applications in which
-     * worker threads only process asynchronous tasks.  This method is
-     * designed to be invoked only when the pool is quiescent, and
-     * typically only before any tasks are submitted. The effects of
-     * invocations at other times may be unpredictable.
-     *
-     * @param async if {@code true}, use locally FIFO scheduling
-     * @return the previous mode
-     * @see #getAsyncMode
-     */
-    public boolean setAsyncMode(boolean async) {
-        boolean oldMode = locallyFifo;
-        locallyFifo = async;
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws != null) {
-            for (int i = 0; i < ws.length; ++i) {
-                ForkJoinWorkerThread t = ws[i];
-                if (t != null)
-                    t.setAsyncMode(async);
-            }
-        }
-        return oldMode;
+        return workerCounts >>> TOTAL_COUNT_SHIFT;
     }
 
     /**
@@ -941,7 +1493,6 @@
      * scheduling mode for forked tasks that are never joined.
      *
      * @return {@code true} if this pool uses async mode
-     * @see #setAsyncMode
      */
     public boolean getAsyncMode() {
         return locallyFifo;
@@ -950,12 +1501,13 @@
     /**
      * Returns an estimate of the number of worker threads that are
      * not blocked waiting to join tasks or for other managed
-     * synchronization.
+     * synchronization. This method may overestimate the
+     * number of running threads.
      *
      * @return the number of worker threads
      */
     public int getRunningThreadCount() {
-        return runningCountOf(workerCounts);
+        return workerCounts & RUNNING_COUNT_MASK;
     }
 
     /**
@@ -966,19 +1518,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        return activeCountOf(runControl);
-    }
-
-    /**
-     * Returns an estimate of the number of threads that are currently
-     * idle waiting for tasks. This method may underestimate the
-     * number of idle threads.
-     *
-     * @return the number of idle threads
-     */
-    final int getIdleThreadCount() {
-        int c = runningCountOf(workerCounts) - activeCountOf(runControl);
-        return (c <= 0) ? 0 : c;
+        return runState & ACTIVE_COUNT_MASK;
     }
 
     /**
@@ -993,7 +1533,7 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return activeCountOf(runControl) == 0;
+        return (runState & ACTIVE_COUNT_MASK) == 0;
     }
 
     /**
@@ -1008,17 +1548,7 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        return stealCount.get();
-    }
-
-    /**
-     * Accumulates steal count from a worker.
-     * Call only when worker known to be idle.
-     */
-    private void updateStealCount(ForkJoinWorkerThread w) {
-        int sc = w.getAndClearStealCount();
-        if (sc != 0)
-            stealCount.addAndGet(sc);
+        return stealCount;
     }
 
     /**
@@ -1033,14 +1563,9 @@
      */
     public long getQueuedTaskCount() {
         long count = 0;
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws != null) {
-            for (int i = 0; i < ws.length; ++i) {
-                ForkJoinWorkerThread t = ws[i];
-                if (t != null)
-                    count += t.getQueueSize();
-            }
-        }
+        for (ForkJoinWorkerThread w : workers)
+            if (w != null)
+                count += w.getQueueSize();
         return count;
     }
 
@@ -1094,16 +1619,11 @@
      * @return the number of elements transferred
      */
     protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
-        int n = submissionQueue.drainTo(c);
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws != null) {
-            for (int i = 0; i < ws.length; ++i) {
-                ForkJoinWorkerThread w = ws[i];
-                if (w != null)
-                    n += w.drainTasksTo(c);
-            }
-        }
-        return n;
+        int count = submissionQueue.drainTo(c);
+        for (ForkJoinWorkerThread w : workers)
+            if (w != null)
+                count += w.drainTasksTo(c);
+        return count;
     }
 
     /**
@@ -1114,36 +1634,34 @@
      * @return a string identifying this pool, as well as its state
      */
     public String toString() {
-        int ps = parallelism;
-        int wc = workerCounts;
-        int rc = runControl;
         long st = getStealCount();
         long qt = getQueuedTaskCount();
         long qs = getQueuedSubmissionCount();
+        int wc = workerCounts;
+        int tc = wc >>> TOTAL_COUNT_SHIFT;
+        int rc = wc & RUNNING_COUNT_MASK;
+        int pc = parallelism;
+        int rs = runState;
+        int ac = rs & ACTIVE_COUNT_MASK;
         return super.toString() +
-            "[" + runStateToString(runStateOf(rc)) +
-            ", parallelism = " + ps +
-            ", size = " + totalCountOf(wc) +
-            ", active = " + activeCountOf(rc) +
-            ", running = " + runningCountOf(wc) +
+            "[" + runLevelToString(rs) +
+            ", parallelism = " + pc +
+            ", size = " + tc +
+            ", active = " + ac +
+            ", running = " + rc +
             ", steals = " + st +
             ", tasks = " + qt +
             ", submissions = " + qs +
             "]";
     }
 
-    private static String runStateToString(int rs) {
-        switch(rs) {
-        case RUNNING: return "Running";
-        case SHUTDOWN: return "Shutting down";
-        case TERMINATING: return "Terminating";
-        case TERMINATED: return "Terminated";
-        default: throw new Error("Unknown run state");
-        }
+    private static String runLevelToString(int s) {
+        return ((s & TERMINATED) != 0 ? "Terminated" :
+                ((s & TERMINATING) != 0 ? "Terminating" :
+                 ((s & SHUTDOWN) != 0 ? "Shutting down" :
+                  "Running")));
     }
 
-    // lifecycle control
-
     /**
      * Initiates an orderly shutdown in which previously submitted
      * tasks are executed, but no new tasks will be accepted.
@@ -1158,23 +1676,8 @@
      */
     public void shutdown() {
         checkPermission();
-        transitionRunStateTo(SHUTDOWN);
-        if (canTerminateOnShutdown(runControl)) {
-            if (workers == null) { // shutting down before workers created
-                final ReentrantLock lock = this.workerLock;
-                lock.lock();
-                try {
-                    if (workers == null) {
-                        terminate();
-                        transitionRunStateTo(TERMINATED);
-                        termination.signalAll();
-                    }
-                } finally {
-                    lock.unlock();
-                }
-            }
-            terminateOnShutdown();
-        }
+        advanceRunLevel(SHUTDOWN);
+        tryTerminate(false);
     }
 
     /**
@@ -1195,7 +1698,7 @@
      */
     public List<Runnable> shutdownNow() {
         checkPermission();
-        terminate();
+        tryTerminate(true);
         return Collections.emptyList();
     }
 
@@ -1205,7 +1708,7 @@
      * @return {@code true} if all tasks have completed following shut down
      */
     public boolean isTerminated() {
-        return runStateOf(runControl) == TERMINATED;
+        return runState >= TERMINATED;
     }
 
     /**
@@ -1219,7 +1722,7 @@
      * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        return runStateOf(runControl) == TERMINATING;
+        return (runState & (TERMINATING|TERMINATED)) == TERMINATING;
     }
 
     /**
@@ -1228,15 +1731,7 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return runStateOf(runControl) >= SHUTDOWN;
-    }
-
-    /**
-     * Returns true if pool is not terminating or terminated.
-     * Used internally to suppress execution when terminating.
-     */
-    final boolean isProcessingTasks() {
-        return runStateOf(runControl) < TERMINATING;
+        return runState >= SHUTDOWN;
     }
 
     /**
@@ -1252,585 +1747,10 @@
      */
     public boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException {
-        long nanos = unit.toNanos(timeout);
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
         try {
-            for (;;) {
-                if (isTerminated())
-                    return true;
-                if (nanos <= 0)
-                    return false;
-                nanos = termination.awaitNanos(nanos);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    // Shutdown and termination support
-
-    /**
-     * Callback from terminating worker. Nulls out the corresponding
-     * workers slot, and if terminating, tries to terminate; else
-     * tries to shrink workers array.
-     *
-     * @param w the worker
-     */
-    final void workerTerminated(ForkJoinWorkerThread w) {
-        updateStealCount(w);
-        updateWorkerCount(-1);
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                int idx = w.poolIndex;
-                if (idx >= 0 && idx < ws.length && ws[idx] == w)
-                    ws[idx] = null;
-                if (totalCountOf(workerCounts) == 0) {
-                    terminate(); // no-op if already terminating
-                    transitionRunStateTo(TERMINATED);
-                    termination.signalAll();
-                }
-                else if (isProcessingTasks()) {
-                    tryShrinkWorkerArray();
-                    tryResumeSpare(true); // allow replacement
-                }
-            }
-        } finally {
-            lock.unlock();
-        }
-        signalIdleWorkers();
-    }
-
-    /**
-     * Initiates termination.
-     */
-    private void terminate() {
-        if (transitionRunStateTo(TERMINATING)) {
-            stopAllWorkers();
-            resumeAllSpares();
-            signalIdleWorkers();
-            cancelQueuedSubmissions();
-            cancelQueuedWorkerTasks();
-            interruptUnterminatedWorkers();
-            signalIdleWorkers(); // resignal after interrupt
-        }
-    }
-
-    /**
-     * Possibly terminates when on shutdown state.
-     */
-    private void terminateOnShutdown() {
-        if (!hasQueuedSubmissions() && canTerminateOnShutdown(runControl))
-            terminate();
-    }
-
-    /**
-     * Clears out and cancels submissions.
-     */
-    private void cancelQueuedSubmissions() {
-        ForkJoinTask<?> task;
-        while ((task = pollSubmission()) != null)
-            task.cancel(false);
-    }
-
-    /**
-     * Cleans out worker queues.
-     */
-    private void cancelQueuedWorkerTasks() {
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                for (int i = 0; i < ws.length; ++i) {
-                    ForkJoinWorkerThread t = ws[i];
-                    if (t != null)
-                        t.cancelTasks();
-                }
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Sets each worker's status to terminating. Requires lock to avoid
-     * conflicts with add/remove.
-     */
-    private void stopAllWorkers() {
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                for (int i = 0; i < ws.length; ++i) {
-                    ForkJoinWorkerThread t = ws[i];
-                    if (t != null)
-                        t.shutdownNow();
-                }
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Interrupts all unterminated workers.  This is not required for
-     * sake of internal control, but may help unstick user code during
-     * shutdown.
-     */
-    private void interruptUnterminatedWorkers() {
-        final ReentrantLock lock = this.workerLock;
-        lock.lock();
-        try {
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                for (int i = 0; i < ws.length; ++i) {
-                    ForkJoinWorkerThread t = ws[i];
-                    if (t != null && !t.isTerminated()) {
-                        try {
-                            t.interrupt();
-                        } catch (SecurityException ignore) {
-                        }
-                    }
-                }
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-
-    /*
-     * Nodes for event barrier to manage idle threads.  Queue nodes
-     * are basic Treiber stack nodes, also used for spare stack.
-     *
-     * The event barrier has an event count and a wait queue (actually
-     * a Treiber stack).  Workers are enabled to look for work when
-     * the eventCount is incremented. If they fail to find work, they
-     * may wait for next count. Upon release, threads help others wake
-     * up.
-     *
-     * Synchronization events occur only in enough contexts to
-     * maintain overall liveness:
-     *
-     *   - Submission of a new task to the pool
-     *   - Resizes or other changes to the workers array
-     *   - pool termination
-     *   - A worker pushing a task on an empty queue
-     *
-     * The case of pushing a task occurs often enough, and is heavy
-     * enough compared to simple stack pushes, to require special
-     * handling: Method signalWork returns without advancing count if
-     * the queue appears to be empty.  This would ordinarily result in
-     * races causing some queued waiters not to be woken up. To avoid
-     * this, the first worker enqueued in method sync (see
-     * syncIsReleasable) rescans for tasks after being enqueued, and
-     * helps signal if any are found. This works well because the
-     * worker has nothing better to do, and so might as well help
-     * alleviate the overhead and contention on the threads actually
-     * doing work.  Also, since event counts increments on task
-     * availability exist to maintain liveness (rather than to force
-     * refreshes etc), it is OK for callers to exit early if
-     * contending with another signaller.
-     */
-    static final class WaitQueueNode {
-        WaitQueueNode next; // only written before enqueued
-        volatile ForkJoinWorkerThread thread; // nulled to cancel wait
-        final long count; // unused for spare stack
-
-        WaitQueueNode(long c, ForkJoinWorkerThread w) {
-            count = c;
-            thread = w;
-        }
-
-        /**
-         * Wakes up waiter, returning false if known to already
-         */
-        boolean signal() {
-            ForkJoinWorkerThread t = thread;
-            if (t == null)
-                return false;
-            thread = null;
-            LockSupport.unpark(t);
-            return true;
-        }
-
-        /**
-         * Awaits release on sync.
-         */
-        void awaitSyncRelease(ForkJoinPool p) {
-            while (thread != null && !p.syncIsReleasable(this))
-                LockSupport.park(this);
-        }
-
-        /**
-         * Awaits resumption as spare.
-         */
-        void awaitSpareRelease() {
-            while (thread != null) {
-                if (!Thread.interrupted())
-                    LockSupport.park(this);
-            }
-        }
-    }
-
-    /**
-     * Ensures that no thread is waiting for count to advance from the
-     * current value of eventCount read on entry to this method, by
-     * releasing waiting threads if necessary.
-     *
-     * @return the count
-     */
-    final long ensureSync() {
-        long c = eventCount;
-        WaitQueueNode q;
-        while ((q = syncStack) != null && q.count < c) {
-            if (casBarrierStack(q, null)) {
-                do {
-                    q.signal();
-                } while ((q = q.next) != null);
-                break;
-            }
-        }
-        return c;
-    }
-
-    /**
-     * Increments event count and releases waiting threads.
-     */
-    private void signalIdleWorkers() {
-        long c;
-        do {} while (!casEventCount(c = eventCount, c+1));
-        ensureSync();
-    }
-
-    /**
-     * Signals threads waiting to poll a task. Because method sync
-     * rechecks availability, it is OK to only proceed if queue
-     * appears to be non-empty, and OK to skip under contention to
-     * increment count (since some other thread succeeded).
-     */
-    final void signalWork() {
-        long c;
-        WaitQueueNode q;
-        if (syncStack != null &&
-            casEventCount(c = eventCount, c+1) &&
-            (((q = syncStack) != null && q.count <= c) &&
-             (!casBarrierStack(q, q.next) || !q.signal())))
-            ensureSync();
-    }
-
-    /**
-     * Waits until event count advances from last value held by
-     * caller, or if excess threads, caller is resumed as spare, or
-     * caller or pool is terminating. Updates caller's event on exit.
-     *
-     * @param w the calling worker thread
-     */
-    final void sync(ForkJoinWorkerThread w) {
-        updateStealCount(w); // Transfer w's count while it is idle
-
-        while (!w.isShutdown() && isProcessingTasks() && !suspendIfSpare(w)) {
-            long prev = w.lastEventCount;
-            WaitQueueNode node = null;
-            WaitQueueNode h;
-            while (eventCount == prev &&
-                   ((h = syncStack) == null || h.count == prev)) {
-                if (node == null)
-                    node = new WaitQueueNode(prev, w);
-                if (casBarrierStack(node.next = h, node)) {
-                    node.awaitSyncRelease(this);
-                    break;
-                }
-            }
-            long ec = ensureSync();
-            if (ec != prev) {
-                w.lastEventCount = ec;
-                break;
-            }
-        }
-    }
-
-    /**
-     * Returns {@code true} if worker waiting on sync can proceed:
-     *  - on signal (thread == null)
-     *  - on event count advance (winning race to notify vs signaller)
-     *  - on interrupt
-     *  - if the first queued node, we find work available
-     * If node was not signalled and event count not advanced on exit,
-     * then we also help advance event count.
-     *
-     * @return {@code true} if node can be released
-     */
-    final boolean syncIsReleasable(WaitQueueNode node) {
-        long prev = node.count;
-        if (!Thread.interrupted() && node.thread != null &&
-            (node.next != null ||
-             !ForkJoinWorkerThread.hasQueuedTasks(workers)) &&
-            eventCount == prev)
+            return termination.awaitAdvanceInterruptibly(0, timeout, unit) > 0;
+        } catch (TimeoutException ex) {
             return false;
-        if (node.thread != null) {
-            node.thread = null;
-            long ec = eventCount;
-            if (prev <= ec) // help signal
-                casEventCount(ec, ec+1);
-        }
-        return true;
-    }
-
-    /**
-     * Returns {@code true} if a new sync event occurred since last
-     * call to sync or this method, if so, updating caller's count.
-     */
-    final boolean hasNewSyncEvent(ForkJoinWorkerThread w) {
-        long lc = w.lastEventCount;
-        long ec = ensureSync();
-        if (ec == lc)
-            return false;
-        w.lastEventCount = ec;
-        return true;
-    }
-
-    //  Parallelism maintenance
-
-    /**
-     * Decrements running count; if too low, adds spare.
-     *
-     * Conceptually, all we need to do here is add or resume a
-     * spare thread when one is about to block (and remove or
-     * suspend it later when unblocked -- see suspendIfSpare).
-     * However, implementing this idea requires coping with
-     * several problems: we have imperfect information about the
-     * states of threads. Some count updates can and usually do
-     * lag run state changes, despite arrangements to keep them
-     * accurate (for example, when possible, updating counts
-     * before signalling or resuming), especially when running on
-     * dynamic JVMs that don't optimize the infrequent paths that
-     * update counts. Generating too many threads can make these
-     * problems become worse, because excess threads are more
-     * likely to be context-switched with others, slowing them all
-     * down, especially if there is no work available, so all are
-     * busy scanning or idling.  Also, excess spare threads can
-     * only be suspended or removed when they are idle, not
-     * immediately when they aren't needed. So adding threads will
-     * raise parallelism level for longer than necessary.  Also,
-     * FJ applications often encounter highly transient peaks when
-     * many threads are blocked joining, but for less time than it
-     * takes to create or resume spares.
-     *
-     * @param joinMe if non-null, return early if done
-     * @param maintainParallelism if true, try to stay within
-     * target counts, else create only to avoid starvation
-     * @return true if joinMe known to be done
-     */
-    final boolean preJoin(ForkJoinTask<?> joinMe,
-                          boolean maintainParallelism) {
-        maintainParallelism &= maintainsParallelism; // overrride
-        boolean dec = false;  // true when running count decremented
-        while (spareStack == null || !tryResumeSpare(dec)) {
-            int counts = workerCounts;
-            if (dec || (dec = casWorkerCounts(counts, --counts))) {
-                if (!needSpare(counts, maintainParallelism))
-                    break;
-                if (joinMe.status < 0)
-                    return true;
-                if (tryAddSpare(counts))
-                    break;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Same idea as preJoin
-     */
-    final boolean preBlock(ManagedBlocker blocker,
-                           boolean maintainParallelism) {
-        maintainParallelism &= maintainsParallelism;
-        boolean dec = false;
-        while (spareStack == null || !tryResumeSpare(dec)) {
-            int counts = workerCounts;
-            if (dec || (dec = casWorkerCounts(counts, --counts))) {
-                if (!needSpare(counts, maintainParallelism))
-                    break;
-                if (blocker.isReleasable())
-                    return true;
-                if (tryAddSpare(counts))
-                    break;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns {@code true} if a spare thread appears to be needed.
-     * If maintaining parallelism, returns true when the deficit in
-     * running threads is more than the surplus of total threads, and
-     * there is apparently some work to do.  This self-limiting rule
-     * means that the more threads that have already been added, the
-     * less parallelism we will tolerate before adding another.
-     *
-     * @param counts current worker counts
-     * @param maintainParallelism try to maintain parallelism
-     */
-    private boolean needSpare(int counts, boolean maintainParallelism) {
-        int ps = parallelism;
-        int rc = runningCountOf(counts);
-        int tc = totalCountOf(counts);
-        int runningDeficit = ps - rc;
-        int totalSurplus = tc - ps;
-        return (tc < maxPoolSize &&
-                (rc == 0 || totalSurplus < 0 ||
-                 (maintainParallelism &&
-                  runningDeficit > totalSurplus &&
-                  ForkJoinWorkerThread.hasQueuedTasks(workers))));
-    }
-
-    /**
-     * Adds a spare worker if lock available and no more than the
-     * expected numbers of threads exist.
-     *
-     * @return true if successful
-     */
-    private boolean tryAddSpare(int expectedCounts) {
-        final ReentrantLock lock = this.workerLock;
-        int expectedRunning = runningCountOf(expectedCounts);
-        int expectedTotal = totalCountOf(expectedCounts);
-        boolean success = false;
-        boolean locked = false;
-        // confirm counts while locking; CAS after obtaining lock
-        try {
-            for (;;) {
-                int s = workerCounts;
-                int tc = totalCountOf(s);
-                int rc = runningCountOf(s);
-                if (rc > expectedRunning || tc > expectedTotal)
-                    break;
-                if (!locked && !(locked = lock.tryLock()))
-                    break;
-                if (casWorkerCounts(s, workerCountsFor(tc+1, rc+1))) {
-                    createAndStartSpare(tc);
-                    success = true;
-                    break;
-                }
-            }
-        } finally {
-            if (locked)
-                lock.unlock();
-        }
-        return success;
-    }
-
-    /**
-     * Adds the kth spare worker. On entry, pool counts are already
-     * adjusted to reflect addition.
-     */
-    private void createAndStartSpare(int k) {
-        ForkJoinWorkerThread w = null;
-        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(k + 1);
-        int len = ws.length;
-        // Probably, we can place at slot k. If not, find empty slot
-        if (k < len && ws[k] != null) {
-            for (k = 0; k < len && ws[k] != null; ++k)
-                ;
-        }
-        if (k < len && isProcessingTasks() && (w = createWorker(k)) != null) {
-            ws[k] = w;
-            w.start();
-        }
-        else
-            updateWorkerCount(-1); // adjust on failure
-        signalIdleWorkers();
-    }
-
-    /**
-     * Suspends calling thread w if there are excess threads.  Called
-     * only from sync.  Spares are enqueued in a Treiber stack using
-     * the same WaitQueueNodes as barriers.  They are resumed mainly
-     * in preJoin, but are also woken on pool events that require all
-     * threads to check run state.
-     *
-     * @param w the caller
-     */
-    private boolean suspendIfSpare(ForkJoinWorkerThread w) {
-        WaitQueueNode node = null;
-        int s;
-        while (parallelism < runningCountOf(s = workerCounts)) {
-            if (node == null)
-                node = new WaitQueueNode(0, w);
-            if (casWorkerCounts(s, s-1)) { // representation-dependent
-                // push onto stack
-                do {} while (!casSpareStack(node.next = spareStack, node));
-                // block until released by resumeSpare
-                node.awaitSpareRelease();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Tries to pop and resume a spare thread.
-     *
-     * @param updateCount if true, increment running count on success
-     * @return true if successful
-     */
-    private boolean tryResumeSpare(boolean updateCount) {
-        WaitQueueNode q;
-        while ((q = spareStack) != null) {
-            if (casSpareStack(q, q.next)) {
-                if (updateCount)
-                    updateRunningCount(1);
-                q.signal();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Pops and resumes all spare threads. Same idea as ensureSync.
-     *
-     * @return true if any spares released
-     */
-    private boolean resumeAllSpares() {
-        WaitQueueNode q;
-        while ( (q = spareStack) != null) {
-            if (casSpareStack(q, null)) {
-                do {
-                    updateRunningCount(1);
-                    q.signal();
-                } while ((q = q.next) != null);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Pops and shuts down excessive spare threads. Call only while
-     * holding lock. This is not guaranteed to eliminate all excess
-     * threads, only those suspended as spares, which are the ones
-     * unlikely to be needed in the future.
-     */
-    private void trimSpares() {
-        int surplus = totalCountOf(workerCounts) - parallelism;
-        WaitQueueNode q;
-        while (surplus > 0 && (q = spareStack) != null) {
-            if (casSpareStack(q, null)) {
-                do {
-                    updateRunningCount(1);
-                    ForkJoinWorkerThread w = q.thread;
-                    if (w != null && surplus > 0 &&
-                        runningCountOf(workerCounts) > 0 && w.shutdown())
-                        --surplus;
-                    q.signal();
-                } while ((q = q.next) != null);
-            }
         }
     }
 
@@ -1838,11 +1758,17 @@
      * Interface for extending managed parallelism for tasks running
      * in {@link ForkJoinPool}s.
      *
-     * <p>A {@code ManagedBlocker} provides two methods.
-     * Method {@code isReleasable} must return {@code true} if
-     * blocking is not necessary. Method {@code block} blocks the
-     * current thread if necessary (perhaps internally invoking
-     * {@code isReleasable} before actually blocking).
+     * <p>A {@code ManagedBlocker} provides two methods.  Method
+     * {@code isReleasable} must return {@code true} if blocking is
+     * not necessary. Method {@code block} blocks the current thread
+     * if necessary (perhaps internally invoking {@code isReleasable}
+     * before actually blocking). The unusual methods in this API
+     * accommodate synchronizers that may, but don't usually, block
+     * for long periods. Similarly, they allow more efficient internal
+     * handling of cases in which additional workers may be, but
+     * usually are not, needed to ensure sufficient parallelism.
+     * Toward this end, implementations of method {@code isReleasable}
+     * must be amenable to repeated invocation.
      *
      * <p>For example, here is a ManagedBlocker based on a
      * ReentrantLock:
@@ -1860,6 +1786,26 @@
      *     return hasLock || (hasLock = lock.tryLock());
      *   }
      * }}</pre>
+     *
+     * <p>Here is a class that possibly blocks waiting for an
+     * item on a given queue:
+     *  <pre> {@code
+     * class QueueTaker<E> implements ManagedBlocker {
+     *   final BlockingQueue<E> queue;
+     *   volatile E item = null;
+     *   QueueTaker(BlockingQueue<E> q) { this.queue = q; }
+     *   public boolean block() throws InterruptedException {
+     *     if (item == null)
+     *       item = queue.take();
+     *     return true;
+     *   }
+     *   public boolean isReleasable() {
+     *     return item != null || (item = queue.poll()) != null;
+     *   }
+     *   public E getItem() { // call after pool.managedBlock completes
+     *     return item;
+     *   }
+     * }}</pre>
      */
     public static interface ManagedBlocker {
         /**
@@ -1883,14 +1829,7 @@
      * Blocks in accord with the given blocker.  If the current thread
      * is a {@link ForkJoinWorkerThread}, this method possibly
      * arranges for a spare thread to be activated if necessary to
-     * ensure parallelism while the current thread is blocked.
-     *
-     * <p>If {@code maintainParallelism} is {@code true} and the pool
-     * supports it ({@link #getMaintainsParallelism}), this method
-     * attempts to maintain the pool's nominal parallelism. Otherwise
-     * it activates a thread only if necessary to avoid complete
-     * starvation. This option may be preferable when blockages use
-     * timeouts, or are almost always brief.
+     * ensure sufficient parallelism while the current thread is blocked.
      *
      * <p>If the caller is not a {@link ForkJoinTask}, this method is
      * behaviorally equivalent to
@@ -1904,33 +1843,18 @@
      * first be expanded to ensure parallelism, and later adjusted.
      *
      * @param blocker the blocker
-     * @param maintainParallelism if {@code true} and supported by
-     * this pool, attempt to maintain the pool's nominal parallelism;
-     * otherwise activate a thread only if necessary to avoid
-     * complete starvation.
      * @throws InterruptedException if blocker.block did so
      */
-    public static void managedBlock(ManagedBlocker blocker,
-                                    boolean maintainParallelism)
+    public static void managedBlock(ManagedBlocker blocker)
         throws InterruptedException {
         Thread t = Thread.currentThread();
-        ForkJoinPool pool = ((t instanceof ForkJoinWorkerThread) ?
-                             ((ForkJoinWorkerThread) t).pool : null);
-        if (!blocker.isReleasable()) {
-            try {
-                if (pool == null ||
-                    !pool.preBlock(blocker, maintainParallelism))
-                    awaitBlocker(blocker);
-            } finally {
-                if (pool != null)
-                    pool.updateRunningCount(1);
-            }
+        if (t instanceof ForkJoinWorkerThread) {
+            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
+            w.pool.awaitBlocker(blocker);
         }
-    }
-
-    private static void awaitBlocker(ManagedBlocker blocker)
-        throws InterruptedException {
-        do {} while (!blocker.isReleasable() && !blocker.block());
+        else {
+            do {} while (!blocker.isReleasable() && !blocker.block());
+        }
     }
 
     // AbstractExecutorService overrides.  These rely on undocumented
@@ -1948,32 +1872,18 @@
     // Unsafe mechanics
 
     private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long workerCountsOffset =
+        objectFieldOffset("workerCounts", ForkJoinPool.class);
+    private static final long runStateOffset =
+        objectFieldOffset("runState", ForkJoinPool.class);
     private static final long eventCountOffset =
         objectFieldOffset("eventCount", ForkJoinPool.class);
-    private static final long workerCountsOffset =
-        objectFieldOffset("workerCounts", ForkJoinPool.class);
-    private static final long runControlOffset =
-        objectFieldOffset("runControl", ForkJoinPool.class);
-    private static final long syncStackOffset =
-        objectFieldOffset("syncStack",ForkJoinPool.class);
-    private static final long spareStackOffset =
-        objectFieldOffset("spareStack", ForkJoinPool.class);
-
-    private boolean casEventCount(long cmp, long val) {
-        return UNSAFE.compareAndSwapLong(this, eventCountOffset, cmp, val);
-    }
-    private boolean casWorkerCounts(int cmp, int val) {
-        return UNSAFE.compareAndSwapInt(this, workerCountsOffset, cmp, val);
-    }
-    private boolean casRunControl(int cmp, int val) {
-        return UNSAFE.compareAndSwapInt(this, runControlOffset, cmp, val);
-    }
-    private boolean casSpareStack(WaitQueueNode cmp, WaitQueueNode val) {
-        return UNSAFE.compareAndSwapObject(this, spareStackOffset, cmp, val);
-    }
-    private boolean casBarrierStack(WaitQueueNode cmp, WaitQueueNode val) {
-        return UNSAFE.compareAndSwapObject(this, syncStackOffset, cmp, val);
-    }
+    private static final long eventWaitersOffset =
+        objectFieldOffset("eventWaiters", ForkJoinPool.class);
+    private static final long stealCountOffset =
+        objectFieldOffset("stealCount", ForkJoinPool.class);
+    private static final long spareWaitersOffset =
+        objectFieldOffset("spareWaiters", ForkJoinPool.class);
 
     private static long objectFieldOffset(String field, Class<?> klazz) {
         try {
--- a/src/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Sep 16 11:17:32 2010 -0700
+++ b/src/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Sep 16 11:19:43 2010 -0700
@@ -91,10 +91,7 @@
  * results of a task is {@link #join}, but there are several variants:
  * The {@link Future#get} methods support interruptible and/or timed
  * waits for completion and report results using {@code Future}
- * conventions. Method {@link #helpJoin} enables callers to actively
- * execute other tasks while awaiting joins, which is sometimes more
- * efficient but only applies when all subtasks are known to be
- * strictly tree-structured. Method {@link #invoke} is semantically
+ * conventions. Method {@link #invoke} is semantically
  * equivalent to {@code fork(); join()} but always attempts to begin
  * execution in the current thread. The "<em>quiet</em>" forms of
  * these methods do not extract results or report exceptions. These
@@ -130,7 +127,7 @@
  * ForkJoinTasks (as may be determined using method {@link
  * #inForkJoinPool}).  Attempts to invoke them in other contexts
  * result in exceptions or errors, possibly including
- * ClassCastException.
+ * {@code ClassCastException}.
  *
  * <p>Most base support methods are {@code final}, to prevent
  * overriding of implementations that are intrinsically tied to the
@@ -152,9 +149,8 @@
  *
  * <p>This class provides {@code adapt} methods for {@link Runnable}
  * and {@link Callable}, that may be of use when mixing execution of
- * {@code ForkJoinTasks} with other kinds of tasks. When all tasks
- * are of this form, consider using a pool in
- * {@linkplain ForkJoinPool#setAsyncMode async mode}.
+ * {@code ForkJoinTasks} with other kinds of tasks. When all tasks are
+ * of this form, consider using a pool constructed in <em>asyncMode</em>.
  *
  * <p>ForkJoinTasks are {@code Serializable}, which enables them to be
  * used in extensions such as remote execution frameworks. It is
@@ -166,33 +162,43 @@
  */
 public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
 
-    /**
-     * Run control status bits packed into a single int to minimize
-     * footprint and to ensure atomicity (via CAS).  Status is
-     * initially zero, and takes on nonnegative values until
-     * completed, upon which status holds COMPLETED. CANCELLED, or
-     * EXCEPTIONAL, which use the top 3 bits.  Tasks undergoing
-     * blocking waits by other threads have SIGNAL_MASK bits set --
-     * bit 15 for external (nonFJ) waits, and the rest a count of
-     * waiting FJ threads.  (This representation relies on
-     * ForkJoinPool max thread limits). Completion of a stolen task
-     * with SIGNAL_MASK bits set awakens waiter via notifyAll. Even
-     * though suboptimal for some purposes, we use basic builtin
-     * wait/notify to take advantage of "monitor inflation" in JVMs
-     * that we would otherwise need to emulate to avoid adding further
-     * per-task bookkeeping overhead. Note that bits 16-28 are
-     * currently unused. Also value 0x80000000 is available as spare
-     * completion value.
+    /*
+     * See the internal documentation of class ForkJoinPool for a
+     * general implementation overview.  ForkJoinTasks are mainly
+     * responsible for maintaining their "status" field amidst relays
+     * to methods in ForkJoinWorkerThread and ForkJoinPool. The
+     * methods of this class are more-or-less layered into (1) basic
+     * status maintenance (2) execution and awaiting completion (3)
+     * user-level methods that additionally report results. This is
+     * sometimes hard to see because this file orders exported methods
+     * in a way that flows well in javadocs. In particular, most
+     * join mechanics are in method quietlyJoin, below.
      */
+
+    /*
+     * The status field holds run control status bits packed into a
+     * single int to minimize footprint and to ensure atomicity (via
+     * CAS).  Status is initially zero, and takes on nonnegative
+     * values until completed, upon which status holds value
+     * NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking
+     * waits by other threads have the SIGNAL bit set.  Completion of
+     * a stolen task with SIGNAL set awakens any waiters via
+     * notifyAll. Even though suboptimal for some purposes, we use
+     * basic builtin wait/notify to take advantage of "monitor
+     * inflation" in JVMs that we would otherwise need to emulate to
+     * avoid adding further per-task bookkeeping overhead.  We want
+     * these monitors to be "fat", i.e., not use biasing or thin-lock
+     * techniques, so use some odd coding idioms that tend to avoid
+     * them.
+     */
+
+    /** The run status of this task */
     volatile int status; // accessed directly by pool and workers
 
-    static final int COMPLETION_MASK      = 0xe0000000;
-    static final int NORMAL               = 0xe0000000; // == mask
-    static final int CANCELLED            = 0xc0000000;
-    static final int EXCEPTIONAL          = 0xa0000000;
-    static final int SIGNAL_MASK          = 0x0000ffff;
-    static final int INTERNAL_SIGNAL_MASK = 0x00007fff;
-    static final int EXTERNAL_SIGNAL      = 0x00008000; // top bit of low word
+    private static final int NORMAL      = -1;
+    private static final int CANCELLED   = -2;
+    private static final int EXCEPTIONAL = -3;
+    private static final int SIGNAL      =  1;
 
     /**
      * Table of exceptions thrown by tasks, to enable reporting by
@@ -206,176 +212,94 @@
         Collections.synchronizedMap
         (new WeakHashMap<ForkJoinTask<?>, Throwable>());
 
-    // within-package utilities
+    // Maintaining completion status
 
     /**
-     * Gets current worker thread, or null if not a worker thread.
-     */
-    static ForkJoinWorkerThread getWorker() {
-        Thread t = Thread.currentThread();
-        return ((t instanceof ForkJoinWorkerThread) ?
-                (ForkJoinWorkerThread) t : null);
-    }
-
-    final boolean casStatus(int cmp, int val) {
-        return UNSAFE.compareAndSwapInt(this, statusOffset, cmp, val);
-    }
-
-    /**
-     * Workaround for not being able to rethrow unchecked exceptions.
-     */
-    static void rethrowException(Throwable ex) {
-        if (ex != null)
-            UNSAFE.throwException(ex);
-    }
-
-    // Setting completion status
-
-    /**
-     * Marks completion and wakes up threads waiting to join this task.
+     * Marks completion and wakes up threads waiting to join this task,
+     * also clearing signal request bits.
      *
      * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
      */
-    final void setCompletion(int completion) {
-        ForkJoinPool pool = getPool();
-        if (pool != null) {
-            int s; // Clear signal bits while setting completion status
-            do {} while ((s = status) >= 0 && !casStatus(s, completion));
-
-            if ((s & SIGNAL_MASK) != 0) {
-                if ((s &= INTERNAL_SIGNAL_MASK) != 0)
-                    pool.updateRunningCount(s);
-                synchronized (this) { notifyAll(); }
+    private void setCompletion(int completion) {
+        int s;
+        while ((s = status) >= 0) {
+            if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
+                if (s != 0)
+                    synchronized (this) { notifyAll(); }
+                break;
             }
         }
-        else
-            externallySetCompletion(completion);
-    }
-
-    /**
-     * Version of setCompletion for non-FJ threads.  Leaves signal
-     * bits for unblocked threads to adjust, and always notifies.
-     */
-    private void externallySetCompletion(int completion) {
-        int s;
-        do {} while ((s = status) >= 0 &&
-                     !casStatus(s, (s & SIGNAL_MASK) | completion));
-        synchronized (this) { notifyAll(); }
-    }
-
-    /**
-     * Sets status to indicate normal completion.
-     */
-    final void setNormalCompletion() {
-        // Try typical fast case -- single CAS, no signal, not already done.
-        // Manually expand casStatus to improve chances of inlining it
-        if (!UNSAFE.compareAndSwapInt(this, statusOffset, 0, NORMAL))
-            setCompletion(NORMAL);
-    }
-
-    // internal waiting and notification
-
-    /**
-     * Performs the actual monitor wait for awaitDone.
-     */
-    private void doAwaitDone() {
-        // Minimize lock bias and in/de-flation effects by maximizing
-        // chances of waiting inside sync
-        try {
-            while (status >= 0)
-                synchronized (this) { if (status >= 0) wait(); }
-        } catch (InterruptedException ie) {
-            onInterruptedWait();
-        }
     }
 
     /**
-     * Performs the actual timed monitor wait for awaitDone.
+     * Records exception and sets exceptional completion.
+     *
+     * @return status on exit
      */
-    private void doAwaitDone(long startTime, long nanos) {
-        synchronized (this) {
+    private void setExceptionalCompletion(Throwable rex) {
+        exceptionMap.put(this, rex);
+        setCompletion(EXCEPTIONAL);
+    }
+
+    /**
+     * Blocks a worker thread until completion. Called only by
+     * pool. Currently unused -- pool-based waits use timeout
+     * version below.
+     */
+    final void internalAwaitDone() {
+        int s;         // the odd construction reduces lock bias effects
+        while ((s = status) >= 0) {
             try {
-                while (status >= 0) {
-                    long nt = nanos - (System.nanoTime() - startTime);
-                    if (nt <= 0)
-                        break;
-                    wait(nt / 1000000, (int) (nt % 1000000));
+                synchronized(this) {
+                    if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
+                        wait();
                 }
             } catch (InterruptedException ie) {
-                onInterruptedWait();
+                cancelIfTerminating();
             }
         }
     }
 
-    // Awaiting completion
-
     /**
-     * Sets status to indicate there is joiner, then waits for join,
-     * surrounded with pool notifications.
+     * Blocks a worker thread until completed or timed out.  Called
+     * only by pool.
      *
-     * @return status upon exit
+     * @return status on exit
      */
-    private int awaitDone(ForkJoinWorkerThread w,
-                          boolean maintainParallelism) {
-        ForkJoinPool pool = (w == null) ? null : w.pool;
+    final int internalAwaitDone(long millis) {
         int s;
-        while ((s = status) >= 0) {
-            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
-                if (pool == null || !pool.preJoin(this, maintainParallelism))
-                    doAwaitDone();
-                if (((s = status) & INTERNAL_SIGNAL_MASK) != 0)
-                    adjustPoolCountsOnUnblock(pool);
-                break;
+        if ((s = status) >= 0) {
+            try {
+                synchronized(this) {
+                    if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
+                        wait(millis, 0);
+                }
+            } catch (InterruptedException ie) {
+                cancelIfTerminating();
             }
+            s = status;
         }
         return s;
     }
 
     /**
-     * Timed version of awaitDone
-     *
-     * @return status upon exit
+     * Blocks a non-worker-thread until completion.
      */
-    private int awaitDone(ForkJoinWorkerThread w, long nanos) {
-        ForkJoinPool pool = (w == null) ? null : w.pool;
+    private void externalAwaitDone() {
         int s;
         while ((s = status) >= 0) {
-            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
-                long startTime = System.nanoTime();
-                if (pool == null || !pool.preJoin(this, false))
-                    doAwaitDone(startTime, nanos);
-                if ((s = status) >= 0) {
-                    adjustPoolCountsOnCancelledWait(pool);
-                    s = status;
-                }
-                if (s < 0 && (s & INTERNAL_SIGNAL_MASK) != 0)
-                    adjustPoolCountsOnUnblock(pool);
-                break;
-            }
-        }
-        return s;
-    }
-
-    /**
-     * Notifies pool that thread is unblocked. Called by signalled
-     * threads when woken by non-FJ threads (which is atypical).
-     */
-    private void adjustPoolCountsOnUnblock(ForkJoinPool pool) {
-        int s;
-        do {} while ((s = status) < 0 && !casStatus(s, s & COMPLETION_MASK));
-        if (pool != null && (s &= INTERNAL_SIGNAL_MASK) != 0)
-            pool.updateRunningCount(s);
-    }
-
-    /**
-     * Notifies pool to adjust counts on cancelled or timed out wait.
-     */
-    private void adjustPoolCountsOnCancelledWait(ForkJoinPool pool) {
-        if (pool != null) {
-            int s;
-            while ((s = status) >= 0 && (s & INTERNAL_SIGNAL_MASK) != 0) {
-                if (casStatus(s, s - 1)) {
-                    pool.updateRunningCount(1);
+            synchronized(this) {
+                if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){
+                    boolean interrupted = false;
+                    while (status >= 0) {
+                        try {
+                            wait();
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
+                        }
+                    }
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
                     break;
                 }
             }
@@ -383,153 +307,19 @@
     }
 
     /**
-     * Handles interruptions during waits.
-     */
-    private void onInterruptedWait() {
-        ForkJoinWorkerThread w = getWorker();
-        if (w == null)
-            Thread.currentThread().interrupt(); // re-interrupt
-        else if (w.isTerminating())
-            cancelIgnoringExceptions();
-        // else if FJworker, ignore interrupt
-    }
-
-    // Recording and reporting exceptions
-
-    private void setDoneExceptionally(Throwable rex) {
-        exceptionMap.put(this, rex);
-        setCompletion(EXCEPTIONAL);
-    }
-
-    /**
-     * Throws the exception associated with status s.
-     *
-     * @throws the exception
-     */
-    private void reportException(int s) {
-        if ((s &= COMPLETION_MASK) < NORMAL) {
-            if (s == CANCELLED)
-                throw new CancellationException();
-            else
-                rethrowException(exceptionMap.get(this));
-        }
-    }
-
-    /**
-     * Returns result or throws exception using j.u.c.Future conventions.
-     * Only call when {@code isDone} known to be true or thread known
-     * to be interrupted.
-     */
-    private V reportFutureResult()
-        throws InterruptedException, ExecutionException {
-        if (Thread.interrupted())
-            throw new InterruptedException();
-        int s = status & COMPLETION_MASK;
-        if (s < NORMAL) {
-            Throwable ex;
-            if (s == CANCELLED)
-                throw new CancellationException();
-            if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
-                throw new ExecutionException(ex);
-        }
-        return getRawResult();
-    }
-
-    /**
-     * Returns result or throws exception using j.u.c.Future conventions
-     * with timeouts.
-     */
-    private V reportTimedFutureResult()
-        throws InterruptedException, ExecutionException, TimeoutException {
-        if (Thread.interrupted())
-            throw new InterruptedException();
-        Throwable ex;
-        int s = status & COMPLETION_MASK;
-        if (s == NORMAL)
-            return getRawResult();
-        else if (s == CANCELLED)
-            throw new CancellationException();
-        else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
-            throw new ExecutionException(ex);
-        else
-            throw new TimeoutException();
-    }
-
-    // internal execution methods
-
-    /**
-     * Calls exec, recording completion, and rethrowing exception if
-     * encountered. Caller should normally check status before calling.
-     *
-     * @return true if completed normally
-     */
-    private boolean tryExec() {
-        try { // try block must contain only call to exec
-            if (!exec())
-                return false;
-        } catch (Throwable rex) {
-            setDoneExceptionally(rex);
-            rethrowException(rex);
-            return false; // not reached
-        }
-        setNormalCompletion();
-        return true;
-    }
-
-    /**
-     * Main execution method used by worker threads. Invokes
-     * base computation unless already complete.
+     * Unless done, calls exec and records status if completed, but
+     * doesn't wait for completion otherwise. Primary execution method
+     * for ForkJoinWorkerThread.
      */
     final void quietlyExec() {
-        if (status >= 0) {
-            try {
-                if (!exec())
-                    return;
-            } catch (Throwable rex) {
-                setDoneExceptionally(rex);
+        try {
+            if (status < 0 || !exec())
                 return;
-            }
-            setNormalCompletion();
+        } catch (Throwable rex) {
+            setExceptionalCompletion(rex);
+            return;
         }
-    }
-
-    /**
-     * Calls exec(), recording but not rethrowing exception.
-     * Caller should normally check status before calling.
-     *
-     * @return true if completed normally
-     */
-    private boolean tryQuietlyInvoke() {
-        try {
-            if (!exec())
-                return false;
-        } catch (Throwable rex) {
-            setDoneExceptionally(rex);
-            return false;
-        }
-        setNormalCompletion();
-        return true;
-    }
-
-    /**
-     * Cancels, ignoring any exceptions it throws.
-     */
-    final void cancelIgnoringExceptions() {
-        try {
-            cancel(false);
-        } catch (Throwable ignore) {
-        }
-    }
-
-    /**
-     * Main implementation of helpJoin
-     */
-    private int busyJoin(ForkJoinWorkerThread w) {
-        int s;
-        ForkJoinTask<?> t;
-        while ((s = status) >= 0 && (t = w.scanWhileJoining(this)) != null)
-            t.quietlyExec();
-        return (s >= 0) ? awaitDone(w, false) : s; // block if no work
+        setCompletion(NORMAL); // must be outside try block
     }
 
     // public methods
@@ -567,34 +357,41 @@
      * @return the computed result
      */
     public final V join() {
-        ForkJoinWorkerThread w = getWorker();
-        if (w == null || status < 0 || !w.unpushTask(this) || !tryExec())
-            reportException(awaitDone(w, true));
+        quietlyJoin();
+        Throwable ex;
+        if (status < NORMAL && (ex = getException()) != null)
+            UNSAFE.throwException(ex);
         return getRawResult();
     }
 
     /**
      * Commences performing this task, awaits its completion if
-     * necessary, and return its result, or throws an (unchecked)
-     * exception if the underlying computation did so.
+     * necessary, and returns its result, or throws an (unchecked)
+     * {@code RuntimeException} or {@code Error} if the underlying
+     * computation did so.
      *
      * @return the computed result
      */
     public final V invoke() {
-        if (status >= 0 && tryExec())
-            return getRawResult();
-        else
-            return join();
+        quietlyInvoke();
+        Throwable ex;
+        if (status < NORMAL && (ex = getException()) != null)
+            UNSAFE.throwException(ex);
+        return getRawResult();
     }
 
     /**
      * Forks the given tasks, returning when {@code isDone} holds for
      * each task or an (unchecked) exception is encountered, in which
-     * case the exception is rethrown.  If either task encounters an
-     * exception, the other one may be, but is not guaranteed to be,
-     * cancelled.  If both tasks throw an exception, then this method
-     * throws one of them.  The individual status of each task may be
-     * checked using {@link #getException()} and related methods.
+     * case the exception is rethrown. If more than one task
+     * encounters an exception, then this method throws any one of
+     * these exceptions. If any task encounters an exception, the
+     * other may be cancelled. However, the execution status of
+     * individual tasks is not guaranteed upon exceptional return. The
+     * status of each task may be obtained using {@link
+     * #getException()} and related methods to check if they have been
+     * cancelled, completed normally or exceptionally, or left
+     * unprocessed.
      *
      * <p>This method may be invoked only from within {@code
      * ForkJoinTask} computations (as may be determined using method
@@ -615,12 +412,14 @@
     /**
      * Forks the given tasks, returning when {@code isDone} holds for
      * each task or an (unchecked) exception is encountered, in which
-     * case the exception is rethrown. If any task encounters an
-     * exception, others may be, but are not guaranteed to be,
-     * cancelled.  If more than one task encounters an exception, then
-     * this method throws any one of these exceptions.  The individual
-     * status of each task may be checked using {@link #getException()}
-     * and related methods.
+     * case the exception is rethrown. If more than one task
+     * encounters an exception, then this method throws any one of
+     * these exceptions. If any task encounters an exception, others
+     * may be cancelled. However, the execution status of individual
+     * tasks is not guaranteed upon exceptional return. The status of
+     * each task may be obtained using {@link #getException()} and
+     * related methods to check if they have been cancelled, completed
+     * normally or exceptionally, or left unprocessed.
      *
      * <p>This method may be invoked only from within {@code
      * ForkJoinTask} computations (as may be determined using method
@@ -644,7 +443,7 @@
                 t.fork();
             else {
                 t.quietlyInvoke();
-                if (ex == null)
+                if (ex == null && t.status < NORMAL)
                     ex = t.getException();
             }
         }
@@ -655,26 +454,27 @@
                     t.cancel(false);
                 else {
                     t.quietlyJoin();
-                    if (ex == null)
+                    if (ex == null && t.status < NORMAL)
                         ex = t.getException();
                 }
             }
         }
         if (ex != null)
-            rethrowException(ex);
+            UNSAFE.throwException(ex);
     }
 
     /**
      * Forks all tasks in the specified collection, returning when
      * {@code isDone} holds for each task or an (unchecked) exception
-     * is encountered.  If any task encounters an exception, others
-     * may be, but are not guaranteed to be, cancelled.  If more than
-     * one task encounters an exception, then this method throws any
-     * one of these exceptions.  The individual status of each task
-     * may be checked using {@link #getException()} and related
-     * methods.  The behavior of this operation is undefined if the
-     * specified collection is modified while the operation is in
-     * progress.
+     * is encountered, in which case the exception is rethrown. If
+     * more than one task encounters an exception, then this method
+     * throws any one of these exceptions. If any task encounters an
+     * exception, others may be cancelled. However, the execution