changeset 1061:7f5d822a91a4

Merge.
author andrew
date Tue, 14 Apr 2009 16:51:38 +0100
parents 111759f6793e ccff58bccd07
children 65dfd94650d3
files make/jprt.config src/windows/classes/sun/awt/windows/fontconfig.98.properties src/windows/classes/sun/awt/windows/fontconfig.Me.properties
diffstat 216 files changed, 11175 insertions(+), 3836 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Mar 30 23:19:55 2009 +0100
+++ b/.hgtags	Tue Apr 14 16:51:38 2009 +0100
@@ -26,3 +26,6 @@
 8311105ea7a3db7bcbcb2b696459127c7f2297a4 jdk7-b49
 58ba2cd5a25053684ec53205d95edeeaa0006f13 jdk7-b50
 fea0898259ae41c73620b1815aa48f036216155c jdk7-b51
+bcbeadb4a5d759b29e876ee2c83401e91ff22f60 jdk7-b52
+a2033addca678f9e4c0d92ffa1e389171cc9321d jdk7-b53
+d1c43d1f5676a24ba86221ac7cad5694f3a9afda jdk7-b54
--- a/make/common/Defs-linux.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/Defs-linux.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -94,6 +94,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 CC_OPT/NONE     = 
 CC_OPT/LOWER    = -O2
@@ -173,8 +176,8 @@
 
 # FASTDEBUG: Optimize the code in the -g versions, gives us a faster debug java
 ifeq ($(FASTDEBUG), true)
-  CFLAGS_DBG    += $(CC_OPT/LOWER)
-  CXXFLAGS_DBG	+= $(CC_OPT/LOWER)
+  CFLAGS_DBG    += $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
+  CXXFLAGS_DBG	+= $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
 endif
 
 CPPFLAGS_COMMON = -D$(ARCH) -DARCH='"$(ARCH)"' -DLINUX $(VERSION_DEFINES) \
--- a/make/common/Defs-solaris.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/Defs-solaris.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -93,6 +93,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 #
 # If -Xa is in CFLAGS_COMMON it will end up ahead of $(CC_OPT) for the
@@ -143,8 +146,8 @@
 #        Performance/size of files should be about the same, maybe smaller.
 #
 ifeq ($(FASTDEBUG), true)
-  CFLAGS_DEBUG_OPTION    = -g  $(CC_OPT/LOWER)
-  CXXFLAGS_DEBUG_OPTION  = -g0 $(CXX_OPT/LOWER)
+  CFLAGS_DEBUG_OPTION    = -g  $(CC_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
+  CXXFLAGS_DEBUG_OPTION  = -g0 $(CXX_OPT/$(FASTDEBUG_OPTIMIZATION_LEVEL))
 endif
 
 CFLAGS_COMMON   = -L$(OBJDIR)
--- a/make/common/Defs-windows.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/Defs-windows.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -111,6 +111,9 @@
     OPTIMIZATION_LEVEL = LOWER
   endif
 endif
+ifndef FASTDEBUG_OPTIMIZATION_LEVEL
+  FASTDEBUG_OPTIMIZATION_LEVEL = LOWER
+endif
 
 ifeq ($(CC_VERSION),msvc)
   # Visual Studio .NET 2003 or VS2003 compiler option definitions:
--- a/make/common/Defs.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/Defs.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -145,6 +145,11 @@
 #     2. ALT_BINARY_PLUGS_PATH overrides all locations of classes and libraries
 #     3. ALT_BUILD_BINARY_PLUGS_PATH is used to find a ALT_BINARY_PLUGS_PATH
 #     4. ALT_CLOSED_JDK_IMPORT_PATH is used to locate classes and libraries
+#   Note: If any of the ALT_ variables are modified here, it is assumed
+#         that the build should be done with IMPORT_BINARY_PLUGS=true as
+#         well.  Otherwise the default will be IMPORT_BINARY_PLUGS=false.
+#         Lastly, setting IMPORT_BINARY_PLUGS=false on the command line
+#         will override this logic, and plugs will not be imported.
 #
 
 # Always needed, defines the name of the imported/exported jarfile
@@ -155,9 +160,11 @@
     CLOSED_JDK_IMPORT_PATH = $(ALT_CLOSED_JDK_IMPORT_PATH)
     BINARY_PLUGS_PATH = $(CLOSED_JDK_IMPORT_PATH)
     BINARY_PLUGS_JARFILE = $(CLOSED_JDK_IMPORT_PATH)/jre/lib/rt.jar
+    IMPORT_BINARY_PLUGS=true
   endif
   ifdef ALT_BUILD_BINARY_PLUGS_PATH
     BUILD_BINARY_PLUGS_PATH = $(ALT_BUILD_BINARY_PLUGS_PATH)
+    IMPORT_BINARY_PLUGS=true
   else
     BUILD_BINARY_PLUGS_PATH = $(SLASH_JAVA)/re/jdk/$(JDK_VERSION)/promoted/latest/openjdk/binaryplugs
   endif
@@ -166,9 +173,11 @@
   ifdef ALT_BINARY_PLUGS_PATH
     BINARY_PLUGS_PATH  = $(ALT_BINARY_PLUGS_PATH)
     BINARY_PLUGS_JARFILE = $(BINARY_PLUGS_PATH)/jre/lib/$(BINARY_PLUGS_JARNAME)
+    IMPORT_BINARY_PLUGS=true
   endif
   ifdef ALT_BINARY_PLUGS_JARFILE
     BINARY_PLUGS_JARFILE = $(ALT_BINARY_PLUGS_JARFILE)
+    IMPORT_BINARY_PLUGS=true
   endif
 endif # OPENJDK
 
--- a/make/common/shared/Defs-java.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/shared/Defs-java.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -59,7 +59,15 @@
     ADD_CLIENT_VM_OPTION = true
   endif
 endif
-JAVA_JVM_FLAGS =
+
+# Options for hotspot to turn off printing of options with fastdebug version
+#   and creating the hotspot.log file.
+JAVA_HOTSPOT_DISABLE_PRINT_VMOPTIONS = \
+   -XX:-PrintVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-LogVMOutput
+
+# JVM options
+JAVA_JVM_FLAGS = $(JAVA_HOTSPOT_DISABLE_PRINT_VMOPTIONS)
+
 ifeq ($(ADD_CLIENT_VM_OPTION), true)
   JAVA_JVM_FLAGS += -client
 endif
--- a/make/common/shared/Platform.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/shared/Platform.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -229,11 +229,19 @@
   TEMP_DISK=C:/temp
   # GNU Make or MKS overrides $(PROCESSOR_ARCHITECTURE) to always
   # return "x86". Use the first word of $(PROCESSOR_IDENTIFIER) instead.
+  PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
+  PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH))
+  PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH))
+  PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH))
   ifndef ARCH_DATA_MODEL
-    ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
+    ifeq ($(PROC_ARCH),IA64)
       ARCH_DATA_MODEL=64
     else
-      ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64)
+      ifeq ($(PROC_ARCH),X64)
         ARCH_DATA_MODEL=64
       else
         ARCH_DATA_MODEL=32
@@ -245,10 +253,12 @@
     # If the user wants to perform a cross compile build then they must
     # - set ARCH_DATA_MODEL=64 and either
     #      + set ARCH to ia64 or amd64, or
-    ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)), AMD64)
+    ifeq ($(PROC_ARCH),X64)
       ARCH=amd64
     else
-      ARCH=ia64
+      ifeq ($(PROC_ARCH),IA64)
+        ARCH=ia64
+      endif
     endif
     LIBARCH=$(ARCH)
     # Value of Java os.arch property
--- a/make/common/shared/Sanity-Settings.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/shared/Sanity-Settings.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -245,6 +245,7 @@
   ALL_SETTINGS+=$(call addAltSetting,FREETYPE_HEADERS_PATH)
   ALL_SETTINGS+=$(call addAltSetting,FREETYPE_LIB_PATH)
   ALL_SETTINGS+=$(call addHeading,OPENJDK Import Binary Plug Settings)
+  ALL_SETTINGS+=$(call addOptionalSetting,IMPORT_BINARY_PLUGS)
   ALL_SETTINGS+=$(call addAltSetting,BINARY_PLUGS_JARFILE)
   ALL_SETTINGS+=$(call addAltSetting,BINARY_PLUGS_PATH)
   ALL_SETTINGS+=$(call addAltSetting,BUILD_BINARY_PLUGS_PATH)
--- a/make/common/shared/Sanity.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/common/shared/Sanity.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -502,13 +502,15 @@
 ######################################################
 ifdef OPENJDK
 sane-binary-plugs:
+  ifeq ($(IMPORT_BINARY_PLUGS),true)
 	@if [ ! -d "$(BINARY_PLUGS_PATH)" ]; then \
-	  $(ECHO) "ERROR: Can't locate pre-built libraries. \n" \
+	  $(ECHO) "WARNING: Can't locate pre-built libraries. \n" \
 	    "      Please check your access to \n" \
 	    "          $(BINARY_PLUGS_PATH) \n" \
 	    "      and/or check your value of ALT_BINARY_PLUGS_PATH. \n" \
-	   "" >> $(ERROR_FILE); \
+	   "" >> $(WARNING_FILE); \
 	fi
+  endif
 endif
 
 ######################################################
--- a/make/java/fdlibm/Makefile	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/fdlibm/Makefile	Tue Apr 14 16:51:38 2009 +0100
@@ -45,6 +45,7 @@
 ifeq ($(PLATFORM),windows)
   # Turn all optimizations off
   OPTIMIZATION_LEVEL = NONE
+  FASTDEBUG_OPTIMIZATION_LEVEL = NONE
   OTHER_CFLAGS =
   CPPFLAGS_DBG += -DLOGGING
 endif
@@ -56,6 +57,7 @@
 ifeq ($(PLATFORM),linux)
   # Turn all optimizations off
   OPTIMIZATION_LEVEL = NONE
+  FASTDEBUG_OPTIMIZATION_LEVEL = NONE
 endif
 
 #
--- a/make/java/java/mapfile-vers	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/java/mapfile-vers	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -135,7 +135,8 @@
 		Java_java_lang_ClassLoader_00024NativeLibrary_find;
 		Java_java_lang_ClassLoader_00024NativeLibrary_load;
 		Java_java_lang_ClassLoader_00024NativeLibrary_unload;
-                Java_java_lang_ClassLoader_registerNatives;
+		Java_java_lang_ClassLoader_getCaller; 
+		Java_java_lang_ClassLoader_registerNatives;
 		Java_java_lang_Compiler_registerNatives;
 		Java_java_lang_Double_longBitsToDouble;
 		Java_java_lang_Double_doubleToRawLongBits;
--- a/make/java/net/FILES_c.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/net/FILES_c.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -39,6 +39,10 @@
 	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	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/net/Makefile	Tue Apr 14 16:51:38 2009 +0100
@@ -108,11 +108,24 @@
 #
 LOCALE_SET_DEFINITION = jre
 
-properties: $(LIBDIR) $(LIBDIR)/net.properties
+MISC_FILES = $(LIBDIR) $(LIBDIR)/net.properties
 
 $(LIBDIR)/net.properties: $(SHARE_SRC)/lib/net.properties
 	@$(RM) $@
 	$(CP) $< $@
 
-build: properties
+# 
+# SDP configuration template
+#
+ifeq ($(PLATFORM), solaris)
+SDP_PATH = sdp/sdp.conf.template
+SDP_CONF = $(LIBDIR)/$(SDP_PATH)
+$(SDP_CONF): $(PLATFORM_SRC)/lib/$(SDP_PATH)
+	@$(RM) $*
+	$(install-file)
 
+MISC_FILES += $(SDP_CONF)
+endif
+
+build: $(MISC_FILES)
+
--- a/make/java/net/mapfile-vers	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/net/mapfile-vers	Tue Apr 14 16:51:38 2009 +0100
@@ -90,6 +90,7 @@
 		Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0;
 		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/redist/Makefile	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/java/redist/Makefile	Tue Apr 14 16:51:38 2009 +0100
@@ -251,9 +251,11 @@
 #
 ifdef OPENJDK
 
-include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
+  ifeq ($(IMPORT_BINARY_PLUGS),true)
+    include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
 
-build: import-binary-plugs
+    build: import-binary-plugs
+  endif
 
 else # !OPENJDK
 
--- a/make/jdk_generic_profile.sh	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/jdk_generic_profile.sh	Tue Apr 14 16:51:38 2009 +0100
@@ -174,7 +174,8 @@
    
   # Check CYGWIN (should have already been done)
   #   Assumption here is that you are in a shell window via cygwin.
-  if [ "$(echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64)" != "" ] ; then
+  proc_arch=`echo "$(PROCESSOR_IDENTIFIER)" | expand | cut -d' ' -f1 | sed -e 's@x86@X86@g' -e 's@Intel64@X64@g' -e 's@em64t@X64@g' -e 's@EM64T@X64@g' -e 's@amd64@X64@g' -e 's@AMD64@X64@g' -e 's@ia64@IA64@g'`
+  if [ "${proc_arch}" = "X64" ] ; then
     windows_arch=amd64
   else
     windows_arch=i586
--- a/make/jprt.config	Mon Mar 30 23:19:55 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,363 +0,0 @@
-#!echo "This is not a shell script"
-#############################################################################
-#
-# Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-#############################################################################
-#
-# JPRT shell configuration for building.
-#
-# Input environment variables:
-#    ALT_BOOTDIR
-#    ALT_SLASH_JAVA
-#    ALT_JDK_IMPORT_PATH
-#    OPENJDK
-#    Windows Only:
-#      PATH
-#      VS71COMNTOOLS
-#      PROCESSOR_IDENTIFIER
-#      ROOTDIR
-#
-# Output variable settings:
-#    make            Full path to GNU make
-#    compiler_path   Path to compiler bin directory
-#    compiler_name   Unique name of this compiler
-#
-# Output environment variables:
-#    PATH
-#    ALT_COMPILER_PATH
-#    OPENJDK only:
-#      ALT_CLOSED_JDK_IMPORT_PATH
-#      ALT_JDK_DEVTOOLS_DIR
-#    Windows Only:
-#      ALT_MSDEVTOOLS_PATH
-#      ALT_DEVTOOLS_PATH (To avoid the C:/UTILS default)
-#      LIB
-#      INCLUDE
-#
-# After JDK6, most settings will be found via ALT_SLASH_JAVA or
-#   by way of other system environment variables. If this was JDK5
-#   or an older JDK, you might need to export more ALT_* variables.
-#
-# On Windows AMD64, if MSSDK is not set, assumes Platform SDK is installed at:
-#          C:/Program Files/Microsoft Platform SDK
-#
-#############################################################################
-
-#############################################################################
-# Error
-error() # message
-{
-  echo "ERROR: $1"
-  exit 6
-}
-# Directory must exist
-dirMustExist() # dir name
-{
-  if [ ! -d "$1" ] ; then
-    error "Directory for $2 does not exist: $1"
-  fi
-}
-# File must exist
-fileMustExist() # dir name
-{
-  if [ ! -f "$1" ] ; then
-    error "File for $2 does not exist: $1"
-  fi
-}
-#############################################################################
-
-# Should be set by JPRT as the 3 basic inputs
-bootdir="${ALT_BOOTDIR}"
-slashjava="${ALT_SLASH_JAVA}"
-jdk_import="${ALT_JDK_IMPORT_PATH}"
-
-# The /java/devtools items
-jdk_devtools="${slashjava}/devtools"
-share="${jdk_devtools}/share"
-
-# Needed for langtools, maybe other parts of the build
-ANT_HOME="${share}/ant/latest"
-export ANT_HOME
-
-# The 3 bin directories in common to all platforms
-sharebin="${share}/bin"
-antbin="${ANT_HOME}/bin"
-
-# Check input
-dirMustExist "${bootdir}"         ALT_BOOTDIR
-dirMustExist "${slashjava}"       ALT_SLASH_JAVA
-dirMustExist "${jdk_import}"      ALT_JDK_IMPORT_PATH
-dirMustExist "${ANT_HOME}"        ANT_HOME
-
-# Use the JDK import for now (FIXME: use the binary plugs?)
-if [ "${OPENJDK}" = true ] ; then
-  ALT_CLOSED_JDK_IMPORT_PATH="${jdk_import}"
-  export ALT_CLOSED_JDK_IMPORT_PATH
-fi
-
-# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise.
-osname=`uname -s`
-if [ "${osname}" = SunOS ] ; then
-   
-    # SOLARIS: Sparc or X86
-    osarch=`uname -p`
-    if [ "${osarch}" = sparc ] ; then
-	solaris_arch=sparc
-    else
-	solaris_arch=i386
-    fi
-
-    # Get the compilers into path (make sure it matches ALT setting)
-    if [ "${JPRT_SOLARIS_COMPILER_NAME}" != "" ] ; then
-        compiler_name=${JPRT_SOLARIS_COMPILER_NAME}
-    else
-	compiler_name=SS12
-    fi
-    compiler_path=${jdk_devtools}/${solaris_arch}/SUNWspro/${compiler_name}/bin
-    ALT_COMPILER_PATH="${compiler_path}"
-    export ALT_COMPILER_PATH
-    dirMustExist "${compiler_path}" ALT_COMPILER_PATH
-    path4sdk=${compiler_path}:${sharebin}:${antbin}
-
-    # Add basic solaris system paths
-    path4sdk=${path4sdk}:/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin
-
-    # Get the previous JDK to be used to bootstrap the build
-    path4sdk=${bootdir}/bin:${path4sdk}
-
-    # Find GNU make
-    make=/usr/sfw/bin/gmake
-    if [ ! -f ${make} ] ; then
-	make=/opt/sfw/bin/gmake
-	if [ ! -f ${make} ] ; then
-	    make=${jdk_devtools}/${solaris_arch}/bin/gnumake
-        fi 
-    fi
-    fileMustExist "${make}" make
-
-    # File creation mask
-    umask 002
-
-elif [ "${osname}" = Linux ] ; then
-   
-    # LINUX: X86, AMD64
-    osarch=`uname -m`
-    if [ "${osarch}" = i686 ] ; then
-	linux_arch=i586
-    elif [ "${osarch}" = x86_64 ] ; then
-	linux_arch=amd64
-    fi
-
-    # Get the compilers into path (make sure it matches ALT setting)
-    compiler_path=/usr/bin
-    compiler_name=usr_bin
-    ALT_COMPILER_PATH="${compiler_path}"
-    export ALT_COMPILER_PATH
-    dirMustExist "${compiler_path}" ALT_COMPILER_PATH
-    path4sdk=${compiler_path}:${sharebin}:${antbin}
-    
-    # Add basic paths
-    path4sdk=${path4sdk}:/usr/bin:/bin:/usr/sbin:/sbin
-
-    # Get the previous JDK to be used to bootstrap the build
-    path4sdk=${bootdir}/bin:${path4sdk}
-    
-    # Find GNU make
-    make=/usr/bin/make
-    fileMustExist "${make}" make
-
-    umask 002
-   
-    # Linux platform may be old, use motif files from the devtools area
-    if [ "${OPENJDK}" = true ] ; then
-      ALT_JDK_DEVTOOLS_DIR="${jdk_devtools}"
-      export ALT_JDK_DEVTOOLS_DIR
-    fi
-
-
-else
-
-    # Windows: Differs on CYGWIN vs. MKS, and the compiler available.
-    #   Also, blanks in pathnames gives GNU make headaches, so anything placed
-    #   in any ALT_* variable should be the short windows dosname.
-   
-    # WINDOWS: Install and use MKS or CYGWIN (should have already been done)
-    #   Assumption here is that you are in a shell window via MKS or cygwin.
-    #   MKS install should have defined the environment variable ROOTDIR.
-    #   We also need to figure out which one we have: X86, AMD64
-    if [ "`echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64`" != "" ] ; then
-	windows_arch=amd64
-    else
-	windows_arch=i586
-    fi
-    
-    # We need to determine if we are running a CYGWIN shell or an MKS shell
-    #    (if uname isn't available, then it will be unix_toolset=unknown)
-    unix_toolset=unknown
-    if [ "`uname -a | fgrep Cygwin`" = "" -a -d "${ROOTDIR}" ] ; then
-        # We kind of assume ROOTDIR is where MKS is and it's ok
-        unix_toolset=MKS
-        mkshome=`dosname -s "${ROOTDIR}"`
-	# Utility to convert to short pathnames without spaces
-	dosname="${mkshome}/mksnt/dosname -s"
-        # Most unix utilities are in the mksnt directory of ROOTDIR
-        unixcommand_path="${mkshome}/mksnt"
-        path4sdk="${sharebin};${antbin};${unixcommand_path}"
-        dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH
-	devtools_path="${jdk_devtools}/win32/bin"
-	path4sdk="${devtools_path};${path4sdk}"
-	# Normally this need not be set, but on Windows it's default is C:/UTILS
-        ALT_DEVTOOLS_PATH="${devtools_path}"
-	export ALT_DEVTOOLS_PATH
-        dirMustExist "${devtools_path}" ALT_DEVTOOLS_PATH
-        # Find GNU make
-        make="${devtools_path}/gnumake.exe"
-        fileMustExist "${make}" make
-    elif [ "`uname -a | fgrep Cygwin`" != "" -a -f /bin/cygpath ] ; then
-        # For CYGWIN, uname will have "Cygwin" in it, and /bin/cygpath should exist
-        unix_toolset=CYGWIN
-	# Utility to convert to short pathnames without spaces
-	dosname="/usr/bin/cygpath -a -m -s"
-        # Most unix utilities are in the /usr/bin
-        unixcommand_path="/usr/bin"
-        path4sdk="${sharebin};${antbin};${unixcommand_path}"
-        dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH
-        # Find GNU make
-        make="${unixcommand_path}/make.exe"
-        fileMustExist "${make}" make
-    else
-      echo "WARNING: Cannot figure out if this is MKS or CYGWIN"
-    fi
-
-    # WINDOWS: Compiler setup (nasty part)
-    #   NOTE: You can use vcvars32.bat to set PATH, LIB, and INCLUDE.
-    #   NOTE: CYGWIN has a link.exe too, make sure the compilers are first
-    if [ "${windows_arch}" = i586 ] ; then
-        # 32bit Windows compiler settings
-        # VisualStudio .NET 2003 VC++ 7.1 (VS71COMNTOOLS should be defined)
-        vs_root=`${dosname} "${VS71COMNTOOLS}/../.."`
-        # Fill in PATH, LIB, and INCLUDE (unset all others to make sure)
-        msdev_root="${vs_root}/Common7/Tools"
-        msdevtools_path="${msdev_root}/bin"
-        vc7_root="${vs_root}/Vc7"
-        compiler_path="${vc7_root}/bin"
-        compiler_name=VS2003
-        platform_sdk="${vc7_root}/PlatformSDK"
-        # LIB and INCLUDE must use ; as a separator
-        include4sdk="${vc7_root}/atlmfc/include"
-        include4sdk="${include4sdk};${vc7_root}/include"
-        include4sdk="${include4sdk};${platform_sdk}/include/prerelease"
-        include4sdk="${include4sdk};${platform_sdk}/include"
-        include4sdk="${include4sdk};${vs_root}/SDK/v1.1/include"
-        lib4sdk="${vc7_root}/atlmfc/lib"
-        lib4sdk="${lib4sdk};${vc7_root}/lib"
-        lib4sdk="${lib4sdk};${platform_sdk}/lib/prerelease"
-        lib4sdk="${lib4sdk};${platform_sdk}/lib"
-        lib4sdk="${lib4sdk};${vs_root}/SDK/v1.1/lib"
-        # Search path and DLL locating path
-        #   WARNING: CYGWIN has a link.exe too, make sure compilers are first
-        path4sdk="${vs_root}/Common7/Tools/bin;${path4sdk}"
-	path4sdk="${vs_root}/SDK/v1.1/bin;${path4sdk}"
-        path4sdk="${vs_root}/Common7/Tools;${path4sdk}"
-	path4sdk="${vs_root}/Common7/Tools/bin/prerelease;${path4sdk}"
-        path4sdk="${vs_root}/Common7/IDE;${path4sdk}"
-	path4sdk="${compiler_path};${path4sdk}"
-    elif [ "${windows_arch}" = amd64 ] ; then
-        # AMD64 64bit Windows compiler settings
-	if [ "${MSSDK}" != "" ] ; then
-	    platform_sdk="${MSSDK}"
-	else
-	    platform_sdk=`${dosname} "C:/Program Files/Microsoft Platform SDK/"`
-	fi
-	compiler_path="${platform_sdk}/Bin/win64/x86/AMD64"
-        compiler_name=VS2005_PSDK
-	msdevtools_path="${platform_sdk}/Bin"
-        # LIB and INCLUDE must use ; as a separator
-        include4sdk="${platform_sdk}/Include"
-	include4sdk="${include4sdk};${platform_sdk}/Include/crt/sys"
-	include4sdk="${include4sdk};${platform_sdk}/Include/mfc"
-	include4sdk="${include4sdk};${platform_sdk}/Include/atl"
-	include4sdk="${include4sdk};${platform_sdk}/Include/crt"
-        lib4sdk="${platform_sdk}/Lib/AMD64"
-        lib4sdk="${lib4sdk};${platform_sdk}/Lib/AMD64/atlmfc"
-        # Search path and DLL locating path
-        #   WARNING: CYGWIN has a link.exe too, make sure compilers are first
-        path4sdk="${platform_sdk}/bin;${path4sdk}"
-        path4sdk="${compiler_path};${path4sdk}"
-    fi
-    # Export LIB and INCLUDE
-    unset lib
-    unset Lib
-    LIB="${lib4sdk}"
-    export LIB
-    unset include
-    unset Include
-    INCLUDE="${include4sdk}"
-    export INCLUDE
-    # Set the ALT variable
-    ALT_COMPILER_PATH=`${dosname} "${compiler_path}"`
-    export ALT_COMPILER_PATH
-    dirMustExist "${compiler_path}" ALT_COMPILER_PATH
-    ALT_MSDEVTOOLS_PATH=`${dosname} "${msdevtools_path}"`
-    export ALT_MSDEVTOOLS_PATH
-    dirMustExist "${msdevtools_path}" ALT_MSDEVTOOLS_PATH
-    
-    # WINDOWS: Get the previous JDK to be used to bootstrap the build
-    path4sdk="${bootdir}/bin;${path4sdk}"
-
-    # Turn all \\ into /, remove duplicates and trailing /
-    slash_path="`echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g'`"
-    
-    # For windows, it's hard to know where the system is, so we just add this
-    #    to PATH.
-    path4sdk="${slash_path};${PATH}"
-    
-    # Convert path4sdk to cygwin style
-    if [ "${unix_toolset}" = CYGWIN ] ; then
-	path4sdk="`/usr/bin/cygpath -p ${path4sdk}`"
-    fi
-
-    # Set special windows ALT variables
-    ALT_ISHIELDDIR="C:/ishield802"
-    export ALT_ISHIELDDIR
-
-    # Sponsors binaries
-    ALT_SPONSOR1DIR=C:/sponsor_binaries
-    export ALT_SPONSOR1DIR
-    ALT_SPONSOR2DIR=C:/sponsor_binaries 
-    export ALT_SPONSOR2DIR
-
-fi
-
-# Export PATH setting
-PATH="${path4sdk}"
-export PATH
-
-# Things we need to unset
-unset LD_LIBRARY_PATH
-unset LD_LIBRARY_PATH_32
-unset LD_LIBRARY_PATH_64
-unset JAVA_HOME
-
--- a/make/jprt.properties	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/jprt.properties	Tue Apr 14 16:51:38 2009 +0100
@@ -53,6 +53,19 @@
 
 # Standard list of jprt test targets for this workspace
 jprt.test.targets=*-*-*-jvm98
+jprt.regression.test.targets=  \
+   *-*-*-java/lang,            \
+   *-*-*-java/security,        \
+   *-*-*-java/text,            \
+   *-*-*-java/util
+
+#jprt.regression.test.targets=   \
+#   *-*-*-java/awt,       \
+#   *-*-*-java/beans,     \
+#   *-*-*-java/io,        \
+#   *-*-*-java/net,       \
+#   *-*-*-java/nio,       \
+#   *-*-*-java/rmi,       \
 
 # Directories needed to build
 jprt.bundle.exclude.src.dirs=build
--- a/make/sun/awt/Makefile	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/sun/awt/Makefile	Tue Apr 14 16:51:38 2009 +0100
@@ -339,8 +339,7 @@
 
 FONTCONFIGS_SRC = $(PLATFORM_SRC)/classes/sun/awt/windows
 _FONTCONFIGS = \
-        fontconfig.properties \
-        fontconfig.98.properties 
+        fontconfig.properties
 
 FONTCONFIGS_SRC_PREFIX =
 
--- a/make/sun/net/FILES_java.gmk	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/sun/net/FILES_java.gmk	Tue Apr 14 16:51:38 2009 +0100
@@ -39,6 +39,7 @@
 	sun/net/TransferProtocolClient.java \
 	sun/net/ConnectionResetException.java \
 	sun/net/NetProperties.java \
+	sun/net/NetHooks.java \
 	sun/net/util/IPAddressUtil.java \
 	sun/net/dns/ResolverConfiguration.java \
 	sun/net/dns/ResolverConfigurationImpl.java \
@@ -123,3 +124,7 @@
 ifeq ($(PLATFORM), windows)
     FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java 
 endif
+
+ifeq ($(PLATFORM), solaris)
+    FILES_java += sun/net/spi/SdpProvider.java
+endif
--- a/make/sun/xawt/mapfile-vers	Mon Mar 30 23:19:55 2009 +0100
+++ b/make/sun/xawt/mapfile-vers	Tue Apr 14 16:51:38 2009 +0100
@@ -304,12 +304,14 @@
         Java_java_awt_FileDialog_initIDs;
         Java_sun_awt_X11_XWindow_initIDs;
 
+        Java_sun_java2d_opengl_OGLContext_getOGLIdString;
         Java_sun_java2d_opengl_OGLMaskFill_maskFill;
         Java_sun_java2d_opengl_OGLRenderer_drawPoly;
         Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer;
         Java_sun_java2d_opengl_OGLSurfaceData_initTexture;
         Java_sun_java2d_opengl_OGLSurfaceData_initFBObject;
         Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer;
+        Java_sun_java2d_opengl_OGLSurfaceData_getTextureID;
         Java_sun_java2d_opengl_OGLSurfaceData_getTextureTarget;
         Java_sun_java2d_opengl_OGLTextRenderer_drawGlyphList;
         Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo;
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java	Tue Apr 14 16:51:38 2009 +0100
@@ -153,7 +153,7 @@
         node.setAttribute("imageWidth", Integer.toString(imageWidth));
         node.setAttribute("imageHeight", Integer.toString(imageHeight));
         node.setAttribute("interlaceFlag",
-                          interlaceFlag ? "true" : "false");
+                          interlaceFlag ? "TRUE" : "FALSE");
         root.appendChild(node);
 
         // Local color table
@@ -185,9 +185,9 @@
         node.setAttribute("disposalMethod",
                           disposalMethodNames[disposalMethod]);
         node.setAttribute("userInputFlag",
-                          userInputFlag ? "true" : "false");
+                          userInputFlag ? "TRUE" : "FALSE");
         node.setAttribute("transparentColorFlag",
-                          transparentColorFlag ? "true" : "false");
+                          transparentColorFlag ? "TRUE" : "FALSE");
         node.setAttribute("delayTime",
                           Integer.toString(delayTime));
         node.setAttribute("transparentColorIndex",
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Tue Apr 14 16:51:38 2009 +0100
@@ -55,6 +55,7 @@
 import org.w3c.dom.NodeList;
 import com.sun.imageio.plugins.common.LZWCompressor;
 import com.sun.imageio.plugins.common.PaletteBuilder;
+import sun.awt.image.ByteComponentRaster;
 
 public class GIFImageWriter extends ImageWriter {
     private static final boolean DEBUG = false; // XXX false for release!
@@ -905,10 +906,18 @@
         LZWCompressor compressor =
             new LZWCompressor(stream, initCodeSize, false);
 
+        /* At this moment we know that input image is indexed image.
+         * We can directly copy data iff:
+         *   - no subsampling required (periodX = 1, periodY = 0)
+         *   - we can access data directly (image is non-tiled,
+         *     i.e. image data are in single block)
+         *   - we can calculate offset in data buffer (next 3 lines)
+         */
         boolean isOptimizedCase =
             periodX == 1 && periodY == 1 &&
+            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
             sampleModel instanceof ComponentSampleModel &&
-            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
+            image.getTile(0, 0) instanceof ByteComponentRaster &&
             image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte;
 
         int numRowsWritten = 0;
@@ -921,11 +930,14 @@
             if (DEBUG) System.out.println("Writing interlaced");
 
             if (isOptimizedCase) {
-                Raster tile = image.getTile(0, 0);
+                ByteComponentRaster tile =
+                    (ByteComponentRaster)image.getTile(0, 0);
                 byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
                 ComponentSampleModel csm =
                     (ComponentSampleModel)tile.getSampleModel();
                 int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
+                // take into account the raster data offset
+                offset += tile.getDataOffset(0);
                 int lineStride = csm.getScanlineStride();
 
                 writeRowsOpt(data, offset, lineStride, compressor,
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java	Tue Apr 14 16:51:38 2009 +0100
@@ -158,13 +158,10 @@
             }
         }
         String value = attr.getNodeValue();
-        // XXX Should be able to use equals() here instead of
-        // equalsIgnoreCase() but some boolean attributes are incorrectly
-        // set to "true" or "false" by the J2SE core metadata classes
-        // getAsTree() method (which are duplicated above). See bug 5082756.
-        if (value.equalsIgnoreCase("TRUE")) {
+        // Allow lower case booleans for backward compatibility, #5082756
+        if (value.equals("TRUE") || value.equals("true")) {
             return true;
-        } else if (value.equalsIgnoreCase("FALSE")) {
+        } else if (value.equals("FALSE") || value.equals("false")) {
             return false;
         } else {
             fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFStreamMetadata.java	Tue Apr 14 16:51:38 2009 +0100
@@ -202,7 +202,7 @@
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("Lossless");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         compression_node.appendChild(node);
 
         // NumProgressiveScans not in stream
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1003,7 +1003,7 @@
                                                3,
                                                new int [] {0, 1, 2},
                                                null);
-            ColorModel cm = new ComponentColorModel(JPEG.sRGB,
+            ColorModel cm = new ComponentColorModel(JPEG.JCS.sRGB,
                                                     false,
                                                     false,
                                                     ColorModel.OPAQUE,
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Tue Apr 14 16:51:38 2009 +0100
@@ -208,15 +208,24 @@
 
     public static final int [] bOffsRGB = { 2, 1, 0 };
 
-    protected static final ColorSpace sRGB =
-        ColorSpace.getInstance(ColorSpace.CS_sRGB);
-    protected static ColorSpace YCC = null;  // Can't be final
+    /* These are kept in the inner class to avoid static initialization
+     * of the CMM class until someone actually needs it.
+     * (e.g. do not init CMM on the request for jpeg mime types)
+     */
+    public static class JCS {
+        public static final ColorSpace sRGB =
+            ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        public static final ColorSpace YCC;
 
-    static {
-        try {
-            YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
-        } catch (IllegalArgumentException e) {
-            // PYCC.pf may not always be installed
+        static {
+            ColorSpace cs = null;
+            try {
+                cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
+            } catch (IllegalArgumentException e) {
+                // PYCC.pf may not always be installed
+            } finally {
+                YCC = cs;
+            }
         }
     }
 
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Tue Apr 14 16:51:38 2009 +0100
@@ -228,31 +228,31 @@
             (BufferedImage.TYPE_BYTE_GRAY);
         defaultTypes[JPEG.JCS_RGB] =
             ImageTypeSpecifier.createInterleaved
-            (JPEG.sRGB,
+            (JPEG.JCS.sRGB,
              JPEG.bOffsRGB,
              DataBuffer.TYPE_BYTE,
              false,
              false);
         defaultTypes[JPEG.JCS_RGBA] =
             ImageTypeSpecifier.createPacked
-            (JPEG.sRGB,
+            (JPEG.JCS.sRGB,
              0xff000000,
              0x00ff0000,
              0x0000ff00,
              0x000000ff,
              DataBuffer.TYPE_INT,
              false);
-        if (JPEG.YCC != null) {
+        if (JPEG.JCS.YCC != null) {
             defaultTypes[JPEG.JCS_YCC] =
                 ImageTypeSpecifier.createInterleaved
-                (JPEG.YCC,
+                (JPEG.JCS.YCC,
                  JPEG.bandOffsets[2],
                  DataBuffer.TYPE_BYTE,
                  false,
                  false);
             defaultTypes[JPEG.JCS_YCCA] =
                 ImageTypeSpecifier.createInterleaved
-                (JPEG.YCC,
+                (JPEG.JCS.YCC,
                  JPEG.bandOffsets[3],
                  DataBuffer.TYPE_BYTE,
                  true,
@@ -774,7 +774,7 @@
         case JPEG.JCS_RGB:
             list.add(raw);
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.YCC != null) {
+            if (JPEG.JCS.YCC != null) {
                 list.add(getImageType(JPEG.JCS_YCC));
             }
             break;
@@ -811,7 +811,7 @@
             }
 
             list.add(getImageType(JPEG.JCS_GRAYSCALE));
-            if (JPEG.YCC != null) { // Might be null if PYCC.pf not installed
+            if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed
                 list.add(getImageType(JPEG.JCS_YCC));
             }
             break;
@@ -893,7 +893,7 @@
                        (!cs.isCS_sRGB()) &&
                        (cm.getNumComponents() == numComponents)) {
                 // Target isn't sRGB, so convert from sRGB to the target
-                convert = new ColorConvertOp(JPEG.sRGB, cs, null);
+                convert = new ColorConvertOp(JPEG.JCS.sRGB, cs, null);
             } else if (csType != ColorSpace.TYPE_RGB) {
                 throw new IIOException("Incompatible color conversion");
             }
@@ -906,18 +906,18 @@
             }
             break;
         case JPEG.JCS_YCC:
-            if (JPEG.YCC == null) { // We can't do YCC at all
+            if (JPEG.JCS.YCC == null) { // We can't do YCC at all
                 throw new IIOException("Incompatible color conversion");
             }
-            if ((cs != JPEG.YCC) &&
+            if ((cs != JPEG.JCS.YCC) &&
                 (cm.getNumComponents() == numComponents)) {
-                convert = new ColorConvertOp(JPEG.YCC, cs, null);
+                convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null);
             }
             break;
         case JPEG.JCS_YCCA:
             // No conversions available; image must be YCCA
-            if ((JPEG.YCC == null) || // We can't do YCC at all
-                (cs != JPEG.YCC) ||
+            if ((JPEG.JCS.YCC == null) || // We can't do YCC at all
+                (cs != JPEG.JCS.YCC) ||
                 (cm.getNumComponents() != numComponents)) {
                 throw new IIOException("Incompatible color conversion");
             }
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Tue Apr 14 16:51:38 2009 +0100
@@ -39,8 +39,6 @@
     private static String [] writerSpiNames =
         {"com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi"};
 
-    private boolean registered = false;
-
     public JPEGImageReaderSpi() {
         super(JPEG.vendor,
               JPEG.version,
@@ -61,26 +59,6 @@
               );
     }
 
-    public void onRegistration(ServiceRegistry registry,
-                               Class<?> category) {
-        if (registered) {
-            return;
-        }
-        try {
-            java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("jpeg"));
-            // Stuff it all into one lib for first pass
-            //java.security.AccessController.doPrivileged(
-            //new sun.security.action.LoadLibraryAction("imageioIJG"));
-        } catch (Throwable e) { // Fail on any Throwable
-            // if it can't be loaded, deregister and return
-            registry.deregisterServiceProvider(this);
-            return;
-        }
-
-        registered = true;
-    }
-
     public String getDescription(Locale locale) {
         return "Standard JPEG Image Reader";
     }
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Tue Apr 14 16:51:38 2009 +0100
@@ -812,13 +812,13 @@
                             }
                             break;
                         case ColorSpace.TYPE_3CLR:
-                            if (cs == JPEG.YCC) {
+                            if (cs == JPEG.JCS.YCC) {
                                 if (!alpha) {
                                     if (jfif != null) {
                                         convertTosRGB = true;
                                         convertOp =
                                         new ColorConvertOp(cs,
-                                                           JPEG.sRGB,
+                                                           JPEG.JCS.sRGB,
                                                            null);
                                         outCsType = JPEG.JCS_YCbCr;
                                     } else if (adobe != null) {
@@ -1494,7 +1494,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1533,7 +1533,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
@@ -1579,7 +1579,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     if (alpha) {
                         retval = JPEG.JCS_YCCA;
                     } else {
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Tue Apr 14 16:51:38 2009 +0100
@@ -42,8 +42,6 @@
     private static String [] readerSpiNames =
         {"com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi"};
 
-    private boolean registered = false;
-
     public JPEGImageWriterSpi() {
         super(JPEG.vendor,
               JPEG.version,
@@ -68,23 +66,6 @@
         return "Standard JPEG Image Writer";
     }
 
-    public void onRegistration(ServiceRegistry registry,
-                               Class<?> category) {
-        if (registered) {
-            return;
-        }
-        try {
-            java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("jpeg"));
-        } catch (Throwable e) { // Fail on any Throwable
-            // if it can't be loaded, deregister and return
-            registry.deregisterServiceProvider(this);
-            return;
-        }
-
-        registered = true;
-    }
-
     public boolean isFormatLossless() {
         return false;
     }
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java	Tue Apr 14 16:51:38 2009 +0100
@@ -490,7 +490,7 @@
                 }
                 break;
             case ColorSpace.TYPE_3CLR:
-                if (cs == JPEG.YCC) {
+                if (cs == JPEG.JCS.YCC) {
                     wantJFIF = false;
                     componentIDs[0] = (byte) 'Y';
                     componentIDs[1] = (byte) 'C';
@@ -955,7 +955,7 @@
 
         // Lossless - false
         IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
-        lossless.setAttribute("value", "false");
+        lossless.setAttribute("value", "FALSE");
         compression.appendChild(lossless);
 
         // NumProgressiveScans - count sos segments
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Tue Apr 14 16:51:38 2009 +0100
@@ -37,6 +37,7 @@
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
+import java.io.EOFException;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.SequenceInputStream;
@@ -59,7 +60,7 @@
 import java.io.ByteArrayOutputStream;
 import sun.awt.image.ByteInterleavedRaster;
 
-class PNGImageDataEnumeration implements Enumeration {
+class PNGImageDataEnumeration implements Enumeration<InputStream> {
 
     boolean firstTime = true;
     ImageInputStream stream;
@@ -72,7 +73,7 @@
         int type = stream.readInt(); // skip chunk type
     }
 
-    public Object nextElement() {
+    public InputStream nextElement() {
         try {
             firstTime = false;
             ImageInputStream iis = new SubImageInputStream(stream, length);
@@ -207,25 +208,17 @@
         resetStreamSettings();
     }
 
-    private String readNullTerminatedString(String charset) throws IOException {
+    private String readNullTerminatedString(String charset, int maxLen) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         int b;
-        while ((b = stream.read()) != 0) {
+        int count = 0;
+        while ((maxLen > count++) && ((b = stream.read()) != 0)) {
+            if (b == -1) throw new EOFException();
             baos.write(b);
         }
         return new String(baos.toByteArray(), charset);
     }
 
-    private String readNullTerminatedString() throws IOException {
-        StringBuilder b = new StringBuilder();
-        int c;
-
-        while ((c = stream.read()) != 0) {
-            b.append((char)c);
-        }
-        return b.toString();
-    }
-
     private void readHeader() throws IIOException {
         if (gotHeader) {
             return;
@@ -434,7 +427,7 @@
     }
 
     private void parse_iCCP_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.iCCP_profileName = keyword;
 
         metadata.iCCP_compressionMethod = stream.readUnsignedByte();
@@ -450,7 +443,7 @@
     private void parse_iTXt_chunk(int chunkLength) throws IOException {
         long chunkStart = stream.getStreamPosition();
 
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.iTXt_keyword.add(keyword);
 
         int compressionFlag = stream.readUnsignedByte();
@@ -459,15 +452,17 @@
         int compressionMethod = stream.readUnsignedByte();
         metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
 
-        String languageTag = readNullTerminatedString("UTF8");
+        String languageTag = readNullTerminatedString("UTF8", 80);
         metadata.iTXt_languageTag.add(languageTag);
 
+        long pos = stream.getStreamPosition();
+        int maxLen = (int)(chunkStart + chunkLength - pos);
         String translatedKeyword =
-            readNullTerminatedString("UTF8");
+            readNullTerminatedString("UTF8", maxLen);
         metadata.iTXt_translatedKeyword.add(translatedKeyword);
 
         String text;
-        long pos = stream.getStreamPosition();
+        pos = stream.getStreamPosition();
         byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
         stream.readFully(b);
 
@@ -511,7 +506,7 @@
 
     private void parse_sPLT_chunk(int chunkLength)
         throws IOException, IIOException {
-        metadata.sPLT_paletteName = readNullTerminatedString();
+        metadata.sPLT_paletteName = readNullTerminatedString("ISO-8859-1", 80);
         chunkLength -= metadata.sPLT_paletteName.length() + 1;
 
         int sampleDepth = stream.readUnsignedByte();
@@ -554,12 +549,12 @@
     }
 
     private void parse_tEXt_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.tEXt_keyword.add(keyword);
 
         byte[] b = new byte[chunkLength - keyword.length() - 1];
         stream.readFully(b);
-        metadata.tEXt_text.add(new String(b));
+        metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
     }
 
     private void parse_tIME_chunk() throws IOException {
@@ -640,7 +635,7 @@
     }
 
     private void parse_zTXt_chunk(int chunkLength) throws IOException {
-        String keyword = readNullTerminatedString();
+        String keyword = readNullTerminatedString("ISO-8859-1", 80);
         metadata.zTXt_keyword.add(keyword);
 
         int method = stream.readUnsignedByte();
@@ -648,7 +643,7 @@
 
         byte[] b = new byte[chunkLength - keyword.length() - 2];
         stream.readFully(b);
-        metadata.zTXt_text.add(new String(inflate(b)));
+        metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
     }
 
     private void readMetadata() throws IIOException {
@@ -1263,7 +1258,7 @@
         try {
             stream.seek(imageStartPosition);
 
-            Enumeration e = new PNGImageDataEnumeration(stream);
+            Enumeration<InputStream> e = new PNGImageDataEnumeration(stream);
             InputStream is = new SequenceInputStream(e);
 
            /* InflaterInputStream uses an Inflater instance which consumes
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java	Tue Apr 14 16:51:38 2009 +0100
@@ -674,13 +674,8 @@
     private byte[] deflate(byte[] b) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DeflaterOutputStream dos = new DeflaterOutputStream(baos);
-
-        int len = b.length;
-        for (int i = 0; i < len; i++) {
-            dos.write((int)(0xff & b[i]));
-        }
+        dos.write(b);
         dos.close();
-
         return baos.toByteArray();
     }
 
@@ -736,7 +731,7 @@
             cs.writeByte(compressionMethod);
 
             String text = (String)textIter.next();
-            cs.write(deflate(text.getBytes()));
+            cs.write(deflate(text.getBytes("ISO-8859-1")));
             cs.finish();
         }
     }
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java	Tue Apr 14 16:51:38 2009 +0100
@@ -211,8 +211,8 @@
     public int sRGB_renderingIntent;
 
     // tEXt chunk
-    public ArrayList tEXt_keyword = new ArrayList(); // 1-79 char Strings
-    public ArrayList tEXt_text = new ArrayList(); // Strings
+    public ArrayList<String> tEXt_keyword = new ArrayList<String>(); // 1-79 characters
+    public ArrayList<String> tEXt_text = new ArrayList<String>();
 
     // tIME chunk
     public boolean tIME_present;
@@ -235,13 +235,13 @@
     public int tRNS_blue;
 
     // zTXt chunk
-    public ArrayList zTXt_keyword = new ArrayList(); // Strings
-    public ArrayList zTXt_compressionMethod = new ArrayList(); // Integers
-    public ArrayList zTXt_text = new ArrayList(); // Strings
+    public ArrayList<String> zTXt_keyword = new ArrayList<String>();
+    public ArrayList<Integer> zTXt_compressionMethod = new ArrayList<Integer>();
+    public ArrayList<String> zTXt_text = new ArrayList<String>();
 
     // Unknown chunks
-    public ArrayList unknownChunkType = new ArrayList(); // Strings
-    public ArrayList unknownChunkData = new ArrayList(); // byte arrays
+    public ArrayList<String> unknownChunkType = new ArrayList<String>();
+    public ArrayList<byte[]> unknownChunkData = new ArrayList<byte[]>();
 
     public PNGMetadata() {
         super(true,
@@ -426,21 +426,14 @@
         return false;
     }
 
-    private ArrayList cloneBytesArrayList(ArrayList in) {
+    private ArrayList<byte[]> cloneBytesArrayList(ArrayList<byte[]> in) {
         if (in == null) {
             return null;
         } else {
-            ArrayList list = new ArrayList(in.size());
-            Iterator iter = in.iterator();
-            while (iter.hasNext()) {
-                Object o = iter.next();
-                if (o == null) {
-                    list.add(null);
-                } else {
-                    list.add(((byte[])o).clone());
-                }
+            ArrayList<byte[]> list = new ArrayList<byte[]>(in.size());
+            for (byte[] b: in) {
+                list.add((b == null) ? null : (byte[])b.clone());
             }
-
             return list;
         }
     }
@@ -600,7 +593,7 @@
                 IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
                 iTXt_node.setAttribute("keyword", iTXt_keyword.get(i));
                 iTXt_node.setAttribute("compressionFlag",
-                        iTXt_compressionFlag.get(i) ? "1" : "0");
+                        iTXt_compressionFlag.get(i) ? "TRUE" : "FALSE");
                 iTXt_node.setAttribute("compressionMethod",
                         iTXt_compressionMethod.get(i).toString());
                 iTXt_node.setAttribute("languageTag",
@@ -832,7 +825,7 @@
         }
 
         node = new IIOMetadataNode("BlackIsZero");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         chroma_node.appendChild(node);
 
         if (PLTE_present) {
@@ -894,7 +887,7 @@
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("Lossless");
-        node.setAttribute("value", "true");
+        node.setAttribute("value", "TRUE");
         compression_node.appendChild(node);
 
         node = new IIOMetadataNode("NumProgressiveScans");
@@ -1040,7 +1033,7 @@
             node.setAttribute("language",
                               iTXt_languageTag.get(i));
             if (iTXt_compressionFlag.get(i)) {
-                node.setAttribute("compression", "deflate");
+                node.setAttribute("compression", "zip");
             } else {
                 node.setAttribute("compression", "none");
             }
@@ -1052,7 +1045,7 @@
             node = new IIOMetadataNode("TextEntry");
             node.setAttribute("keyword", (String)zTXt_keyword.get(i));
             node.setAttribute("value", (String)zTXt_text.get(i));
-            node.setAttribute("compression", "deflate");
+            node.setAttribute("compression", "zip");
 
             text_node.appendChild(node);
         }
@@ -1162,12 +1155,13 @@
             }
         }
         String value = attr.getNodeValue();
-        if (value.equals("true")) {
+        // Allow lower case booleans for backward compatibility, #5082756
+        if (value.equals("TRUE") || value.equals("true")) {
             return true;
-        } else if (value.equals("false")) {
+        } else if (value.equals("FALSE") || value.equals("false")) {
             return false;
         } else {
-            fatal(node, "Attribute " + name + " must be 'true' or 'false'!");
+            fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
             return false;
         }
     }
@@ -1421,26 +1415,30 @@
                     }
 
                     String keyword = getAttribute(iTXt_node, "keyword");
-                    iTXt_keyword.add(keyword);
+                    if (isValidKeyword(keyword)) {
+                        iTXt_keyword.add(keyword);
 
-                    boolean compressionFlag =
-                        getBooleanAttribute(iTXt_node, "compressionFlag");
-                    iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
+                        boolean compressionFlag =
+                            getBooleanAttribute(iTXt_node, "compressionFlag");
+                        iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
 
-                    String compressionMethod =
-                        getAttribute(iTXt_node, "compressionMethod");
-                    iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
+                        String compressionMethod =
+                            getAttribute(iTXt_node, "compressionMethod");
+                        iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
 
-                    String languageTag =
-                        getAttribute(iTXt_node, "languageTag");
-                    iTXt_languageTag.add(languageTag);
+                        String languageTag =
+                            getAttribute(iTXt_node, "languageTag");
+                        iTXt_languageTag.add(languageTag);
 
-                    String translatedKeyword =
-                        getAttribute(iTXt_node, "translatedKeyword");
-                    iTXt_translatedKeyword.add(translatedKeyword);
+                        String translatedKeyword =
+                            getAttribute(iTXt_node, "translatedKeyword");
+                        iTXt_translatedKeyword.add(translatedKeyword);
 
-                    String text = getAttribute(iTXt_node, "text");
-                    iTXt_text.add(text);
+                        String text = getAttribute(iTXt_node, "text");
+                        iTXt_text.add(text);
+
+                    }
+                    // silently skip invalid text entry
 
                     iTXt_node = iTXt_node.getNextSibling();
                 }
@@ -1692,11 +1690,45 @@
         }
     }
 
-    private boolean isISOLatin(String s) {
+    /*
+     * Accrding to PNG spec, keywords are restricted to 1 to 79 bytes
+     * in length. Keywords shall contain only printable Latin-1 characters
+     * and spaces; To reduce the chances for human misreading of a keyword,
+     * leading spaces, trailing spaces, and consecutive spaces are not
+     * permitted in keywords.
+     *
+     * See: http://www.w3.org/TR/PNG/#11keywords
+     */
+    private boolean isValidKeyword(String s) {
+        int len = s.length();
+        if (len < 1 || len >= 80) {
+            return false;
+        }
+        if (s.startsWith(" ") || s.endsWith(" ") || s.contains("  ")) {
+            return false;
+        }
+        return isISOLatin(s, false);
+    }
+
+    /*
+     * According to PNG spec, keyword shall contain only printable
+     * Latin-1 [ISO-8859-1] characters and spaces; that is, only
+     * character codes 32-126 and 161-255 decimal are allowed.
+     * For Latin-1 value fields the 0x10 (linefeed) control
+     * character is aloowed too.
+     *
+     * See: http://www.w3.org/TR/PNG/#11keywords
+     */
+    private boolean isISOLatin(String s, boolean isLineFeedAllowed) {
         int len = s.length();
         for (int i = 0; i < len; i++) {
-            if (s.charAt(i) > 255) {
-                return false;
+            char c = s.charAt(i);
+            if (c < 32 || c > 255 || (c > 126 && c < 161)) {
+                // not printable. Check whether this is an allowed
+                // control char
+                if (!isLineFeedAllowed || c != 0x10) {
+                    return false;
+                }
             }
         }
         return true;
@@ -1929,19 +1961,22 @@
                 while (child != null) {
                     String childName = child.getNodeName();
                     if (childName.equals("TextEntry")) {
-                        String keyword = getAttribute(child, "keyword");
+                        String keyword =
+                            getAttribute(child, "keyword", "", false);
                         String value = getAttribute(child, "value");
-                        String encoding = getAttribute(child, "encoding");
-                        String language = getAttribute(child, "language");
+                        String language =
+                            getAttribute(child, "language", "", false);
                         String compression =
-                            getAttribute(child, "compression");
+                            getAttribute(child, "compression", "none", false);
 
-                        if (isISOLatin(value)) {
+                        if (!isValidKeyword(keyword)) {
+                            // Just ignore this node, PNG requires keywords
+                        } else if (isISOLatin(value, true)) {
                             if (compression.equals("zip")) {
                                 // Use a zTXt node
                                 zTXt_keyword.add(keyword);
                                 zTXt_text.add(value);
-                                zTXt_compressionMethod.add(new Integer(0));
+                                zTXt_compressionMethod.add(Integer.valueOf(0));
                             } else {
                                 // Use a tEXt node
                                 tEXt_keyword.add(keyword);
@@ -1998,14 +2033,14 @@
         sBIT_present = false;
         sPLT_present = false;
         sRGB_present = false;
-        tEXt_keyword = new ArrayList();
-        tEXt_text = new ArrayList();
+        tEXt_keyword = new ArrayList<String>();
+        tEXt_text = new ArrayList<String>();
         tIME_present = false;
         tRNS_present = false;
-        zTXt_keyword = new ArrayList();
-        zTXt_compressionMethod = new ArrayList();
-        zTXt_text = new ArrayList();
-        unknownChunkType = new ArrayList();
-        unknownChunkData = new ArrayList();
+        zTXt_keyword = new ArrayList<String>();
+        zTXt_compressionMethod = new ArrayList<Integer>();
+        zTXt_text = new ArrayList<String>();
+        unknownChunkType = new ArrayList<String>();
+        unknownChunkData = new ArrayList<byte[]>();
     }
 }
--- a/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Tue Apr 14 16:51:38 2009 +0100
@@ -94,6 +94,10 @@
                                  tgn != null;
                                  tg = tgn, tgn = tg.getParent());
                             streamCloser = new Thread(tg, streamCloserRunnable);
+                            /* Set context class loader to null in order to avoid
+                             * keeping a strong reference to an application classloader.
+                             */
+                            streamCloser.setContextClassLoader(null);
                             Runtime.getRuntime().addShutdownHook(streamCloser);
                             return null;
                         }
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Tue Apr 14 16:51:38 2009 +0100
@@ -22,7 +22,6 @@
  * CA 95054 USA or visit www.sun.com if you need additional information or
  * have any questions.
  */
-
 package com.sun.jmx.remote.internal;
 
 import java.io.IOException;
@@ -34,6 +33,7 @@
 import java.util.Map;
 import java.util.concurrent.Executor;
 
+import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import javax.security.auth.Subject;
@@ -54,6 +54,9 @@
 
 
 public abstract class ClientNotifForwarder {
+
+    private final AccessControlContext acc;
+ 
     public ClientNotifForwarder(Map<String, ?> env) {
         this(null, env);
     }
@@ -87,6 +90,8 @@
             this.command = command;
             if (thread == null) {
                 thread = new Thread() {
+
+                    @Override
                     public void run() {
                         while (true) {
                             Runnable r;
@@ -130,6 +135,7 @@
 
         this.defaultClassLoader = defaultClassLoader;
         this.executor = ex;
+        this.acc = AccessController.getContext();
     }
 
     /**
@@ -380,28 +386,85 @@
         setState(TERMINATED);
     }
 
-// -------------------------------------------------
-// private classes
-// -------------------------------------------------
+
+    // -------------------------------------------------
+    // private classes
+    // -------------------------------------------------
     //
+
     private class NotifFetcher implements Runnable {
+
+        private volatile boolean alreadyLogged = false;
+
+        private void logOnce(String msg, SecurityException x) {
+            if (alreadyLogged) return;
+            // Log only once.
+            logger.config("setContextClassLoader",msg);
+            if (x != null) logger.fine("setContextClassLoader", x);
+            alreadyLogged = true;
+        }
+
+        // Set new context class loader, returns previous one.
+        private final ClassLoader setContextClassLoader(final ClassLoader loader) {
+            final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
+            // if ctxt is null, log a config message and throw a
+            // SecurityException.
+            if (ctxt == null) {
+                logOnce("AccessControlContext must not be null.",null);
+                throw new SecurityException("AccessControlContext must not be null");
+            }
+            return AccessController.doPrivileged(
+                new PrivilegedAction<ClassLoader>() {
+                    public ClassLoader run() {
+                        try {
+                            // get context class loader - may throw
+                            // SecurityException - though unlikely.
+                            final ClassLoader previous =
+                                Thread.currentThread().getContextClassLoader();
+
+                            // if nothing needs to be done, break here...
+                            if (loader == previous) return previous;
+
+                            // reset context class loader - may throw
+                            // SecurityException
+                            Thread.currentThread().setContextClassLoader(loader);
+                            return previous;
+                        } catch (SecurityException x) {
+                            logOnce("Permission to set ContextClassLoader missing. " +
+                                    "Notifications will not be dispatched. " +
+                                    "Please check your Java policy configuration: " +
+                                    x, x);
+                            throw x;
+                        }
+                    }
+                }, ctxt);
+        }
+
         public void run() {
+            final ClassLoader previous;
+            if (defaultClassLoader != null) {
+                previous = setContextClassLoader(defaultClassLoader);
+            } else {
+                previous = null;
+            }
+            try {
+                doRun();
+            } finally {
+                if (defaultClassLoader != null) {
+                    setContextClassLoader(previous);
+                }
+            }
+        }
+
+        private void doRun() {
             synchronized (ClientNotifForwarder.this) {
                 currentFetchThread = Thread.currentThread();
 
-                if (state == STARTING)
+                if (state == STARTING) {
                     setState(STARTED);
+                }
             }
 
-            if (defaultClassLoader != null) {
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                        public Void run() {
-                            Thread.currentThread().
-                                setContextClassLoader(defaultClassLoader);
-                            return null;
-                        }
-                    });
-            }
 
             NotificationResult nr = null;
             if (!shouldStop() && (nr = fetchNotifs()) != null) {
@@ -434,8 +497,9 @@
                         // check if an mbean unregistration notif
                         if (!listenerID.equals(mbeanRemovedNotifID)) {
                             final ClientListenerInfo li = infoList.get(listenerID);
-                            if (li != null)
-                                listeners.put(listenerID,li);
+                            if (li != null) {
+                                listeners.put(listenerID, li);
+                            }
                             continue;
                         }
                         final Notification notif = tn.getNotification();
@@ -799,9 +863,7 @@
     private long clientSequenceNumber = -1;
     private final int maxNotifications;
     private final long timeout;
-
     private Integer mbeanRemovedNotifID = null;
-
     private Thread currentFetchThread;
 
     // state
--- a/src/share/classes/com/sun/jmx/remote/security/MBeanServerAccessController.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/jmx/remote/security/MBeanServerAccessController.java	Tue Apr 14 16:51:38 2009 +0100
@@ -111,6 +111,22 @@
      */
     protected abstract void checkWrite();
 
+    /**
+     * Check if the caller can create the named class.  The default
+     * implementation of this method calls {@link #checkWrite()}.
+     */
+    protected void checkCreate(String className) {
+        checkWrite();
+    }
+
+    /**
+     * Check if the caller can unregister the named MBean.  The default
+     * implementation of this method calls {@link #checkWrite()}.
+     */
+    protected void checkUnregister(ObjectName name) {
+        checkWrite();
+    }
+
     //--------------------------------------------
     //--------------------------------------------
     //
@@ -148,7 +164,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className, ObjectName name)
@@ -158,7 +174,7 @@
         MBeanRegistrationException,
         MBeanException,
         NotCompliantMBeanException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className);
@@ -170,7 +186,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className, ObjectName name,
@@ -181,7 +197,7 @@
         MBeanRegistrationException,
         MBeanException,
         NotCompliantMBeanException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -196,7 +212,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className,
@@ -209,7 +225,7 @@
         MBeanException,
         NotCompliantMBeanException,
         InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -222,7 +238,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className,
@@ -237,7 +253,7 @@
         MBeanException,
         NotCompliantMBeanException,
         InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -394,45 +410,45 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className)
         throws ReflectionException, MBeanException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className,
                               Object params[],
                               String signature[])
         throws ReflectionException, MBeanException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, params, signature);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className, ObjectName loaderName)
         throws ReflectionException, MBeanException, InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, loaderName);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className, ObjectName loaderName,
                               Object params[], String signature[])
         throws ReflectionException, MBeanException, InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, loaderName,
                                             params, signature);
     }
@@ -579,12 +595,12 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkUnregister()</code>, then forward this method to the
      * wrapped object.
      */
     public void unregisterMBean(ObjectName name)
         throws InstanceNotFoundException, MBeanRegistrationException {
-        checkWrite();
+        checkUnregister(name);
         getMBeanServer().unregisterMBean(name);
     }
 
--- a/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java	Tue Apr 14 16:51:38 2009 +0100
@@ -31,11 +31,17 @@
 import java.security.AccessController;
 import java.security.Principal;
 import java.security.PrivilegedAction;
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
 import javax.management.MBeanServer;
+import javax.management.ObjectName;
 import javax.security.auth.Subject;
 
 /**
@@ -46,7 +52,8 @@
  * not allowed; in this case the request is not forwarded to the
  * wrapped object.</p>
  *
- * <p>This class implements the {@link #checkRead()} and {@link #checkWrite()}
+ * <p>This class implements the {@link #checkRead()}, {@link #checkWrite()},
+ * {@link #checkCreate(String)}, and {@link #checkUnregister(ObjectName)}
  * methods based on an access level properties file containing username/access
  * level pairs. The set of username/access level pairs is passed either as a
  * filename which denotes a properties file on disk, or directly as an instance
@@ -56,14 +63,50 @@
  * has exactly one access level. The same access level can be shared by several
  * usernames.</p>
  *
- * <p>The supported access level values are <i>readonly</i> and
- * <i>readwrite</i>.</p>
+ * <p>The supported access level values are {@code readonly} and
+ * {@code readwrite}.  The {@code readwrite} access level can be
+ * qualified by one or more <i>clauses</i>, where each clause looks
+ * like <code>create <i>classNamePattern</i></code> or {@code
+ * unregister}.  For example:</p>
+ * 
+ * <pre>
+ * monitorRole  readonly
+ * controlRole  readwrite \
+ *              create javax.management.timer.*,javax.management.monitor.* \
+ *              unregister
+ * </pre>
+ * 
+ * <p>(The continuation lines with {@code \} come from the parser for
+ * Properties files.)</p>
  */
 public class MBeanServerFileAccessController
     extends MBeanServerAccessController {
 
-    public static final String READONLY = "readonly";
-    public static final String READWRITE = "readwrite";
+    static final String READONLY = "readonly";
+    static final String READWRITE = "readwrite";
+
+    static final String CREATE = "create";
+    static final String UNREGISTER = "unregister";
+
+    private enum AccessType {READ, WRITE, CREATE, UNREGISTER};
+
+    private static class Access {
+        final boolean write;
+        final String[] createPatterns;
+        private boolean unregister;
+
+        Access(boolean write, boolean unregister, List<String> createPatternList) {
+            this.write = write;
+            int npats = (createPatternList == null) ? 0 : createPatternList.size();
+            if (npats == 0)
+                this.createPatterns = NO_STRINGS;
+            else
+                this.createPatterns = createPatternList.toArray(new String[npats]);
+            this.unregister = unregister;
+        }
+
+        private final String[] NO_STRINGS = new String[0];
+    }
 
     /**
      * <p>Create a new MBeanServerAccessController that forwards all the
@@ -87,8 +130,8 @@
         throws IOException {
         super();
         this.accessFileName = accessFileName;
-        props = propertiesFromFile(accessFileName);
-        checkValues(props);
+        Properties props = propertiesFromFile(accessFileName);
+        parseProperties(props);
     }
 
     /**
@@ -123,14 +166,14 @@
      * #setMBeanServer} method after doing access checks based on read and
      * write permissions.</p>
      *
-     * <p>This instance is initialized from the specified properties instance.
-     * This constructor makes a copy of the properties instance using its
-     * <code>clone</code> method and it is the copy that is consulted to check
-     * the username and access level of an incoming connection. The original
-     * properties object can be modified without affecting the copy. If the
-     * {@link #refresh} method is then called, the
-     * <code>MBeanServerFileAccessController</code> will make a new copy of the
-     * properties object at that time.</p>
+     * <p>This instance is initialized from the specified properties
+     * instance.  This constructor makes a copy of the properties
+     * instance and it is the copy that is consulted to check the
+     * username and access level of an incoming connection. The
+     * original properties object can be modified without affecting
+     * the copy. If the {@link #refresh} method is then called, the
+     * <code>MBeanServerFileAccessController</code> will make a new
+     * copy of the properties object at that time.</p>
      *
      * @param accessFileProps properties list containing the username/access
      * level entries.
@@ -145,8 +188,7 @@
         if (accessFileProps == null)
             throw new IllegalArgumentException("Null properties");
         originalProps = accessFileProps;
-        props = (Properties) accessFileProps.clone();
-        checkValues(props);
+        parseProperties(accessFileProps);
     }
 
     /**
@@ -155,14 +197,14 @@
      * #setMBeanServer} method after doing access checks based on read and
      * write permissions.</p>
      *
-     * <p>This instance is initialized from the specified properties instance.
-     * This constructor makes a copy of the properties instance using its
-     * <code>clone</code> method and it is the copy that is consulted to check
-     * the username and access level of an incoming connection. The original
-     * properties object can be modified without affecting the copy. If the
-     * {@link #refresh} method is then called, the
-     * <code>MBeanServerFileAccessController</code> will make a new copy of the
-     * properties object at that time.</p>
+     * <p>This instance is initialized from the specified properties
+     * instance.  This constructor makes a copy of the properties
+     * instance and it is the copy that is consulted to check the
+     * username and access level of an incoming connection. The
+     * original properties object can be modified without affecting
+     * the copy. If the {@link #refresh} method is then called, the
+     * <code>MBeanServerFileAccessController</code> will make a new
+     * copy of the properties object at that time.</p>
      *
      * @param accessFileProps properties list containing the username/access
      * level entries.
@@ -184,16 +226,36 @@
      * Check if the caller can do read operations. This method does
      * nothing if so, otherwise throws SecurityException.
      */
+    @Override
     public void checkRead() {
-        checkAccessLevel(READONLY);
+        checkAccess(AccessType.READ, null);
     }
 
     /**
      * Check if the caller can do write operations.  This method does
      * nothing if so, otherwise throws SecurityException.
      */
+    @Override
     public void checkWrite() {
-        checkAccessLevel(READWRITE);
+        checkAccess(AccessType.WRITE, null);
+    }
+
+    /**
+     * Check if the caller can create MBeans or instances of the given class.
+     * This method does nothing if so, otherwise throws SecurityException.
+     */
+    @Override
+    public void checkCreate(String className) {
+        checkAccess(AccessType.CREATE, className);
+    }
+
+    /**
+     * Check if the caller can do unregister operations.  This method does
+     * nothing if so, otherwise throws SecurityException.
+     */
+    @Override
+    public void checkUnregister(ObjectName name) {
+        checkAccess(AccessType.UNREGISTER, null);
     }
 
     /**
@@ -218,14 +280,13 @@
      * @exception IllegalArgumentException if any of the supplied access
      * level values differs from "readonly" or "readwrite".
      */
-    public void refresh() throws IOException {
-        synchronized (props) {
-            if (accessFileName == null)
-                props = (Properties) originalProps.clone();
-            else
-                props = propertiesFromFile(accessFileName);
-            checkValues(props);
-        }
+    public synchronized void refresh() throws IOException {
+        Properties props;
+        if (accessFileName == null)
+            props = (Properties) originalProps;
+        else
+            props = propertiesFromFile(accessFileName);
+        parseProperties(props);
     }
 
     private static Properties propertiesFromFile(String fname)
@@ -234,13 +295,15 @@
         try {
             Properties p = new Properties();
             p.load(fin);
+	    // Properties.load does a buffered read so we don't need to wrap
+	    // the FileInputStream in a BufferedInputStream.
             return p;
         } finally {
             fin.close();
         }
     }
 
-    private void checkAccessLevel(String accessLevel) {
+    private synchronized void checkAccess(AccessType requiredAccess, String arg) {
         final AccessControlContext acc = AccessController.getContext();
         final Subject s =
             AccessController.doPrivileged(new PrivilegedAction<Subject>() {
@@ -250,38 +313,233 @@
                 });
         if (s == null) return; /* security has not been enabled */
         final Set<Principal> principals = s.getPrincipals();
+        String newPropertyValue = null;
         for (Principal p : principals) {
-            String grantedAccessLevel;
-            synchronized (props) {
-                grantedAccessLevel = props.getProperty(p.getName());
-            }
-            if (grantedAccessLevel != null) {
-                if (accessLevel.equals(READONLY) &&
-                    (grantedAccessLevel.equals(READONLY) ||
-                     grantedAccessLevel.equals(READWRITE)))
-                    return;
-                if (accessLevel.equals(READWRITE) &&
-                    grantedAccessLevel.equals(READWRITE))
+            Access access = accessMap.get(p.getName());
+            if (access != null) {
+                boolean ok;
+                switch (requiredAccess) {
+                    case READ:
+                        ok = true;  // all access entries imply read
+                        break;
+                    case WRITE:
+                        ok = access.write;
+                        break;
+                    case UNREGISTER:
+                        ok = access.unregister;
+                        if (!ok && access.write)
+                            newPropertyValue = "unregister";
+                         break;
+                    case CREATE:
+                        ok = checkCreateAccess(access, arg);
+                        if (!ok && access.write)
+                            newPropertyValue = "create " + arg;
+                        break;
+                    default:
+                        throw new AssertionError();
+                }
+                if (ok)
                     return;
             }
         }
-        throw new SecurityException("Access denied! Invalid access level for " +
-                                    "requested MBeanServer operation.");
+        SecurityException se = new SecurityException("Access denied! Invalid " +
+                "access level for requested MBeanServer operation.");
+        // Add some more information to help people with deployments that
+        // worked before we required explicit create clauses. We're not giving
+        // any information to the bad guys, other than that the access control
+        // is based on a file, which they could have worked out from the stack
+        // trace anyway.
+        if (newPropertyValue != null) {
+            SecurityException se2 = new SecurityException("Access property " +
+                    "for this identity should be similar to: " + READWRITE +
+                    " " + newPropertyValue);
+            se.initCause(se2);
+        }
+        throw se;
     }
 
-    private void checkValues(Properties props) {
-        Collection<?> c = props.values();
-        for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
-            final String accessLevel = (String) i.next();
-            if (!accessLevel.equals(READONLY) &&
-                !accessLevel.equals(READWRITE)) {
-                throw new IllegalArgumentException(
-                    "Syntax error in access level entry [" + accessLevel + "]");
-            }
+    private static boolean checkCreateAccess(Access access, String className) {
+        for (String classNamePattern : access.createPatterns) {
+            if (classNameMatch(classNamePattern, className))
+                return true;
+        }
+        return false;
+    }
+
+    private static boolean classNameMatch(String pattern, String className) {
+        // We studiously avoided regexes when parsing the properties file,
+        // because that is done whenever the VM is started with the
+        // appropriate -Dcom.sun.management options, even if nobody ever
+        // creates an MBean.  We don't want to incur the overhead of loading
+        // all the regex code whenever those options are specified, but if we
+        // get as far as here then the VM is already running and somebody is
+        // doing the very unusual operation of remotely creating an MBean.
+        // Because that operation is so unusual, we don't try to optimize
+        // by hand-matching or by caching compiled Pattern objects.
+        StringBuilder sb = new StringBuilder();
+        StringTokenizer stok = new StringTokenizer(pattern, "*", true);
+        while (stok.hasMoreTokens()) {
+            String tok = stok.nextToken();
+            if (tok.equals("*"))
+                sb.append("[^.]*");
+            else
+                sb.append(Pattern.quote(tok));
+        }
+        return className.matches(sb.toString());
+    }
+
+    private void parseProperties(Properties props) {
+        this.accessMap = new HashMap<String, Access>();
+        for (Map.Entry<Object, Object> entry : props.entrySet()) {
+            String identity = (String) entry.getKey();
+            String accessString = (String) entry.getValue();
+            Access access = Parser.parseAccess(identity, accessString);
+            accessMap.put(identity, access);
         }
     }
 
-    private Properties props;
+    private static class Parser {
+        private final static int EOS = -1;  // pseudo-codepoint "end of string"
+        static {
+            assert !Character.isWhitespace(EOS);
+        }
+
+        private final String identity;  // just for better error messages
+        private final String s;  // the string we're parsing
+        private final int len;   // s.length()
+        private int i;
+        private int c;
+        // At any point, either c is s.codePointAt(i), or i == len and
+        // c is EOS.  We use int rather than char because it is conceivable
+        // (if unlikely) that a classname in a create clause might contain
+        // "supplementary characters", the ones that don't fit in the original
+        // 16 bits for Unicode.
+
+        private Parser(String identity, String s) {
+            this.identity = identity;
+            this.s = s;
+            this.len = s.length();
+            this.i = 0;
+            if (i < len)
+                this.c = s.codePointAt(i);
+            else
+                this.c = EOS;
+        }
+
+        static Access parseAccess(String identity, String s) {
+            return new Parser(identity, s).parseAccess();
+        }
+
+        private Access parseAccess() {
+            skipSpace();
+            String type = parseWord();
+            Access access;
+            if (type.equals(READONLY))
+                access = new Access(false, false, null);
+            else if (type.equals(READWRITE))
+                access = parseReadWrite();
+            else {
+                throw syntax("Expected " + READONLY + " or " + READWRITE +
+                        ": " + type);
+            }
+            if (c != EOS)
+                throw syntax("Extra text at end of line");
+            return access;
+        }
+
+        private Access parseReadWrite() {
+            List<String> createClasses = new ArrayList<String>();
+            boolean unregister = false;
+            while (true) {
+                skipSpace();
+                if (c == EOS)
+                    break;
+                String type = parseWord();
+                if (type.equals(UNREGISTER))
+                    unregister = true;
+                else if (type.equals(CREATE))
+                    parseCreate(createClasses);
+                else
+                    throw syntax("Unrecognized keyword " + type);
+            }
+            return new Access(true, unregister, createClasses);
+        }
+
+        private void parseCreate(List<String> createClasses) {
+            while (true) {
+                skipSpace();
+                createClasses.add(parseClassName());
+                skipSpace();
+                if (c == ',')
+                    next();
+                else
+                    break;
+            }
+        }
+
+        private String parseClassName() {
+            // We don't check that classname components begin with suitable
+            // characters (so we accept 1.2.3 for example).  This means that
+            // there are only two states, which we can call dotOK and !dotOK
+            // according as a dot (.) is legal or not.  Initially we're in
+            // !dotOK since a classname can't start with a dot; after a dot
+            // we're in !dotOK again; and after any other characters we're in
+            // dotOK.  The classname is only accepted if we end in dotOK,
+            // so we reject an empty name or a name that ends with a dot.
+            final int start = i;
+            boolean dotOK = false;
+            while (true) {
+                if (c == '.') {
+                    if (!dotOK)
+                        throw syntax("Bad . in class name");
+                    dotOK = false;
+                } else if (c == '*' || Character.isJavaIdentifierPart(c))
+                    dotOK = true;
+                else
+                    break;
+                next();
+            }
+            String className = s.substring(start, i);
+            if (!dotOK)
+                throw syntax("Bad class name " + className);
+            return className;
+        }
+
+        // Advance c and i to the next character, unless already at EOS.
+        private void next() {
+            if (c != EOS) {
+                i += Character.charCount(c);
+                if (i < len)
+                    c = s.codePointAt(i);
+                else
+                    c = EOS;
+            }
+        }
+
+        private void skipSpace() {
+            while (Character.isWhitespace(c))
+                next();
+        }
+
+        private String parseWord() {
+            skipSpace();
+            if (c == EOS)
+                throw syntax("Expected word at end of line");
+            final int start = i;
+            while (c != EOS && !Character.isWhitespace(c))
+                next();
+            String word = s.substring(start, i);
+            skipSpace();
+            return word;
+        }
+
+        private IllegalArgumentException syntax(String msg) {
+            return new IllegalArgumentException(
+                    msg + " [" + identity + " " + s + "]");
+        }
+    }
+
+    private Map<String, Access> accessMap;
     private Properties originalProps;
     private String accessFileName;
 }
--- a/src/share/classes/com/sun/jndi/ldap/LdapCtx.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/jndi/ldap/LdapCtx.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -302,7 +302,16 @@
 
         schemaTrees = new Hashtable(11, 0.75f);
         initEnv();
-        connect(false);
+        try {
+            connect(false);
+        } catch (NamingException e) {
+            try {
+                close();
+            } catch (Exception e2) {
+                // Nothing
+            }
+            throw e;
+        }
     }
 
     LdapCtx(LdapCtx existing, String newDN) throws NamingException {
--- a/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,12 +33,33 @@
 
 final class VersionHelper12 extends VersionHelper {
 
+    // System property to control whether classes may be loaded from an
+    // arbitrary URL code base.
+    private static final String TRUST_URL_CODEBASE_PROPERTY =
+        "com.sun.jndi.ldap.object.trustURLCodebase";
+
+    // Determine whether classes may be loaded from an arbitrary URL code base.
+    private static final String trustURLCodebase =
+        AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
+                            "false");
+                }
+            }
+        );
+
     VersionHelper12() {} // Disallow external from creating one of these.
 
     ClassLoader getURLClassLoader(String[] url)
         throws MalformedURLException {
             ClassLoader parent = getContextClassLoader();
-            if (url != null) {
+            /*
+             * Classes may only be loaded from an arbitrary URL code base when
+             * the system property com.sun.jndi.ldap.object.trustURLCodebase
+             * has been set to "true".
+             */
+            if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) {
                 return URLClassLoader.newInstance(getUrlArray(url), parent);
             } else {
                 return parent;
--- a/src/share/classes/java/awt/Font.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/awt/Font.java	Tue Apr 14 16:51:38 2009 +0100
@@ -37,6 +37,8 @@
 import java.awt.peer.FontPeer;
 import java.io.*;
 import java.lang.ref.SoftReference;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
 import java.text.AttributedCharacterIterator.Attribute;
 import java.text.CharacterIterator;
 import java.text.StringCharacterIterator;
@@ -51,6 +53,7 @@
 import sun.font.AttributeValues;
 import sun.font.EAttribute;
 import sun.font.CompositeFont;
+import sun.font.CreatedFontTracker;
 import sun.font.Font2D;
 import sun.font.Font2DHandle;
 import sun.font.FontManager;
@@ -575,14 +578,16 @@
     }
 
     /* used to implement Font.createFont */
-    private Font(File fontFile, int fontFormat, boolean isCopy)
+    private Font(File fontFile, int fontFormat,
+                 boolean isCopy, CreatedFontTracker tracker)
         throws FontFormatException {
         this.createdFont = true;
         /* Font2D instances created by this method track their font file
          * so that when the Font2D is GC'd it can also remove the file.
          */
         this.font2DHandle =
-            FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
+            FontManager.createFont2D(fontFile, fontFormat,
+                                     isCopy, tracker).handle;
         this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
         this.style = Font.PLAIN;
         this.size = 1;
@@ -788,6 +793,29 @@
     }
 
     /**
+     * Used with the byte count tracker for fonts created from streams.
+     * If a thread can create temp files anyway, no point in counting
+     * font bytes.
+     */
+    private static boolean hasTempPermission() {
+
+        if (System.getSecurityManager() == null) {
+            return true;
+        }
+        File f = null;
+        boolean hasPerm = false;
+        try {
+            f = File.createTempFile("+~JT", ".tmp", null);
+            f.delete();
+            f = null;
+            hasPerm = true;
+        } catch (Throwable t) {
+            /* inc. any kind of SecurityException */
+        }
+        return hasPerm;
+    }
+
+    /**
      * Returns a new <code>Font</code> using the specified font type
      * and input data.  The new <code>Font</code> is
      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
@@ -822,58 +850,96 @@
             fontFormat != Font.TYPE1_FONT) {
             throw new IllegalArgumentException ("font format not recognized");
         }
-        final InputStream fStream = fontStream;
-        Object ret = java.security.AccessController.doPrivileged(
-           new java.security.PrivilegedAction() {
-              public Object run() {
-                  File tFile = null;
-                  FileOutputStream outStream = null;
-                  try {
-                      tFile = File.createTempFile("+~JF", ".tmp", null);
-                      /* Temp file deleted by font shutdown hook */
-                      BufferedInputStream inStream =
-                          new BufferedInputStream(fStream);
-                      outStream = new FileOutputStream(tFile);
-                      int bytesRead = 0;
-                      int bufSize = 8192;
-                      byte [] buf = new byte[bufSize];
-                      while (bytesRead != -1) {
-                          try {
-                              bytesRead = inStream.read(buf, 0, bufSize);
-                          } catch (Throwable t) {
-                              throw new IOException();
-                          }
-                          if (bytesRead != -1) {
-                              outStream.write(buf, 0, bytesRead);
-                          }
-                      }
-                      /* don't close the input stream */
-                      outStream.close();
-                  } catch (IOException e) {
-                      if (outStream != null) {
-                          try {
-                              outStream.close();
-                          } catch (Exception e1) {
-                          }
-                      }
-                      if (tFile != null) {
-                          try {
-                              tFile.delete();
-                          }  catch (Exception e2) {
-                          }
-                      }
-                      return e;
-                  }
-                  return tFile;
-              }
-          });
+        boolean copiedFontData = false;
 
-        if (ret instanceof File) {
-            return new Font((File)ret, fontFormat, true);
-        } else if (ret instanceof IOException) {
-            throw (IOException)ret;
-        } else {
-            throw new FontFormatException("Couldn't access font stream");
+        try {
+            final File tFile = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<File>() {
+                    public File run() throws IOException {
+                        return File.createTempFile("+~JF", ".tmp", null);
+                    }
+                }
+            );
+
+            int totalSize = 0;
+            CreatedFontTracker tracker = null;
+            try {
+                final OutputStream outStream =
+                    AccessController.doPrivileged(
+                        new PrivilegedExceptionAction<OutputStream>() {
+                            public OutputStream run() throws IOException {
+                                return new FileOutputStream(tFile);
+                            }
+                        }
+                    );
+                if (!hasTempPermission()) {
+                    tracker = CreatedFontTracker.getTracker();
+                }
+                try {
+                    byte[] buf = new byte[8192]; 
+                    for (;;) {
+                        int bytesRead = fontStream.read(buf);
+                        if (bytesRead < 0) {
+                            break;
+                        }
+                        if (tracker != null) {
+                            if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
+                                throw new IOException("File too big.");
+                            }
+                            if (totalSize+tracker.getNumBytes() >
+                                tracker.MAX_TOTAL_BYTES)
+                              {
+                                throw new IOException("Total files too big.");
+                            }
+                            totalSize += bytesRead;
+                            tracker.addBytes(bytesRead);
+                        }
+                        outStream.write(buf, 0, bytesRead);
+                    }
+                    /* don't close the input stream */
+                } finally {
+                    outStream.close();
+                }
+                /* After all references to a Font2D are dropped, the file
+                 * will be removed. To support long-lived AppContexts,
+                 * we need to then decrement the byte count by the size
+                 * of the file.
+                 * If the data isn't a valid font, the implementation will
+                 * delete the tmp file and decrement the byte count
+                 * in the tracker object before returning from the
+                 * constructor, so we can set 'copiedFontData' to true here
+                 * without waiting for the results of that constructor.
+                 */
+                copiedFontData = true;
+                Font font = new Font(tFile, fontFormat, true, tracker);
+                return font;
+            } finally {
+                if (!copiedFontData) {
+                    if (tracker != null) {
+                        tracker.subBytes(totalSize);
+                    }
+                    AccessController.doPrivileged(
+                        new PrivilegedExceptionAction<Void>() {
+                            public Void run() {
+                                tFile.delete();
+                                return null;
+                            }
+                        }
+                    );
+                }
+            }
+        } catch (Throwable t) {
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            }
+            if (t instanceof IOException) {
+                throw (IOException)t;
+            }
+            Throwable cause = t.getCause();
+            if (cause instanceof FontFormatException) {
+                throw (FontFormatException)cause;
+            }
+            throw new IOException("Problem reading font data.");
         }
     }
 
@@ -913,6 +979,9 @@
      */
     public static Font createFont(int fontFormat, File fontFile)
         throws java.awt.FontFormatException, java.io.IOException {
+
+        fontFile = new File(fontFile.getPath());
+
         if (fontFormat != Font.TRUETYPE_FONT &&
             fontFormat != Font.TYPE1_FONT) {
             throw new IllegalArgumentException ("font format not recognized");
@@ -926,7 +995,7 @@
         if (!fontFile.canRead()) {
             throw new IOException("Can't read " + fontFile);
         }
-        return new Font(fontFile, fontFormat, false);
+        return new Font(fontFile, fontFormat, false, null);
     }
 
     /**
--- a/src/share/classes/java/awt/GraphicsEnvironment.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/awt/GraphicsEnvironment.java	Tue Apr 14 16:51:38 2009 +0100
@@ -356,6 +356,9 @@
      * @since 1.5
      */
     public void preferLocaleFonts() {
+        if (!(this instanceof SunGraphicsEnvironment)) {
+            return;
+        }
         sun.font.FontManager.preferLocaleFonts();
     }
 
@@ -376,6 +379,9 @@
      * @since 1.5
      */
     public void preferProportionalFonts() {
+        if (!(this instanceof SunGraphicsEnvironment)) {
+            return;
+        }
         sun.font.FontManager.preferProportionalFonts();
     }
 
--- a/src/share/classes/java/awt/color/ICC_Profile.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/awt/color/ICC_Profile.java	Tue Apr 14 16:51:38 2009 +0100
@@ -737,7 +737,7 @@
     ICC_Profile(ProfileDeferralInfo pdi) {
         this.deferralInfo = pdi;
         this.profileActivator = new ProfileActivator() {
-            public void activate() {
+            public void activate() throws ProfileDataException {
                 activateDeferredProfile();
             }
         };
@@ -830,20 +830,16 @@
         case ColorSpace.CS_sRGB:
             synchronized(ICC_Profile.class) {
                 if (sRGBprofile == null) {
-                    try {
-                        /*
-                         * Deferral is only used for standard profiles.
-                         * Enabling the appropriate access privileges is handled
-                         * at a lower level.
-                         */
-                        sRGBprofile = getDeferredInstance(
-                            new ProfileDeferralInfo("sRGB.pf",
-                                                    ColorSpace.TYPE_RGB,
-                                                    3, CLASS_DISPLAY));
-                    } catch (IOException e) {
-                        throw new IllegalArgumentException(
-                              "Can't load standard profile: sRGB.pf");
-                    }
+                    /*
+                     * Deferral is only used for standard profiles.
+                     * Enabling the appropriate access privileges is handled
+                     * at a lower level.
+                     */
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("sRGB.pf",
+                                                ColorSpace.TYPE_RGB, 3,
+                                                CLASS_DISPLAY);
+                    sRGBprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = sRGBprofile;
             }
@@ -853,7 +849,11 @@
         case ColorSpace.CS_CIEXYZ:
             synchronized(ICC_Profile.class) {
                 if (XYZprofile == null) {
-                    XYZprofile = getStandardProfile("CIEXYZ.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("CIEXYZ.pf",
+                                                ColorSpace.TYPE_XYZ, 3,
+                                                CLASS_DISPLAY);
+                    XYZprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = XYZprofile;
             }
@@ -863,7 +863,11 @@
         case ColorSpace.CS_PYCC:
             synchronized(ICC_Profile.class) {
                 if (PYCCprofile == null) {
-                    PYCCprofile = getStandardProfile("PYCC.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("PYCC.pf",
+                                                ColorSpace.TYPE_3CLR, 3,
+                                                CLASS_DISPLAY);
+                    PYCCprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = PYCCprofile;
             }
@@ -873,7 +877,11 @@
         case ColorSpace.CS_GRAY:
             synchronized(ICC_Profile.class) {
                 if (GRAYprofile == null) {
-                    GRAYprofile = getStandardProfile("GRAY.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("GRAY.pf",
+                                                ColorSpace.TYPE_GRAY, 1,
+                                                CLASS_DISPLAY);
+                    GRAYprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = GRAYprofile;
             }
@@ -883,7 +891,11 @@
         case ColorSpace.CS_LINEAR_RGB:
             synchronized(ICC_Profile.class) {
                 if (LINEAR_RGBprofile == null) {
-                    LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf");
+                    ProfileDeferralInfo pInfo =
+                        new ProfileDeferralInfo("LINEAR_RGB.pf",
+                                                ColorSpace.TYPE_RGB, 3,
+                                                CLASS_DISPLAY);
+                    LINEAR_RGBprofile = getDeferredInstance(pInfo);
                 }
                 thisProfile = LINEAR_RGBprofile;
             }
@@ -1047,9 +1059,7 @@
      * code will take care of access privileges.
      * @see activateDeferredProfile()
      */
-    static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi)
-        throws IOException {
-
+    static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
         if (!ProfileDeferralMgr.deferring) {
             return getStandardProfile(pdi.filename);
         }
@@ -1063,33 +1073,37 @@
     }
 
 
-    void activateDeferredProfile() {
-    byte profileData[];
-    FileInputStream fis;
-    String fileName = deferralInfo.filename;
+    void activateDeferredProfile() throws ProfileDataException {
+        byte profileData[];
+        FileInputStream fis;
+        String fileName = deferralInfo.filename;
 
         profileActivator = null;
         deferralInfo = null;
         if ((fis = openProfile(fileName)) == null) {
-            throw new IllegalArgumentException("Cannot open file " + fileName);
+            throw new ProfileDataException("Cannot open file " + fileName);
         }
         try {
             profileData = getProfileDataFromStream(fis);
             fis.close();    /* close the file */
         }
         catch (IOException e) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
-                fileName);
+            ProfileDataException pde = new
+                ProfileDataException("Invalid ICC Profile Data" + fileName);
+            pde.initCause(e);
+            throw pde;
         }
         if (profileData == null) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
+            throw new ProfileDataException("Invalid ICC Profile Data" +
                 fileName);
         }
         try {
             ID = CMSManager.getModule().loadProfile(profileData);
         } catch (CMMException c) {
-            throw new IllegalArgumentException("Invalid ICC Profile Data" +
-                fileName);
+            ProfileDataException pde = new
+                ProfileDataException("Invalid ICC Profile Data" + fileName);
+            pde.initCause(c);
+            throw pde;
         }
     }
 
--- a/src/share/classes/java/lang/Class.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/Class.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1994-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1994-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2846,14 +2846,14 @@
         if (loader == null)
             return desiredAssertionStatus0(this);
 
-        synchronized(loader) {
-            // If the classloader has been initialized with
-            // the assertion directives, ask it. Otherwise,
-            // ask the VM.
-            return (loader.classAssertionStatus == null ?
-                    desiredAssertionStatus0(this) :
-                    loader.desiredAssertionStatus(getName()));
+        // If the classloader has been initialized with the assertion
+        // directives, ask it. Otherwise, ask the VM.
+        synchronized(loader.assertionLock) {
+            if (loader.classAssertionStatus != null) {
+                return loader.desiredAssertionStatus(getName());
+            }
         }
+        return desiredAssertionStatus0(this);
     }
 
     // Retrieves the desired assertion status of this class from the VM
--- a/src/share/classes/java/lang/ClassLoader.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/ClassLoader.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1994-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1994-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,14 +40,17 @@
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
+import java.util.Collections;
 import java.util.Enumeration;
-import java.util.Hashtable;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.Stack;
 import java.util.Map;
 import java.util.Vector;
+import java.util.Hashtable;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
 import sun.misc.ClassFileTransformer;
 import sun.misc.CompoundEnumeration;
 import sun.misc.Resource;
@@ -91,6 +94,17 @@
  * called the "bootstrap class loader", does not itself have a parent but may
  * serve as the parent of a <tt>ClassLoader</tt> instance.
  *
+ * <p> Class loaders that support concurrent loading of classes are known as
+ * <em>parallel capable</em> class loaders and are required to register
+ * themselves at their class initialization time by invoking the
+ * {@link
+ * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
+ * method. In environments in which the delegation model is not strictly
+ * hierarchical, class loaders need to be parallel capable, otherise class
+ * loading can lead to deadlocks because the loader lock is held for the
+ * duration of the class loading process (see {@link #loadClass
+ * <tt>loadClass</tt>} methods).
+ *
  * <p> Normally, the Java virtual machine loads classes from the local file
  * system in a platform-dependent manner.  For example, on UNIX systems, the
  * virtual machine loads classes from the directory defined by the
@@ -160,31 +174,51 @@
 public abstract class ClassLoader {
 
     private static native void registerNatives();
+
+    // Set of classes which are registered as parallel capable class loaders
+    private static final Set<Class<? extends ClassLoader>> parallelLoaders
+        = Collections.newSetFromMap(Collections.synchronizedMap
+              (new WeakHashMap<Class<? extends ClassLoader>, Boolean>()));
+
     static {
         registerNatives();
+        parallelLoaders.add(ClassLoader.class);
     }
 
     // If initialization succeed this is set to true and security checks will
     // succeed.  Otherwise the object is not initialized and the object is
     // useless.
-    private boolean initialized = false;
+    private final boolean initialized;
 
     // The parent class loader for delegation
-    private ClassLoader parent;
+    // Note: VM hardcoded the offset of this field, thus all new fields
+    // must be added *after* it.
+    private final ClassLoader parent;
+
+    // Maps class name to the corresponding lock object when the current
+    // class loader is parallel capable.
+    // Note: VM also uses this field to decide if the current class loader
+    // is parallel capable and the appropriate lock object for class loading.
+    private final ConcurrentHashMap<String, Object> parallelLockMap;
 
     // Hashtable that maps packages to certs
-    private Hashtable<String, Certificate[]> package2certs
-        = new Hashtable<String, Certificate[]>(11);
+    private final Map <String, Certificate[]> package2certs;
 
     // Shared among all packages with unsigned classes
-    Certificate[] nocerts;
+    private static final Certificate[] nocerts = new Certificate[0];
 
-    // The classes loaded by this class loader.  The only purpose of this table
+    // The classes loaded by this class loader. The only purpose of this table
     // is to keep the classes from being GC'ed until the loader is GC'ed.
-    private Vector<Class<?>> classes = new Vector<Class<?>>();
+    private final Vector<Class<?>> classes = new Vector<Class<?>>();
+
+    // The "default" domain. Set as the default ProtectionDomain on newly
+    // created classes.
+    private final ProtectionDomain defaultDomain =
+        new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
+                             null, this, null);
 
     // The initiating protection domains for all classes loaded by this loader
-    private Set<ProtectionDomain> domains = new HashSet<ProtectionDomain>();
+    private final Set<ProtectionDomain> domains;
 
     // Invoked by the VM to record every loaded class with this loader.
     void addClass(Class c) {
@@ -193,7 +227,9 @@
 
     // The packages defined in this class loader.  Each package name is mapped
     // to its corresponding Package object.
-    private HashMap<String, Package> packages = new HashMap<String, Package>();
+    // @GuardedBy("itself")
+    private final HashMap<String, Package> packages =
+        new HashMap<String, Package>();
 
     /**
      * Creates a new class loader using the specified parent class loader for
@@ -220,6 +256,19 @@
             security.checkCreateClassLoader();
         }
         this.parent = parent;
+        if (parallelLoaders.contains(this.getClass())) {
+            parallelLockMap = new ConcurrentHashMap<String, Object>();
+            package2certs = new ConcurrentHashMap<String, Certificate[]>();
+            domains =
+                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
+            assertionLock = new Object();
+        } else {
+            // no finer-grained lock; lock on the classloader instance
+            parallelLockMap = null;
+            package2certs = new Hashtable<String, Certificate[]>();
+            domains = new HashSet<ProtectionDomain>();
+            assertionLock = this;
+        }
         initialized = true;
     }
 
@@ -244,10 +293,22 @@
             security.checkCreateClassLoader();
         }
         this.parent = getSystemClassLoader();
+        if (parallelLoaders.contains(this.getClass())) {
+            parallelLockMap = new ConcurrentHashMap<String, Object>();
+            package2certs = new ConcurrentHashMap<String, Certificate[]>();
+            domains =
+                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
+            assertionLock = new Object();
+        } else {
+            // no finer-grained lock; lock on the classloader instance
+            parallelLockMap = null;
+            package2certs = new Hashtable<String, Certificate[]>();
+            domains = new HashSet<ProtectionDomain>();
+            assertionLock = this;
+        }
         initialized = true;
     }
 
-
     // -- Class --
 
     /**
@@ -296,6 +357,10 @@
      * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
      * #findClass(String)}, rather than this method.  </p>
      *
+     * <p> Unless overridden, this method synchronizes on the result of
+     * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
+     * during the entire class loading process.
+     *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
@@ -307,37 +372,80 @@
      * @throws  ClassNotFoundException
      *          If the class could not be found
      */
-    protected synchronized Class<?> loadClass(String name, boolean resolve)
+    protected Class<?> loadClass(String name, boolean resolve)
         throws ClassNotFoundException
     {
-        // First, check if the class has already been loaded
-        Class c = findLoadedClass(name);
-        if (c == null) {
-            try {
-                if (parent != null) {
-                    c = parent.loadClass(name, false);
-                } else {
-                    c = findBootstrapClass0(name);
+        synchronized (getClassLoadingLock(name)) {
+            // First, check if the class has already been loaded
+            Class c = findLoadedClass(name);
+            if (c == null) {
+                try {
+                    if (parent != null) {
+                        c = parent.loadClass(name, false);
+                    } else {
+                        c = findBootstrapClass0(name);
+                    }
+                } catch (ClassNotFoundException e) {
+                    // If still not found, then invoke findClass in order
+                    // to find the class.
+                    c = findClass(name);
                 }
-            } catch (ClassNotFoundException e) {
-                // If still not found, then invoke findClass in order
-                // to find the class.
-                c = findClass(name);
+            }
+            if (resolve) {
+                resolveClass(c);
+            }
+            return c;
+        }
+    }
+
+    /**
+     * Returns the lock object for class loading operations.
+     * For backward compatibility, the default implementation of this method
+     * behaves as follows. If this ClassLoader object is registered as
+     * parallel capable, the method returns a dedicated object associated
+     * with the specified class name. Otherwise, the method returns this
+     * ClassLoader object. </p>
+     *
+     * @param  className
+     *         The name of the to-be-loaded class
+     *
+     * @return the lock for class loading operations
+     *
+     * @throws NullPointerException
+     *         If registered as parallel capable and <tt>className</tt> is null
+     *
+     * @see #loadClass(String, boolean)
+     *
+     * @since  1.7
+     */
+    protected Object getClassLoadingLock(String className) {
+        Object lock = this;
+        if (parallelLockMap != null) {
+            Object newLock = new Object();
+            lock = parallelLockMap.putIfAbsent(className, newLock);
+            if (lock == null) {
+                lock = newLock;
             }
         }
-        if (resolve) {
-            resolveClass(c);
-        }
-        return c;
+        return lock;
     }
 
     // This method is invoked by the virtual machine to load a class.
-    private synchronized Class loadClassInternal(String name)
+    private Class loadClassInternal(String name)
         throws ClassNotFoundException
     {
-        return loadClass(name);
+        // For backward compatibility, explicitly lock on 'this' when
+        // the current class loader is not parallel capable.
+        if (parallelLockMap == null) {
+            synchronized (this) {
+                 return loadClass(name);
+            }
+        } else {
+            return loadClass(name);
+        }
     }
 
+    // Invoked by the VM after loading class with this loader.
     private void checkPackageAccess(Class cls, ProtectionDomain pd) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -486,31 +594,32 @@
 
     /* Determine protection domain, and check that:
         - not define java.* class,
-        - signer of this class matches signers for the rest of the classes in package.
+        - signer of this class matches signers for the rest of the classes in
+          package.
     */
     private ProtectionDomain preDefineClass(String name,
-                                            ProtectionDomain protectionDomain)
+                                            ProtectionDomain pd)
     {
         if (!checkName(name))
             throw new NoClassDefFoundError("IllegalName: " + name);
 
         if ((name != null) && name.startsWith("java.")) {
-            throw new SecurityException("Prohibited package name: " +
-                                        name.substring(0, name.lastIndexOf('.')));
+            throw new SecurityException
+                ("Prohibited package name: " +
+                 name.substring(0, name.lastIndexOf('.')));
         }
-        if (protectionDomain == null) {
-            protectionDomain = getDefaultDomain();
+        if (pd == null) {
+            pd = defaultDomain;
         }
 
-        if (name != null)
-            checkCerts(name, protectionDomain.getCodeSource());
+        if (name != null) checkCerts(name, pd.getCodeSource());
 
-        return protectionDomain;
+        return pd;
     }
 
-    private String defineClassSourceLocation(ProtectionDomain protectionDomain)
+    private String defineClassSourceLocation(ProtectionDomain pd)
     {
-        CodeSource cs = protectionDomain.getCodeSource();
+        CodeSource cs = pd.getCodeSource();
         String source = null;
         if (cs != null && cs.getLocation() != null) {
             source = cs.getLocation().toString();
@@ -519,14 +628,15 @@
     }
 
     private Class defineTransformedClass(String name, byte[] b, int off, int len,
-                                         ProtectionDomain protectionDomain,
+                                         ProtectionDomain pd,
                                          ClassFormatError cfe, String source)
       throws ClassFormatError
     {
         // Class format error - try to transform the bytecode and
         // define the class again
         //
-        ClassFileTransformer[] transformers = ClassFileTransformer.getTransformers();
+        ClassFileTransformer[] transformers =
+            ClassFileTransformer.getTransformers();
         Class c = null;
 
         if (transformers != null) {
@@ -535,7 +645,7 @@
                     // Transform byte code using transformer
                     byte[] tb = transformer.transform(b, off, len);
                     c = defineClass1(name, tb, 0, tb.length,
-                                     protectionDomain, source);
+                                     pd, source);
                     break;
                 } catch (ClassFormatError cfe2)     {
                     // If ClassFormatError occurs, try next transformer
@@ -552,11 +662,10 @@
         return c;
     }
 
-    private void postDefineClass(Class c, ProtectionDomain protectionDomain)
+    private void postDefineClass(Class c, ProtectionDomain pd)
     {
-        if (protectionDomain.getCodeSource() != null) {
-            Certificate certs[] =
-                protectionDomain.getCodeSource().getCertificates();
+        if (pd.getCodeSource() != null) {
+            Certificate certs[] = pd.getCodeSource().getCertificates();
             if (certs != null)
                 setSigners(c, certs);
         }
@@ -641,7 +750,8 @@
         try {
             c = defineClass1(name, b, off, len, protectionDomain, source);
         } catch (ClassFormatError cfe) {
-            c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, source);
+            c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,
+                                       source);
         }
 
         postDefineClass(c, protectionDomain);
@@ -656,10 +766,10 @@
      * specified in the documentation for {@link #defineClass(String, byte[],
      * int, int)}.  Before the class can be used it must be resolved.
      *
-     * <p>The rules about the first class defined in a package determining the set of
-     * certificates for the package, and the restrictions on class names are identical
-     * to those specified in the documentation for {@link #defineClass(String, byte[],
-     * int, int, ProtectionDomain)}.
+     * <p>The rules about the first class defined in a package determining the
+     * set of certificates for the package, and the restrictions on class names
+     * are identical to those specified in the documentation for {@link
+     * #defineClass(String, byte[], int, int, ProtectionDomain)}.
      *
      * <p> An invocation of this method of the form
      * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
@@ -668,12 +778,13 @@
      *
      * <blockquote><tt>
      * ...<br>
-     * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#remaining
-     * remaining}()];<br>
+     * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link
+     * java.nio.ByteBuffer#remaining remaining}()];<br>
      *     </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
      * get}(temp);<br>
      *     return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
-     * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0, temp.length, </tt><i>pd</i><tt>);<br>
+     * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0,
+     * temp.length, </tt><i>pd</i><tt>);<br>
      * </tt></blockquote>
      *
      * @param  name
@@ -682,9 +793,9 @@
      *
      * @param  b
      *         The bytes that make up the class data. The bytes from positions
-     *         <tt>b.position()</tt> through <tt>b.position() + b.limit() -1 </tt>
-     *         should have the format of a valid class file as defined by the <a
-     *         href="http://java.sun.com/docs/books/vmspec/">Java Virtual
+     *         <tt>b.position()</tt> through <tt>b.position() + b.limit() -1
+     *         </tt> should have the format of a valid class file as defined by
+     *         the <a href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      *         Machine Specification</a>.
      *
      * @param  protectionDomain
@@ -738,11 +849,13 @@
         String source = defineClassSourceLocation(protectionDomain);
 
         try {
-            c = defineClass2(name, b, b.position(), len, protectionDomain, source);
+            c = defineClass2(name, b, b.position(), len, protectionDomain,
+                             source);
         } catch (ClassFormatError cfe) {
             byte[] tb = new byte[len];
             b.get(tb);  // get bytes out of byte buffer.
-            c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe, source);
+            c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe,
+                                       source);
         }
 
         postDefineClass(c, protectionDomain);
@@ -769,33 +882,29 @@
         return true;
     }
 
-    private synchronized void checkCerts(String name, CodeSource cs) {
+    private void checkCerts(String name, CodeSource cs) {
         int i = name.lastIndexOf('.');
         String pname = (i == -1) ? "" : name.substring(0, i);
-        Certificate[] pcerts = package2certs.get(pname);
-        if (pcerts == null) {
-            // first class in this package gets to define which
-            // certificates must be the same for all other classes
-            // in this package
-            if (cs != null) {
-                pcerts = cs.getCertificates();
+
+        Certificate[] certs = null;
+        if (cs != null) {
+            certs = cs.getCertificates();
+        }
+        Certificate[] pcerts = null;
+        if (parallelLockMap == null) {
+            synchronized (this) {
+                pcerts = package2certs.get(pname);
+                if (pcerts == null) {
+                    package2certs.put(pname, (certs == null? nocerts:certs));
+                }
             }
-            if (pcerts == null) {
-                if (nocerts == null)
-                    nocerts = new Certificate[0];
-                pcerts = nocerts;
-            }
-            package2certs.put(pname, pcerts);
         } else {
-            Certificate[] certs = null;
-            if (cs != null) {
-                certs = cs.getCertificates();
-            }
-
-            if (!compareCerts(pcerts, certs)) {
-                throw new SecurityException("class \""+ name +
-                                            "\"'s signer information does not match signer information of other classes in the same package");
-            }
+            pcerts = ((ConcurrentHashMap<String, Certificate[]>)package2certs).
+                putIfAbsent(pname, (certs == null? nocerts:certs));
+        }
+        if (pcerts != null && !compareCerts(pcerts, certs)) {
+            throw new SecurityException("class \""+ name +
+                 "\"'s signer information does not match signer information of other classes in the same package");
         }
     }
 
@@ -1075,6 +1184,47 @@
         return java.util.Collections.emptyEnumeration();
     }
 
+    // index 0: java.lang.ClassLoader.class
+    // index 1: the immediate caller of index 0.
+    // index 2: the immediate caller of index 1.
+    private static native Class<? extends ClassLoader> getCaller(int index);
+
+    /**
+     * Registers the caller class loader as parallel capable.
+     * In order for the registration to succeed, all super classes
+     * of the caller class loader must also be registered as
+     * parallel capable when this method is called. </p>
+     * Note that once a class loader is registered as
+     * parallel capable, there is no way to change it back.
+     * In addition, registration should be done statically before
+     * any instance of the caller classloader being constructed. </p>
+     *
+     * @return  true if the caller is successfully registered as
+     *          parallel capable and false if otherwise.
+     *
+     * @since   1.7
+     */
+    protected static boolean registerAsParallelCapable() {
+        Class<? extends ClassLoader> caller = getCaller(1);
+        Class superCls = caller.getSuperclass();
+        boolean result = false;
+        // Explicit synchronization needed for composite action
+        synchronized (parallelLoaders) {
+            if (!parallelLoaders.contains(caller)) {
+                if (parallelLoaders.contains(superCls)) {
+                    // register the immediate caller as parallel capable
+                    // if and only if all of its super classes are.
+                    // Note: given current classloading sequence, if
+                    // the immediate super class is parallel capable,
+                    // all the super classes higher up must be too.
+                    result = true;
+                    parallelLoaders.add(caller);
+                }
+            } else result = true;
+        }
+        return result;
+    }
+
     /**
      * Find a resource of the specified name from the search path used to load
      * classes.  This method locates the resource through the system class
@@ -1141,7 +1291,8 @@
     private static Enumeration<URL> getBootstrapResources(String name)
         throws IOException
     {
-        final Enumeration<Resource> e = getBootstrapClassPath().getResources(name);
+        final Enumeration<Resource> e =
+            getBootstrapClassPath().getResources(name);
         return new Enumeration<URL> () {
             public URL nextElement() {
                 return e.nextElement().getURL();
@@ -1377,9 +1528,11 @@
     }
 
     // The class loader for the system
+    // @GuardedBy("ClassLoader.class")
     private static ClassLoader scl;
 
     // Set to true once the system class loader has been set
+    // @GuardedBy("ClassLoader.class")
     private static boolean sclSet;
 
 
@@ -1592,19 +1745,6 @@
         }
     }
 
-    // The "default" domain. Set as the default ProtectionDomain on newly
-    // created classes.
-    private ProtectionDomain defaultDomain = null;
-
-    // Returns (and initializes) the default domain.
-    private synchronized ProtectionDomain getDefaultDomain() {
-        if (defaultDomain == null) {
-            CodeSource cs = new CodeSource(null, (Certificate[]) null);
-            defaultDomain = new ProtectionDomain(cs, null, this, null);
-        }
-        return defaultDomain;
-    }
-
     // All native library names we've loaded.
     private static Vector<String> loadedLibraryNames
         = new Vector<String>();
@@ -1622,8 +1762,8 @@
         = new Stack<NativeLibrary>();
 
     // The paths searched for libraries
-    static private String usr_paths[];
-    static private String sys_paths[];
+    private static String usr_paths[];
+    private static String sys_paths[];
 
     private static String[] initializePath(String propname) {
         String ldpath = System.getProperty(propname, "");
@@ -1803,7 +1943,10 @@
 
     // -- Assertion management --
 
+    final Object assertionLock;
+
     // The default toggle for assertion checking.
+    // @GuardedBy("assertionLock")
     private boolean defaultAssertionStatus = false;
 
     // Maps String packageName to Boolean package default assertion status Note
@@ -1811,12 +1954,14 @@
     // is null then we are delegating assertion status queries to the VM, i.e.,
     // none of this ClassLoader's assertion status modification methods have
     // been invoked.
+    // @GuardedBy("assertionLock")
     private Map<String, Boolean> packageAssertionStatus = null;
 
     // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
     // field is null then we are delegating assertion status queries to the VM,
     // i.e., none of this ClassLoader's assertion status modification methods
     // have been invoked.
+    // @GuardedBy("assertionLock")
     Map<String, Boolean> classAssertionStatus = null;
 
     /**
@@ -1834,11 +1979,13 @@
      *
      * @since  1.4
      */
-    public synchronized void setDefaultAssertionStatus(boolean enabled) {
-        if (classAssertionStatus == null)
-            initializeJavaAssertionMaps();
+    public void setDefaultAssertionStatus(boolean enabled) {
+        synchronized (assertionLock) {
+            if (classAssertionStatus == null)
+                initializeJavaAssertionMaps();
 
-        defaultAssertionStatus = enabled;
+            defaultAssertionStatus = enabled;
+        }
     }
 
     /**
@@ -1878,13 +2025,14 @@
      *
      * @since  1.4
      */
-    public synchronized void setPackageAssertionStatus(String packageName,
-                                                       boolean enabled)
-    {
-        if (packageAssertionStatus == null)
-            initializeJavaAssertionMaps();
+    public void setPackageAssertionStatus(String packageName,
+                                          boolean enabled) {
+        synchronized (assertionLock) {
+            if (packageAssertionStatus == null)
+                initializeJavaAssertionMaps();
 
-        packageAssertionStatus.put(packageName, enabled);
+            packageAssertionStatus.put(packageName, enabled);
+        }
     }
 
     /**
@@ -1909,13 +2057,13 @@
      *
      * @since  1.4
      */
-    public synchronized void setClassAssertionStatus(String className,
-                                                     boolean enabled)
-    {
-        if (classAssertionStatus == null)
-            initializeJavaAssertionMaps();
+    public void setClassAssertionStatus(String className, boolean enabled) {
+        synchronized (assertionLock) {
+            if (classAssertionStatus == null)
+                initializeJavaAssertionMaps();
 
-        classAssertionStatus.put(className, enabled);
+            classAssertionStatus.put(className, enabled);
+        }
     }
 
     /**
@@ -1928,15 +2076,16 @@
      *
      * @since  1.4
      */
-    public synchronized void clearAssertionStatus() {
+    public void clearAssertionStatus() {
         /*
          * Whether or not "Java assertion maps" are initialized, set
          * them to empty maps, effectively ignoring any present settings.
          */
-        classAssertionStatus = new HashMap<String, Boolean>();
-        packageAssertionStatus = new HashMap<String, Boolean>();
-
-        defaultAssertionStatus = false;
+        synchronized (assertionLock) {
+            classAssertionStatus = new HashMap<String, Boolean>();
+            packageAssertionStatus = new HashMap<String, Boolean>();
+            defaultAssertionStatus = false;
+        }
     }
 
     /**
@@ -1961,39 +2110,40 @@
      *
      * @since  1.4
      */
-    synchronized boolean desiredAssertionStatus(String className) {
-        Boolean result;
+    boolean desiredAssertionStatus(String className) {
+        synchronized (assertionLock) {
+            // assert classAssertionStatus   != null;
+            // assert packageAssertionStatus != null;
 
-        // assert classAssertionStatus   != null;
-        // assert packageAssertionStatus != null;
-
-        // Check for a class entry
-        result = classAssertionStatus.get(className);
-        if (result != null)
-            return result.booleanValue();
-
-        // Check for most specific package entry
-        int dotIndex = className.lastIndexOf(".");
-        if (dotIndex < 0) { // default package
-            result = packageAssertionStatus.get(null);
+            // Check for a class entry
+            Boolean result = classAssertionStatus.get(className);
             if (result != null)
                 return result.booleanValue();
+
+            // Check for most specific package entry
+            int dotIndex = className.lastIndexOf(".");
+            if (dotIndex < 0) { // default package
+                result = packageAssertionStatus.get(null);
+                if (result != null)
+                    return result.booleanValue();
+            }
+            while(dotIndex > 0) {
+                className = className.substring(0, dotIndex);
+                result = packageAssertionStatus.get(className);
+                if (result != null)
+                    return result.booleanValue();
+                dotIndex = className.lastIndexOf(".", dotIndex-1);
+            }
+
+            // Return the classloader default
+            return defaultAssertionStatus;
         }
-        while(dotIndex > 0) {
-            className = className.substring(0, dotIndex);
-            result = packageAssertionStatus.get(className);
-            if (result != null)
-                return result.booleanValue();
-            dotIndex = className.lastIndexOf(".", dotIndex-1);
-        }
-
-        // Return the classloader default
-        return defaultAssertionStatus;
     }
 
     // Set up the assertions with information provided by the VM.
+    // Note: Should only be called inside a synchronized block
     private void initializeJavaAssertionMaps() {
-        // assert Thread.holdsLock(this);
+        // assert Thread.holdsLock(assertionLock);
 
         classAssertionStatus = new HashMap<String, Boolean>();
         packageAssertionStatus = new HashMap<String, Boolean>();
--- a/src/share/classes/java/lang/Integer.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/Integer.java	Tue Apr 14 16:51:38 2009 +0100
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import java.util.Properties;
+
 /**
  * The {@code Integer} class wraps a value of the primitive type
  * {@code int} in an object. An object of type {@code Integer}
@@ -442,6 +444,12 @@
     public static int parseInt(String s, int radix)
                 throws NumberFormatException
     {
+        /*
+         * WARNING: This method may be invoked early during VM initialization
+         * before IntegerCache is initialized. Care must be taken to not use
+         * the valueOf method.
+         */
+
         if (s == null) {
             throw new NumberFormatException("null");
         }
@@ -545,7 +553,7 @@
      *            does not contain a parsable {@code int}.
      */
     public static Integer valueOf(String s, int radix) throws NumberFormatException {
-        return new Integer(parseInt(s,radix));
+        return Integer.valueOf(parseInt(s,radix));
     }
 
     /**
@@ -570,20 +578,56 @@
      * @exception  NumberFormatException  if the string cannot be parsed
      *             as an integer.
      */
-    public static Integer valueOf(String s) throws NumberFormatException
-    {
-        return new Integer(parseInt(s, 10));
+    public static Integer valueOf(String s) throws NumberFormatException {
+        return Integer.valueOf(parseInt(s, 10));
+    }
+
+    /**
+     * Cache to support the object identity semantics of autoboxing for values between
+     * -128 and 127 (inclusive) as required by JLS.
+     *
+     * The cache is initialized on first usage. During VM initialization the
+     * getAndRemoveCacheProperties method may be used to get and remove any system
+     * properites that configure the cache size. At this time, the size of the
+     * cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
+     */
+
+    // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
+    private static String integerCacheHighPropValue;
+
+    static void getAndRemoveCacheProperties() {
+        if (!sun.misc.VM.isBooted()) {
+            Properties props = System.getProperties();
+            integerCacheHighPropValue =
+                (String)props.remove("java.lang.Integer.IntegerCache.high");
+            if (integerCacheHighPropValue != null)
+                System.setProperties(props);  // remove from system props
+        }
     }
 
     private static class IntegerCache {
-        private IntegerCache(){}
-
-        static final Integer cache[] = new Integer[-(-128) + 127 + 1];
+        static final int low = -128;
+        static final int high;
+        static final Integer cache[];
 
         static {
-            for(int i = 0; i < cache.length; i++)
-                cache[i] = new Integer(i - 128);
+            // high value may be configured by property
+            int h = 127;
+            if (integerCacheHighPropValue != null) {
+                int i = parseInt(integerCacheHighPropValue);
+                i = Math.max(i, 127);
+                // Maximum array size is Integer.MAX_VALUE
+                h = Math.min(i, Integer.MAX_VALUE - (-low));
+            }
+            high = h;
+
+            cache = new Integer[(high - low) + 1];
+            int j = low;
+            for(int k = 0; k < cache.length; k++)
+                cache[k] = new Integer(j++);
         }
+
+        private IntegerCache() {}
     }
 
     /**
@@ -599,10 +643,9 @@
      * @since  1.5
      */
     public static Integer valueOf(int i) {
-        final int offset = 128;
-        if (i >= -128 && i <= 127) { // must cache
-            return IntegerCache.cache[i + offset];
-        }
+        assert IntegerCache.high >= 127;
+        if (i >= IntegerCache.low && i <= IntegerCache.high)
+            return IntegerCache.cache[i + (-IntegerCache.low)];
         return new Integer(i);
     }
 
@@ -806,7 +849,7 @@
      */
     public static Integer getInteger(String nm, int val) {
         Integer result = getInteger(nm, null);
-        return (result == null) ? new Integer(val) : result;
+        return (result == null) ? Integer.valueOf(val) : result;
     }
 
     /**
@@ -938,7 +981,7 @@
 
         try {
             result = Integer.valueOf(nm.substring(index), radix);
-            result = negative ? new Integer(-result.intValue()) : result;
+            result = negative ? Integer.valueOf(-result.intValue()) : result;
         } catch (NumberFormatException e) {
             // If number is Integer.MIN_VALUE, we'll end up here. The next line
             // handles this case, and causes any genuine format error to be
--- a/src/share/classes/java/lang/Long.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/Long.java	Tue Apr 14 16:51:38 2009 +0100
@@ -510,7 +510,7 @@
      *             contain a parsable {@code long}.
      */
     public static Long valueOf(String s, int radix) throws NumberFormatException {
-        return new Long(parseLong(s, radix));
+        return Long.valueOf(parseLong(s, radix));
     }
 
     /**
@@ -537,7 +537,7 @@
      */
     public static Long valueOf(String s) throws NumberFormatException
     {
-        return new Long(parseLong(s, 10));
+        return Long.valueOf(parseLong(s, 10));
     }
 
     private static class LongCache {
@@ -650,7 +650,7 @@
 
         try {
             result = Long.valueOf(nm.substring(index), radix);
-            result = negative ? new Long(-result.longValue()) : result;
+            result = negative ? Long.valueOf(-result.longValue()) : result;
         } catch (NumberFormatException e) {
             // If number is Long.MIN_VALUE, we'll end up here. The next line
             // handles this case, and causes any genuine format error to be
@@ -869,7 +869,7 @@
      */
     public static Long getLong(String nm, long val) {
         Long result = Long.getLong(nm, null);
-        return (result == null) ? new Long(val) : result;
+        return (result == null) ? Long.valueOf(val) : result;
     }
 
     /**
--- a/src/share/classes/java/lang/System.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/System.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1105,6 +1105,13 @@
         props = new Properties();
         initProperties(props);
         sun.misc.Version.init();
+
+        // Gets and removes system properties that configure the Integer
+        // cache used to support the object identity semantics of autoboxing.
+        // At this time, the size of the cache may be controlled by the
+        // -XX:AutoBoxCacheMax=<size> option.
+        Integer.getAndRemoveCacheProperties();
+
         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
         FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
         FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
--- a/src/share/classes/java/lang/ref/ReferenceQueue.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/ref/ReferenceQueue.java	Tue Apr 14 16:51:38 2009 +0100
@@ -51,7 +51,7 @@
 
     static private class Lock { };
     private Lock lock = new Lock();
-    private Reference<? extends T> head = null;
+    private volatile Reference<? extends T> head = null;
     private long queueLength = 0;
 
     boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
@@ -95,6 +95,8 @@
      *          otherwise <code>null</code>
      */
     public Reference<? extends T> poll() {
+        if (head == null)
+            return null;
         synchronized (lock) {
             return reallyPoll();
         }
--- a/src/share/classes/java/lang/ref/SoftReference.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/lang/ref/SoftReference.java	Tue Apr 14 16:51:38 2009 +0100
@@ -63,11 +63,13 @@
 
 public class SoftReference<T> extends Reference<T> {
 
-    /* Timestamp clock, updated by the garbage collector
+    /**
+     * Timestamp clock, updated by the garbage collector
      */
     static private long clock;
 
-    /* Timestamp updated by each invocation of the get method.  The VM may use
+    /**
+     * Timestamp updated by each invocation of the get method.  The VM may use
      * this field when selecting soft references to be cleared, but it is not
      * required to do so.
      */
@@ -108,7 +110,8 @@
      */
     public T get() {
         T o = super.get();
-        if (o != null) this.timestamp = clock;
+        if (o != null && this.timestamp != clock)
+            this.timestamp = clock;
         return o;
     }
 
--- a/src/share/classes/java/net/AbstractPlainSocketImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -33,6 +33,7 @@
 import java.io.ByteArrayOutputStream;
 
 import sun.net.ConnectionResetException;
+import sun.net.NetHooks;
 
 /**
  * Default Socket Implementation. This implementation does
@@ -304,6 +305,11 @@
      */
 
     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
+        synchronized (fdLock) {
+            if (!closePending && (socket == null || !socket.isBound())) {
+                NetHooks.beforeTcpConnect(fd, address, port);
+            }
+        }
         try {
             FileDescriptor fd = acquireFD();
             try {
@@ -339,6 +345,11 @@
     protected synchronized void bind(InetAddress address, int lport)
         throws IOException
     {
+       synchronized (fdLock) {
+            if (!closePending && (socket == null || !socket.isBound())) {
+                NetHooks.beforeTcpBind(fd, address, lport);
+            }
+        }
         socketBind(address, lport);
         if (socket != null)
             socket.setBound();
--- a/src/share/classes/java/net/URLClassLoader.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/net/URLClassLoader.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,10 +74,10 @@
  */
 public class URLClassLoader extends SecureClassLoader implements Closeable {
     /* The search path for classes and resources */
-    URLClassPath ucp;
+    private final URLClassPath ucp;
 
     /* The context to be used when loading classes and resources */
-    private AccessControlContext acc;
+    private final AccessControlContext acc;
 
     /**
      * Constructs a new URLClassLoader for the given URLs. The URLs will be
@@ -105,7 +105,19 @@
             security.checkCreateClassLoader();
         }
         ucp = new URLClassPath(urls);
-        acc = AccessController.getContext();
+        this.acc = AccessController.getContext();
+    }
+
+    URLClassLoader(URL[] urls, ClassLoader parent,
+                   AccessControlContext acc) {
+        super(parent);
+        // this is to make the stack depth consistent with 1.1
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        ucp = new URLClassPath(urls);
+        this.acc = acc;
     }
 
     /**
@@ -136,7 +148,18 @@
             security.checkCreateClassLoader();
         }
         ucp = new URLClassPath(urls);
-        acc = AccessController.getContext();
+        this.acc = AccessController.getContext();
+    }
+
+    URLClassLoader(URL[] urls, AccessControlContext acc) {
+        super();
+        // this is to make the stack depth consistent with 1.1
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        ucp = new URLClassPath(urls);
+        this.acc = acc;
     }
 
     /**
@@ -599,17 +622,14 @@
     public static URLClassLoader newInstance(final URL[] urls,
                                              final ClassLoader parent) {
         // Save the caller's context
-        AccessControlContext acc = AccessController.getContext();
+        final AccessControlContext acc = AccessController.getContext();
         // Need a privileged block to create the class loader
         URLClassLoader ucl = AccessController.doPrivileged(
             new PrivilegedAction<URLClassLoader>() {
                 public URLClassLoader run() {
-                    return new FactoryURLClassLoader(urls, parent);
+                    return new FactoryURLClassLoader(urls, parent, acc);
                 }
             });
-        // Now set the context on the loader using the one we saved,
-        // not the one inside the privileged block...
-        ucl.acc = acc;
         return ucl;
     }
 
@@ -626,18 +646,14 @@
      */
     public static URLClassLoader newInstance(final URL[] urls) {
         // Save the caller's context
-        AccessControlContext acc = AccessController.getContext();
+        final AccessControlContext acc = AccessController.getContext();
         // Need a privileged block to create the class loader
         URLClassLoader ucl = AccessController.doPrivileged(
             new PrivilegedAction<URLClassLoader>() {
                 public URLClassLoader run() {
-                    return new FactoryURLClassLoader(urls);
+                    return new FactoryURLClassLoader(urls, acc);
                 }
             });
-
-        // Now set the context on the loader using the one we saved,
-        // not the one inside the privileged block...
-        ucl.acc = acc;
         return ucl;
     }
 
@@ -649,20 +665,26 @@
                 }
             }
         );
+        ClassLoader.registerAsParallelCapable();
     }
 }
 
 final class FactoryURLClassLoader extends URLClassLoader {
 
-    FactoryURLClassLoader(URL[] urls, ClassLoader parent) {
-        super(urls, parent);
+    static {
+        ClassLoader.registerAsParallelCapable();
     }
 
-    FactoryURLClassLoader(URL[] urls) {
-        super(urls);
+    FactoryURLClassLoader(URL[] urls, ClassLoader parent,
+                          AccessControlContext acc) {
+        super(urls, parent, acc);
     }
 
-    public final synchronized Class loadClass(String name, boolean resolve)
+    FactoryURLClassLoader(URL[] urls, AccessControlContext acc) {
+        super(urls, acc);
+    }
+
+    public final Class loadClass(String name, boolean resolve)
         throws ClassNotFoundException
     {
         // First check if we have permission to access the package. This
--- a/src/share/classes/java/nio/channels/DatagramChannel.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/nio/channels/DatagramChannel.java	Tue Apr 14 16:51:38 2009 +0100
@@ -261,7 +261,10 @@
      *
      * <p> This method may be invoked at any time.  It will not have any effect
      * on read or write operations that are already in progress at the moment
-     * that it is invoked.  </p>
+     * that it is invoked. If this channel's socket is not bound then this method
+     * will first cause the socket to be bound to an address that is assigned
+     * automatically, as if invoking the {@link #bind bind} method with a
+     * parameter of {@code null}. </p>
      *
      * @param  remote
      *         The remote address to which this channel is to be connected
@@ -356,7 +359,10 @@
      * <p> This method may be invoked at any time.  If another thread has
      * already initiated a read operation upon this channel, however, then an
      * invocation of this method will block until the first operation is
-     * complete. </p>
+     * complete. If this channel's socket is not bound then this method will
+     * first cause the socket to be bound to an address that is assigned
+     * automatically, as if invoking the {@link #bind bind} method with a
+     * parameter of {@code null}. </p>
      *
      * @param  dst
      *         The buffer into which the datagram is to be transferred
@@ -413,7 +419,10 @@
      * <p> This method may be invoked at any time.  If another thread has
      * already initiated a write operation upon this channel, however, then an
      * invocation of this method will block until the first operation is
-     * complete. </p>
+     * complete. If this channel's socket is not bound then this method will
+     * first cause the socket to be bound to an address that is assigned
+     * automatically, as if by invoking the {@link #bind bind) method with a
+     * parameter of {@code null}. </p>
      *
      * @param  src
      *         The buffer containing the datagram to be sent
--- a/src/share/classes/java/security/SecureClassLoader.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/security/SecureClassLoader.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,14 +45,19 @@
      * succeed. Otherwise the object is not initialized and the object is
      * useless.
      */
-    private boolean initialized = false;
+    private final boolean initialized;
 
     // HashMap that maps CodeSource to ProtectionDomain
-    private HashMap<CodeSource, ProtectionDomain> pdcache =
+    // @GuardedBy("pdcache")
+    private final HashMap<CodeSource, ProtectionDomain> pdcache =
                         new HashMap<CodeSource, ProtectionDomain>(11);
 
     private static final Debug debug = Debug.getInstance("scl");
 
+    static {
+        ClassLoader.registerAsParallelCapable();
+    }
+
     /**
      * Creates a new SecureClassLoader using the specified parent
      * class loader for delegation.
@@ -136,10 +141,7 @@
                                          byte[] b, int off, int len,
                                          CodeSource cs)
     {
-        if (cs == null)
-            return defineClass(name, b, off, len);
-        else
-            return defineClass(name, b, off, len, getProtectionDomain(cs));
+        return defineClass(name, b, off, len, getProtectionDomain(cs));
     }
 
     /**
@@ -172,10 +174,7 @@
     protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
                                          CodeSource cs)
     {
-        if (cs == null)
-            return defineClass(name, b, (ProtectionDomain)null);
-        else
-            return defineClass(name, b, getProtectionDomain(cs));
+        return defineClass(name, b, getProtectionDomain(cs));
     }
 
     /**
@@ -209,12 +208,10 @@
             if (pd == null) {
                 PermissionCollection perms = getPermissions(cs);
                 pd = new ProtectionDomain(cs, perms, this, null);
-                if (pd != null) {
-                    pdcache.put(cs, pd);
-                    if (debug != null) {
-                        debug.println(" getPermissions "+ pd);
-                        debug.println("");
-                    }
+                pdcache.put(cs, pd);
+                if (debug != null) {
+                    debug.println(" getPermissions "+ pd);
+                    debug.println("");
                 }
             }
         }
--- a/src/share/classes/java/util/TreeMap.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/TreeMap.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1068,14 +1068,14 @@
         }
         public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                                       E toElement,   boolean toInclusive) {
-            return new TreeSet<E>(m.subMap(fromElement, fromInclusive,
-                                           toElement,   toInclusive));
+            return new KeySet<E>(m.subMap(fromElement, fromInclusive,
+                                          toElement,   toInclusive));
         }
         public NavigableSet<E> headSet(E toElement, boolean inclusive) {
-            return new TreeSet<E>(m.headMap(toElement, inclusive));
+            return new KeySet<E>(m.headMap(toElement, inclusive));
         }
         public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
-            return new TreeSet<E>(m.tailMap(fromElement, inclusive));
+            return new KeySet<E>(m.tailMap(fromElement, inclusive));
         }
         public SortedSet<E> subSet(E fromElement, E toElement) {
             return subSet(fromElement, true, toElement, false);
@@ -1087,7 +1087,7 @@
             return tailSet(fromElement, true);
         }
         public NavigableSet<E> descendingSet() {
-            return new TreeSet(m.descendingMap());
+            return new KeySet(m.descendingMap());
         }
     }
 
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Tue Apr 14 16:51:38 2009 +0100
@@ -2394,15 +2394,14 @@
                                       boolean fromInclusive,
                                       E toElement,
                                       boolean toInclusive) {
-            return new ConcurrentSkipListSet<E>
-                (m.subMap(fromElement, fromInclusive,
-                          toElement,   toInclusive));
+            return new KeySet<E>(m.subMap(fromElement, fromInclusive,
+                                          toElement,   toInclusive));
         }
         public NavigableSet<E> headSet(E toElement, boolean inclusive) {
-            return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
+            return new KeySet<E>(m.headMap(toElement, inclusive));
         }
         public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
-            return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
+            return new KeySet<E>(m.tailMap(fromElement, inclusive));
         }
         public NavigableSet<E> subSet(E fromElement, E toElement) {
             return subSet(fromElement, true, toElement, false);
@@ -2414,7 +2413,7 @@
             return tailSet(fromElement, true);
         }
         public NavigableSet<E> descendingSet() {
-            return new ConcurrentSkipListSet(m.descendingMap());
+            return new KeySet(m.descendingMap());
         }
     }
 
--- a/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Tue Apr 14 16:51:38 2009 +0100
@@ -166,6 +166,11 @@
         static final int SIGNAL    = -1;
         /** waitStatus value to indicate thread is waiting on condition */
         static final int CONDITION = -2;
+        /**
+         * waitStatus value to indicate the next acquireShared should
+         * unconditionally propagate
+         */
+        static final int PROPAGATE = -3;
 
         /**
          * Status field, taking on only the values:
@@ -180,10 +185,16 @@
          *               Nodes never leave this state. In particular,
          *               a thread with cancelled node never again blocks.
          *   CONDITION:  This node is currently on a condition queue.
-         *               It will not be used as a sync queue node until
-         *               transferred. (Use of this value here
-         *               has nothing to do with the other uses
-         *               of the field, but simplifies mechanics.)
+         *               It will not be used as a sync queue node
+         *               until transferred, at which time the status
+         *               will be set to 0. (Use of this value here has
+         *               nothing to do with the other uses of the
+         *               field, but simplifies mechanics.)
+         *   PROPAGATE:  A releaseShared should be propagated to other
+         *               nodes. This is set (for head node only) in
+         *               doReleaseShared to ensure propagation
+         *               continues, even if other operations have
+         *               since intervened.
          *   0:          None of the above
          *
          * The values are arranged numerically to simplify use.
@@ -403,10 +414,13 @@
      */
     private void unparkSuccessor(Node node) {
         /*
-         * Try to clear status in anticipation of signalling.  It is
-         * OK if this fails or if status is changed by waiting thread.
+         * If status is negative (i.e., possibly needing signal) try
+         * to clear in anticipation of signalling.  It is OK if this
+         * fails or if status is changed by waiting thread.
          */
-        compareAndSetWaitStatus(node, Node.SIGNAL, 0);
+        int ws = node.waitStatus;
+        if (ws < 0)
+            compareAndSetWaitStatus(node, ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -426,23 +440,70 @@
     }
 
     /**
+     * Release action for shared mode -- signal successor and ensure
+     * propagation. (Note: For exclusive mode, release just amounts
+     * to calling unparkSuccessor of head if it needs signal.)
+     */
+    private void doReleaseShared() {
+        /*
+         * Ensure that a release propagates, even if there are other
+         * in-progress acquires/releases.  This proceeds in the usual
+         * way of trying to unparkSuccessor of head if it needs
+         * signal. But if it does not, status is set to PROPAGATE to
+         * ensure that upon release, propagation continues.
+         * Additionally, we must loop in case a new node is added
+         * while we are doing this. Also, unlike other uses of
+         * unparkSuccessor, we need to know if CAS to reset status
+         * fails, if so rechecking.
+         */
+        for (;;) {
+            Node h = head;
+            if (h != null && h != tail) {
+                int ws = h.waitStatus;
+                if (ws == Node.SIGNAL) {
+                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+                        continue;            // loop to recheck cases
+                    unparkSuccessor(h);
+                }
+                else if (ws == 0 &&
+                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+                    continue;                // loop on failed CAS
+            }
+            if (h == head)                   // loop if head changed
+                break;
+        }
+    }
+
+    /**
      * Sets head of queue, and checks if successor may be waiting
-     * in shared mode, if so propagating if propagate > 0.
+     * in shared mode, if so propagating if either propagate > 0 or
+     * PROPAGATE status was set.
      *
-     * @param pred the node holding waitStatus for node
      * @param node the node
      * @param propagate the return value from a tryAcquireShared
      */
     private void setHeadAndPropagate(Node node, long propagate) {
+        Node h = head; // Record old head for check below
         setHead(node);
-        if (propagate > 0 && node.waitStatus != 0) {
-            /*
-             * Don't bother fully figuring out successor.  If it
-             * looks null, call unparkSuccessor anyway to be safe.
-             */
+        /*
+         * Try to signal next queued node if:
+         *   Propagation was indicated by caller,
+         *     or was recorded (as h.waitStatus) by a previous operation
+         *     (note: this uses sign-check of waitStatus because
+         *      PROPAGATE status may transition to SIGNAL.)
+         * and
+         *   The next node is waiting in shared mode,
+         *     or we don't know, because it appears null
+         *
+         * The conservatism in both of these checks may cause
+         * unnecessary wake-ups, but only when there are multiple
+         * racing acquires/releases, so most need signals now or soon
+         * anyway.
+         */
+        if (propagate > 0 || h == null || h.waitStatus < 0) {
             Node s = node.next;
             if (s == null || s.isShared())
-                unparkSuccessor(node);
+                doReleaseShared();
         }
     }
 
@@ -465,23 +526,27 @@
         while (pred.waitStatus > 0)
             node.prev = pred = pred.prev;
 
-        // Getting this before setting waitStatus ensures staleness
+        // predNext is the apparent node to unsplice. CASes below will
+        // fail if not, in which case, we lost race vs another cancel
+        // or signal, so no further action is necessary.
         Node predNext = pred.next;
 
-        // Can use unconditional write instead of CAS here
+        // Can use unconditional write instead of CAS here.
+        // After this atomic step, other Nodes can skip past us.
+        // Before, we are free of interference from other threads.
         node.waitStatus = Node.CANCELLED;
 
-        // If we are the tail, remove ourselves
+        // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
             compareAndSetNext(pred, predNext, null);
         } else {
-            // If "active" predecessor found...
-            if (pred != head
-                && (pred.waitStatus == Node.SIGNAL
-                    || compareAndSetWaitStatus(pred, 0, Node.SIGNAL))
-                && pred.thread != null) {
-
-                // If successor is active, set predecessor's next link
+            // If successor needs signal, try to set pred's next-link
+            // so it will get one. Otherwise wake it up to propagate.
+            int ws;
+            if (pred != head &&
+                ((ws = pred.waitStatus) == Node.SIGNAL ||
+                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+                pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
                     compareAndSetNext(pred, predNext, next);
@@ -503,14 +568,14 @@
      * @return {@code true} if thread should block
      */
     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
-        int s = pred.waitStatus;
-        if (s < 0)
+        int ws = pred.waitStatus;
+        if (ws == Node.SIGNAL)
             /*
              * This node has already set status asking a release
              * to signal it, so it can safely park.
              */
             return true;
-        if (s > 0) {
+        if (ws > 0) {
             /*
              * Predecessor was cancelled. Skip over predecessors and
              * indicate retry.
@@ -519,14 +584,14 @@
                 node.prev = pred = pred.prev;
             } while (pred.waitStatus > 0);
             pred.next = node;
+        } else {
+            /*
+             * waitStatus must be 0 or PROPAGATE.  Indicate that we
+             * need a signal, but don't park yet.  Caller will need to
+             * retry to make sure it cannot acquire before parking.
+             */
+            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
         }
-        else
-            /*
-             * Indicate that we need a signal, but don't park yet. Caller
-             * will need to retry to make sure it cannot acquire before
-             * parking.
-             */
-            compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
         return false;
     }
 
@@ -1046,9 +1111,7 @@
      */
     public final boolean releaseShared(long arg) {
         if (tryReleaseShared(arg)) {
-            Node h = head;
-            if (h != null && h.waitStatus != 0)
-                unparkSuccessor(h);
+            doReleaseShared();
             return true;
         }
         return false;
@@ -1390,8 +1453,8 @@
          * case the waitStatus can be transiently and harmlessly wrong).
          */
         Node p = enq(node);
-        int c = p.waitStatus;
-        if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
+        int ws = p.waitStatus;
+        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
--- a/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Tue Apr 14 16:51:38 2009 +0100
@@ -389,6 +389,11 @@
         static final int SIGNAL    = -1;
         /** waitStatus value to indicate thread is waiting on condition */
         static final int CONDITION = -2;
+        /**
+         * waitStatus value to indicate the next acquireShared should
+         * unconditionally propagate
+         */
+        static final int PROPAGATE = -3;
 
         /**
          * Status field, taking on only the values:
@@ -403,10 +408,16 @@
          *               Nodes never leave this state. In particular,
          *               a thread with cancelled node never again blocks.
          *   CONDITION:  This node is currently on a condition queue.
-         *               It will not be used as a sync queue node until
-         *               transferred. (Use of this value here
-         *               has nothing to do with the other uses
-         *               of the field, but simplifies mechanics.)
+         *               It will not be used as a sync queue node
+         *               until transferred, at which time the status
+         *               will be set to 0. (Use of this value here has
+         *               nothing to do with the other uses of the
+         *               field, but simplifies mechanics.)
+         *   PROPAGATE:  A releaseShared should be propagated to other
+         *               nodes. This is set (for head node only) in
+         *               doReleaseShared to ensure propagation
+         *               continues, even if other operations have
+         *               since intervened.
          *   0:          None of the above
          *
          * The values are arranged numerically to simplify use.
@@ -626,10 +637,13 @@
      */
     private void unparkSuccessor(Node node) {
         /*
-         * Try to clear status in anticipation of signalling.  It is
-         * OK if this fails or if status is changed by waiting thread.
+         * If status is negative (i.e., possibly needing signal) try
+         * to clear in anticipation of signalling.  It is OK if this
+         * fails or if status is changed by waiting thread.
          */
-        compareAndSetWaitStatus(node, Node.SIGNAL, 0);
+        int ws = node.waitStatus;
+        if (ws < 0)
+            compareAndSetWaitStatus(node, ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -649,23 +663,70 @@
     }
 
     /**
+     * Release action for shared mode -- signal successor and ensure
+     * propagation. (Note: For exclusive mode, release just amounts
+     * to calling unparkSuccessor of head if it needs signal.)
+     */
+    private void doReleaseShared() {
+        /*
+         * Ensure that a release propagates, even if there are other
+         * in-progress acquires/releases.  This proceeds in the usual
+         * way of trying to unparkSuccessor of head if it needs
+         * signal. But if it does not, status is set to PROPAGATE to
+         * ensure that upon release, propagation continues.
+         * Additionally, we must loop in case a new node is added
+         * while we are doing this. Also, unlike other uses of
+         * unparkSuccessor, we need to know if CAS to reset status
+         * fails, if so rechecking.
+         */
+        for (;;) {
+            Node h = head;
+            if (h != null && h != tail) {
+                int ws = h.waitStatus;
+                if (ws == Node.SIGNAL) {
+                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+                        continue;            // loop to recheck cases
+                    unparkSuccessor(h);
+                }
+                else if (ws == 0 &&
+                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+                    continue;                // loop on failed CAS
+            }
+            if (h == head)                   // loop if head changed
+                break;
+        }
+    }
+
+    /**
      * Sets head of queue, and checks if successor may be waiting
-     * in shared mode, if so propagating if propagate > 0.
+     * in shared mode, if so propagating if either propagate > 0 or
+     * PROPAGATE status was set.
      *
-     * @param pred the node holding waitStatus for node
      * @param node the node
      * @param propagate the return value from a tryAcquireShared
      */
     private void setHeadAndPropagate(Node node, int propagate) {
+        Node h = head; // Record old head for check below
         setHead(node);
-        if (propagate > 0 && node.waitStatus != 0) {
-            /*
-             * Don't bother fully figuring out successor.  If it
-             * looks null, call unparkSuccessor anyway to be safe.
-             */
+        /*
+         * Try to signal next queued node if:
+         *   Propagation was indicated by caller,
+         *     or was recorded (as h.waitStatus) by a previous operation
+         *     (note: this uses sign-check of waitStatus because
+         *      PROPAGATE status may transition to SIGNAL.)
+         * and
+         *   The next node is waiting in shared mode,
+         *     or we don't know, because it appears null
+         *
+         * The conservatism in both of these checks may cause
+         * unnecessary wake-ups, but only when there are multiple
+         * racing acquires/releases, so most need signals now or soon
+         * anyway.
+         */
+        if (propagate > 0 || h == null || h.waitStatus < 0) {
             Node s = node.next;
             if (s == null || s.isShared())
-                unparkSuccessor(node);
+                doReleaseShared();
         }
     }
 
@@ -688,23 +749,27 @@
         while (pred.waitStatus > 0)
             node.prev = pred = pred.prev;
 
-        // Getting this before setting waitStatus ensures staleness
+        // predNext is the apparent node to unsplice. CASes below will
+        // fail if not, in which case, we lost race vs another cancel
+        // or signal, so no further action is necessary.
         Node predNext = pred.next;
 
-        // Can use unconditional write instead of CAS here
+        // Can use unconditional write instead of CAS here.
+        // After this atomic step, other Nodes can skip past us.
+        // Before, we are free of interference from other threads.
         node.waitStatus = Node.CANCELLED;
 
-        // If we are the tail, remove ourselves
+        // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
             compareAndSetNext(pred, predNext, null);
         } else {
-            // If "active" predecessor found...
-            if (pred != head
-                && (pred.waitStatus == Node.SIGNAL
-                    || compareAndSetWaitStatus(pred, 0, Node.SIGNAL))
-                && pred.thread != null) {
-
-                // If successor is active, set predecessor's next link
+            // If successor needs signal, try to set pred's next-link
+            // so it will get one. Otherwise wake it up to propagate.
+            int ws;
+            if (pred != head &&
+                ((ws = pred.waitStatus) == Node.SIGNAL ||
+                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+                pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
                     compareAndSetNext(pred, predNext, next);
@@ -726,14 +791,14 @@
      * @return {@code true} if thread should block
      */
     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
-        int s = pred.waitStatus;
-        if (s < 0)
+        int ws = pred.waitStatus;
+        if (ws == Node.SIGNAL)
             /*
              * This node has already set status asking a release
              * to signal it, so it can safely park.
              */
             return true;
-        if (s > 0) {
+        if (ws > 0) {
             /*
              * Predecessor was cancelled. Skip over predecessors and
              * indicate retry.
@@ -742,14 +807,14 @@
                 node.prev = pred = pred.prev;
             } while (pred.waitStatus > 0);
             pred.next = node;
+        } else {
+            /*
+             * waitStatus must be 0 or PROPAGATE.  Indicate that we
+             * need a signal, but don't park yet.  Caller will need to
+             * retry to make sure it cannot acquire before parking.
+             */
+            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
         }
-        else
-            /*
-             * Indicate that we need a signal, but don't park yet. Caller
-             * will need to retry to make sure it cannot acquire before
-             * parking.
-             */
-            compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
         return false;
     }
 
@@ -1269,9 +1334,7 @@
      */
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
-            Node h = head;
-            if (h != null && h.waitStatus != 0)
-                unparkSuccessor(h);
+            doReleaseShared();
             return true;
         }
         return false;
@@ -1613,8 +1676,8 @@
          * case the waitStatus can be transiently and harmlessly wrong).
          */
         Node p = enq(node);
-        int c = p.waitStatus;
-        if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
+        int ws = p.waitStatus;
+        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
--- a/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Tue Apr 14 16:51:38 2009 +0100
@@ -276,7 +276,7 @@
          * Maintained as a ThreadLocal; cached in cachedHoldCounter
          */
         static final class HoldCounter {
-            int count;
+            int count = 0;
             // Use id, not reference, to avoid garbage retention
             final long tid = Thread.currentThread().getId();
         }
@@ -293,8 +293,9 @@
         }
 
         /**
-         * The number of read locks held by current thread.
+         * The number of reentrant read locks held by current thread.
          * Initialized only in constructor and readObject.
+         * Removed whenever a thread's read hold count drops to 0.
          */
         private transient ThreadLocalHoldCounter readHolds;
 
@@ -304,17 +305,35 @@
          * where the next thread to release is the last one to
          * acquire. This is non-volatile since it is just used
          * as a heuristic, and would be great for threads to cache.
+         *
+         * <p>Can outlive the Thread for which it is caching the read
+         * hold count, but avoids garbage retention by not retaining a
+         * reference to the Thread.
+         *
+         * <p>Accessed via a benign data race; relies on the memory
+         * model's final field and out-of-thin-air guarantees.
          */
         private transient HoldCounter cachedHoldCounter;
 
         /**
          * firstReader is the first thread to have acquired the read lock.
          * firstReaderHoldCount is firstReader's hold count.
-         * This allows tracking of read holds for uncontended read
+         *
+         * <p>More precisely, firstReader is the unique thread that last
+         * changed the shared count from 0 to 1, and has not released the
+         * read lock since then; null if there is no such thread.
+         *
+         * <p>Cannot cause garbage retention unless the thread terminated
+         * without relinquishing its read locks, since tryReleaseShared
+         * sets it to null.
+         *
+         * <p>Accessed via a benign data race; relies on the memory
+         * model's out-of-thin-air guarantees for references.
+         *
+         * <p>This allows tracking of read holds for uncontended read
          * locks to be very cheap.
          */
-        private final static long INVALID_THREAD_ID = -1;
-        private transient long firstReader = INVALID_THREAD_ID;
+        private transient Thread firstReader = null;
         private transient int firstReaderHoldCount;
 
         Sync() {
@@ -393,16 +412,16 @@
         }
 
         protected final boolean tryReleaseShared(int unused) {
-            long tid = Thread.currentThread().getId();
-            if (firstReader == tid) {
+            Thread current = Thread.currentThread();
+            if (firstReader == current) {
                 // assert firstReaderHoldCount > 0;
                 if (firstReaderHoldCount == 1)
-                    firstReader = INVALID_THREAD_ID;
+                    firstReader = null;
                 else
                     firstReaderHoldCount--;
             } else {
                 HoldCounter rh = cachedHoldCounter;
-                if (rh == null || rh.tid != tid)
+                if (rh == null || rh.tid != current.getId())
                     rh = readHolds.get();
                 int count = rh.count;
                 if (count <= 1) {
@@ -416,6 +435,9 @@
                 int c = getState();
                 int nextc = c - SHARED_UNIT;
                 if (compareAndSetState(c, nextc))
+                    // Releasing the read lock has no effect on readers,
+                    // but it may allow waiting writers to proceed if
+                    // both read and write locks are now free.
                     return nextc == 0;
             }
         }
@@ -450,15 +472,14 @@
             if (!readerShouldBlock() &&
                 r < MAX_COUNT &&
                 compareAndSetState(c, c + SHARED_UNIT)) {
-                long tid = current.getId();
                 if (r == 0) {
-                    firstReader = tid;
+                    firstReader = current;
                     firstReaderHoldCount = 1;
-                } else if (firstReader == tid) {
+                } else if (firstReader == current) {
                     firstReaderHoldCount++;
                 } else {
                     HoldCounter rh = cachedHoldCounter;
-                    if (rh == null || rh.tid != tid)
+                    if (rh == null || rh.tid != current.getId())
                         cachedHoldCounter = rh = readHolds.get();
                     else if (rh.count == 0)
                         readHolds.set(rh);
@@ -485,19 +506,17 @@
                 int c = getState();
                 if (exclusiveCount(c) != 0) {
                     if (getExclusiveOwnerThread() != current)
-                        //if (removeNeeded) readHolds.remove();
                         return -1;
                     // else we hold the exclusive lock; blocking here
                     // would cause deadlock.
                 } else if (readerShouldBlock()) {
                     // Make sure we're not acquiring read lock reentrantly
-                    long tid = current.getId();
-                    if (firstReader == tid) {
+                    if (firstReader == current) {
                         // assert firstReaderHoldCount > 0;
                     } else {
                         if (rh == null) {
                             rh = cachedHoldCounter;
-                            if (rh == null || rh.tid != tid) {
+                            if (rh == null || rh.tid != current.getId()) {
                                 rh = readHolds.get();
                                 if (rh.count == 0)
                                     readHolds.remove();
@@ -510,25 +529,20 @@
                 if (sharedCount(c) == MAX_COUNT)
                     throw new Error("Maximum lock count exceeded");
                 if (compareAndSetState(c, c + SHARED_UNIT)) {
-                    long tid = current.getId();
                     if (sharedCount(c) == 0) {
-                        firstReader = tid;
+                        firstReader = current;
                         firstReaderHoldCount = 1;
-                    } else if (firstReader == tid) {
+                    } else if (firstReader == current) {
                         firstReaderHoldCount++;
                     } else {
-                        if (rh == null) {
+                        if (rh == null)
                             rh = cachedHoldCounter;
-                            if (rh != null && rh.tid == tid) {
-                                if (rh.count == 0)
-                                    readHolds.set(rh);
-                            } else {
-                                rh = readHolds.get();
-                            }
-                        } else if (rh.count == 0)
+                        if (rh == null || rh.tid != current.getId())
+                            rh = readHolds.get();
+                        else if (rh.count == 0)
                             readHolds.set(rh);
+                        rh.count++;
                         cachedHoldCounter = rh; // cache for release
-                        rh.count++;
                     }
                     return 1;
                 }
@@ -572,15 +586,14 @@
                 if (r == MAX_COUNT)
                     throw new Error("Maximum lock count exceeded");
                 if (compareAndSetState(c, c + SHARED_UNIT)) {
-                    long tid = current.getId();
                     if (r == 0) {
-                        firstReader = tid;
+                        firstReader = current;
                         firstReaderHoldCount = 1;
-                    } else if (firstReader == tid) {
+                    } else if (firstReader == current) {
                         firstReaderHoldCount++;
                     } else {
                         HoldCounter rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != tid)
+                        if (rh == null || rh.tid != current.getId())
                             cachedHoldCounter = rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -626,12 +639,12 @@
             if (getReadLockCount() == 0)
                 return 0;
 
-            long tid = Thread.currentThread().getId();
-            if (firstReader == tid)
+            Thread current = Thread.currentThread();
+            if (firstReader == current)
                 return firstReaderHoldCount;
 
             HoldCounter rh = cachedHoldCounter;
-            if (rh != null && rh.tid == tid)
+            if (rh != null && rh.tid == current.getId())
                 return rh.count;
 
             int count = readHolds.get().count;
@@ -647,7 +660,6 @@
             throws java.io.IOException, ClassNotFoundException {
             s.defaultReadObject();
             readHolds = new ThreadLocalHoldCounter();
-            firstReader = INVALID_THREAD_ID;
             setState(0); // reset to unlocked state
         }
 
--- a/src/share/classes/java/util/logging/LogManager.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/logging/LogManager.java	Tue Apr 14 16:51:38 2009 +0100
@@ -215,6 +215,14 @@
     // This private class is used as a shutdown hook.
     // It does a "reset" to close all open handlers.
     private class Cleaner extends Thread {
+
+        private Cleaner() {
+            /* Set context class loader to null in order to avoid
+             * keeping a strong reference to an application classloader.
+             */
+            this.setContextClassLoader(null);
+        }
+
         public void run() {
             // This is to ensure the LogManager.<clinit> is completed
             // before synchronized block. Otherwise deadlocks are possible.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/zip/ZipConstants64.java	Tue Apr 14 16:51:38 2009 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright 1995-1996 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.zip;
+
+/*
+ * This class defines the constants that are used by the classes
+ * which manipulate Zip64 files.
+ */
+
+class ZipConstants64 {
+
+    /*
+     * ZIP64 constants
+     */
+    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
+    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
+    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
+    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
+    static final int  ZIP64_EXTHDR = 24;           // EXT header size
+    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
+
+    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
+    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
+
+    /*
+     * Zip64 End of central directory (END) header field offsets
+     */
+    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
+    static final int  ZIP64_ENDVEM = 12;      // version made by
+    static final int  ZIP64_ENDVER = 14;      // version needed to extract
+    static final int  ZIP64_ENDNMD = 16;      // number of this disk
+    static final int  ZIP64_ENDDSK = 20;      // disk number of start
+    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
+    static final int  ZIP64_ENDTOT = 32;      // total number of entries
+    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
+    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
+    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
+
+    /*
+     * Zip64 End of central directory locator field offsets
+     */
+    static final int  ZIP64_LOCDSK = 4;       // disk number start
+    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
+    static final int  ZIP64_LOCTOT = 16;      // total number of disks
+
+    /*
+     * Zip64 Extra local (EXT) header field offsets
+     */
+    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
+    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
+    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
+
+    private ZipConstants64() {}
+}
--- a/src/share/classes/java/util/zip/ZipEntry.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/zip/ZipEntry.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -144,11 +144,13 @@
      * Sets the uncompressed size of the entry data.
      * @param size the uncompressed size in bytes
      * @exception IllegalArgumentException if the specified size is less
-     *            than 0 or greater than 0xFFFFFFFF bytes
+     *            than 0, is greater than 0xFFFFFFFF when
+     *            <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
+     *            or is less than 0 when ZIP64 is supported
      * @see #getSize()
      */
     public void setSize(long size) {
-        if (size < 0 || size > 0xFFFFFFFFL) {
+        if (size < 0) {
             throw new IllegalArgumentException("invalid entry size");
         }
         this.size = size;
--- a/src/share/classes/java/util/zip/ZipInputStream.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/zip/ZipInputStream.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.io.EOFException;
 import java.io.PushbackInputStream;
+import static java.util.zip.ZipConstants64.*;
 
 /**
  * This class implements an input stream filter for reading files in the
@@ -285,6 +286,29 @@
             byte[] bb = new byte[len];
             readFully(bb, 0, len);
             e.setExtra(bb);
+            // extra fields are in "HeaderID(2)DataSize(2)Data... format
+            if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
+                int off = 0;
+                while (off + 4 < len) {
+                    int sz = get16(bb, off + 2);
+                    if (get16(bb, off) == ZIP64_EXTID) {
+                        off += 4;
+                        // LOC extra zip64 entry MUST include BOTH original and
+                        // compressed file size fields
+                        if (sz < 16 || (off + sz) > len ) {
+                            // Invalid zip64 extra fields, simply skip. Even it's
+                            // rare, it's possible the entry size happens to be
+                            // the magic value and it "accidnetly" has some bytes
+                            // in extra match the id.
+                            return e;
+                        }
+                        e.size = get64(bb, off);
+                        e.csize = get64(bb, off + 8);
+                        break;
+                    }
+                    off += (sz + 4);
+                }
+            }
         }
         return e;
     }
@@ -375,18 +399,36 @@
         }
         if ((flag & 8) == 8) {
             /* "Data Descriptor" present */
-            readFully(tmpbuf, 0, EXTHDR);
-            long sig = get32(tmpbuf, 0);
-            if (sig != EXTSIG) { // no EXTSIG present
-                e.crc = sig;
-                e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
-                e.size = get32(tmpbuf, EXTLEN - EXTCRC);
-                ((PushbackInputStream)in).unread(
-                                           tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
+            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
+                inf.getBytesRead() > ZIP64_MAGICVAL) {
+                // ZIP64 format
+                readFully(tmpbuf, 0, ZIP64_EXTHDR);
+                long sig = get32(tmpbuf, 0);
+                if (sig != EXTSIG) { // no EXTSIG present
+                    e.crc = sig;
+                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
+                    e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
+                    ((PushbackInputStream)in).unread(
+                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
+                } else {
+                    e.crc = get32(tmpbuf, ZIP64_EXTCRC);
+                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
+                    e.size = get64(tmpbuf, ZIP64_EXTLEN);
+                }
             } else {
-                e.crc = get32(tmpbuf, EXTCRC);
-                e.csize = get32(tmpbuf, EXTSIZ);
-                e.size = get32(tmpbuf, EXTLEN);
+                readFully(tmpbuf, 0, EXTHDR);
+                long sig = get32(tmpbuf, 0);
+                if (sig != EXTSIG) { // no EXTSIG present
+                    e.crc = sig;
+                    e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
+                    e.size = get32(tmpbuf, EXTLEN - EXTCRC);
+                    ((PushbackInputStream)in).unread(
+                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
+                } else {
+                    e.crc = get32(tmpbuf, EXTCRC);
+                    e.csize = get32(tmpbuf, EXTSIZ);
+                    e.size = get32(tmpbuf, EXTLEN);
+                }
             }
         }
         if (e.size != inf.getBytesWritten()) {
@@ -433,6 +475,14 @@
      * The bytes are assumed to be in Intel (little-endian) byte order.
      */
     private static final long get32(byte b[], int off) {
-        return get16(b, off) | ((long)get16(b, off+2) << 16);
+        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
+    }
+
+    /*
+     * Fetches signed 64-bit value from byte array at specified offset.
+     * The bytes are assumed to be in Intel (little-endian) byte order.
+     */
+    private static final long get64(byte b[], int off) {
+        return get32(b, off) | (get32(b, off+4) << 32);
     }
 }
--- a/src/share/classes/java/util/zip/ZipOutputStream.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/zip/ZipOutputStream.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.util.Vector;
 import java.util.HashSet;
+import static java.util.zip.ZipConstants64.*;
 
 /**
  * This class implements an output stream filter for writing files in the
@@ -343,26 +344,52 @@
     private void writeLOC(XEntry xentry) throws IOException {
         ZipEntry e = xentry.entry;
         int flag = xentry.flag;
+        int elen = (e.extra != null) ? e.extra.length : 0;
+        boolean hasZip64 = false;
+
         writeInt(LOCSIG);           // LOC header signature
-        writeShort(version(e));     // version needed to extract
-        writeShort(flag);           // general purpose bit flag
-        writeShort(e.method);       // compression method
-        writeInt(e.time);           // last modification time
+
         if ((flag & 8) == 8) {
+            writeShort(version(e));     // version needed to extract
+            writeShort(flag);           // general purpose bit flag
+            writeShort(e.method);       // compression method
+            writeInt(e.time);           // last modification time
+
             // store size, uncompressed size, and crc-32 in data descriptor
             // immediately following compressed entry data
             writeInt(0);
             writeInt(0);
             writeInt(0);
         } else {
-            writeInt(e.crc);        // crc-32
-            writeInt(e.csize);      // compressed size
-            writeInt(e.size);       // uncompressed size
+            if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
+                hasZip64 = true;
+                writeShort(45);         // ver 4.5 for zip64
+            } else {
+                writeShort(version(e)); // version needed to extract
+            }
+            writeShort(flag);           // general purpose bit flag
+            writeShort(e.method);       // compression method
+            writeInt(e.time);           // last modification time
+            writeInt(e.crc);            // crc-32
+            if (hasZip64) {
+                writeInt(ZIP64_MAGICVAL);
+                writeInt(ZIP64_MAGICVAL);
+                elen += 20;        //headid(2) + size(2) + size(8) + csize(8)
+            } else {
+                writeInt(e.csize);  // compressed size
+                writeInt(e.size);   // uncompressed size
+            }
         }
         byte[] nameBytes = getUTF8Bytes(e.name);
         writeShort(nameBytes.length);
-        writeShort(e.extra != null ? e.extra.length : 0);
+        writeShort(elen);
         writeBytes(nameBytes, 0, nameBytes.length);
+        if (hasZip64) {
+            writeShort(ZIP64_EXTID);
+            writeShort(16);
+            writeLong(e.size);
+            writeLong(e.csize);
+        }
         if (e.extra != null) {
             writeBytes(e.extra, 0, e.extra.length);
         }
@@ -375,8 +402,13 @@
     private void writeEXT(ZipEntry e) throws IOException {
         writeInt(EXTSIG);           // EXT header signature
         writeInt(e.crc);            // crc-32
-        writeInt(e.csize);          // compressed size
-        writeInt(e.size);           // uncompressed size
+        if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
+            writeLong(e.csize);
+            writeLong(e.size);
+        } else {
+            writeInt(e.csize);          // compressed size
+            writeInt(e.size);           // uncompressed size
+        }
     }
 
     /*
@@ -387,18 +419,49 @@
         ZipEntry e  = xentry.entry;
         int flag = xentry.flag;
         int version = version(e);
+
+        long csize = e.csize;
+        long size = e.size;
+        long offset = xentry.offset;
+        int e64len = 0;
+        boolean hasZip64 = false;
+        if (e.csize >= ZIP64_MAGICVAL) {
+            csize = ZIP64_MAGICVAL;
+            e64len += 8;              // csize(8)
+            hasZip64 = true;
+        }
+        if (e.size >= ZIP64_MAGICVAL) {
+            size = ZIP64_MAGICVAL;    // size(8)
+            e64len += 8;
+            hasZip64 = true;
+        }
+        if (xentry.offset >= ZIP64_MAGICVAL) {
+            offset = ZIP64_MAGICVAL;
+            e64len += 8;              // offset(8)
+            hasZip64 = true;
+        }
         writeInt(CENSIG);           // CEN header signature
-        writeShort(version);        // version made by
-        writeShort(version);        // version needed to extract
+        if (hasZip64) {
+            writeShort(45);         // ver 4.5 for zip64
+            writeShort(45);
+        } else {
+            writeShort(version);    // version made by
+            writeShort(version);    // version needed to extract
+        }
         writeShort(flag);           // general purpose bit flag
         writeShort(e.method);       // compression method
         writeInt(e.time);           // last modification time
         writeInt(e.crc);            // crc-32
-        writeInt(e.csize);          // compressed size
-        writeInt(e.size);           // uncompressed size
+        writeInt(csize);            // compressed size
+        writeInt(size);             // uncompressed size
         byte[] nameBytes = getUTF8Bytes(e.name);
         writeShort(nameBytes.length);
-        writeShort(e.extra != null ? e.extra.length : 0);
+        if (hasZip64) {
+            // + headid(2) + datasize(2)
+            writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0));
+        } else {
+            writeShort(e.extra != null ? e.extra.length : 0);
+        }
         byte[] commentBytes;
         if (e.comment != null) {
             commentBytes = getUTF8Bytes(e.comment);
@@ -410,8 +473,18 @@
         writeShort(0);              // starting disk number
         writeShort(0);              // internal file attributes (unused)
         writeInt(0);                // external file attributes (unused)
-        writeInt(xentry.offset);    // relative offset of local header
+        writeInt(offset);           // relative offset of local header
         writeBytes(nameBytes, 0, nameBytes.length);
+        if (hasZip64) {
+            writeShort(ZIP64_EXTID);// Zip64 extra
+            writeShort(e64len);
+            if (size == ZIP64_MAGICVAL)
+                writeLong(e.size);
+            if (csize == ZIP64_MAGICVAL)
+                writeLong(e.csize);
+            if (offset == ZIP64_MAGICVAL)
+                writeLong(xentry.offset);
+        }
         if (e.extra != null) {
             writeBytes(e.extra, 0, e.extra.length);
         }
@@ -424,15 +497,50 @@
      * Writes end of central directory (END) header.
      */
     private void writeEND(long off, long len) throws IOException {
+        boolean hasZip64 = false;
+        long xlen = len;
+        long xoff = off;
+        if (xlen >= ZIP64_MAGICVAL) {
+            xlen = ZIP64_MAGICVAL;
+            hasZip64 = true;
+        }
+        if (xoff >= ZIP64_MAGICVAL) {
+            xoff = ZIP64_MAGICVAL;
+            hasZip64 = true;
+        }
         int count = xentries.size();
-        writeInt(ENDSIG);           // END record signature
-        writeShort(0);              // number of this disk
-        writeShort(0);              // central directory start disk
-        writeShort(count);          // number of directory entries on disk
-        writeShort(count);          // total number of directory entries
-        writeInt(len);              // length of central directory
-        writeInt(off);              // offset of central directory
-        if (comment != null) {      // zip file comment
+        if (count >= ZIP64_MAGICCOUNT) {
+            count = ZIP64_MAGICCOUNT;
+            hasZip64 = true;
+        }
+        if (hasZip64) {
+            long off64 = written;
+            //zip64 end of central directory record
+            writeInt(ZIP64_ENDSIG);        // zip64 END record signature
+            writeLong(ZIP64_ENDHDR - 12);  // size of zip64 end
+            writeShort(45);                // version made by
+            writeShort(45);                // version needed to extract
+            writeInt(0);                   // number of this disk
+            writeInt(0);                   // central directory start disk
+            writeLong(xentries.size());    // number of directory entires on disk
+            writeLong(xentries.size());    // number of directory entires
+            writeLong(len);                // length of central directory
+            writeLong(off);                // offset of central directory
+
+            //zip64 end of central directory locator
+            writeInt(ZIP64_LOCSIG);        // zip64 END locator signature
+            writeInt(0);                   // zip64 END start disk
+            writeLong(off64);              // offset of zip64 END
+            writeInt(1);                   // total number of disks (?)
+        }
+        writeInt(ENDSIG);                 // END record signature
+        writeShort(0);                    // number of this disk
+        writeShort(0);                    // central directory start disk
+        writeShort(count);                // number of directory entries on disk
+        writeShort(count);                // total number of directory entries
+        writeInt(xlen);                   // length of central directory
+        writeInt(xoff);                   // offset of central directory
+        if (comment != null) {            // zip file comment
             byte[] b = getUTF8Bytes(comment);
             writeShort(b.length);
             writeBytes(b, 0, b.length);
@@ -464,6 +572,22 @@
     }
 
     /*
+     * Writes a 64-bit int to the output stream in little-endian byte order.
+     */
+    private void writeLong(long v) throws IOException {
+        OutputStream out = this.out;
+        out.write((int)((v >>>  0) & 0xff));
+        out.write((int)((v >>>  8) & 0xff));
+        out.write((int)((v >>> 16) & 0xff));
+        out.write((int)((v >>> 24) & 0xff));
+        out.write((int)((v >>> 32) & 0xff));
+        out.write((int)((v >>> 40) & 0xff));
+        out.write((int)((v >>> 48) & 0xff));
+        out.write((int)((v >>> 56) & 0xff));
+        written += 8;
+    }
+
+    /*
      * Writes an array of bytes to the output stream.
      */
     private void writeBytes(byte[] b, int off, int len) throws IOException {
--- a/src/share/classes/java/util/zip/package.html	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/java/util/zip/package.html	Tue Apr 14 16:51:38 2009 +0100
@@ -46,6 +46,13 @@
       </a> - a detailed description of the Info-ZIP format upon which
       the <code>java.util.zip</code> classes are based.
 <p>
+  <a name="zip64">
+  <li>An implementation may optionally support the ZIP64(tm) format extensions
+      defined by the 
+      <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
+      PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
+      are used to overcome the size limitations of the original ZIP format.
+<p>
   <li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
       ZLIB Compressed Data Format Specification version 3.3</a>
       &nbsp;
@@ -70,7 +77,6 @@
   <li>CRC-32 checksum is described in RFC 1952 (above)
 <p>
   <li>Adler-32 checksum is described in RFC 1950 (above)
-
 </ul>
 
 
--- a/src/share/classes/javax/imageio/ImageTypeSpecifier.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/imageio/ImageTypeSpecifier.java	Tue Apr 14 16:51:38 2009 +0100
@@ -67,126 +67,13 @@
      * <code>BufferedImage</code> types.
      */
     private static ImageTypeSpecifier[] BISpecifier;
-
+    private static ColorSpace sRGB;
     // Initialize the standard specifiers
     static {
-        ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 
         BISpecifier =
             new ImageTypeSpecifier[BufferedImage.TYPE_BYTE_INDEXED + 1];
-
-        BISpecifier[BufferedImage.TYPE_CUSTOM] = null;
-
-        BISpecifier[BufferedImage.TYPE_INT_RGB] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0x0,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_INT_ARGB] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0xff000000,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_INT_ARGB_PRE] =
-            createPacked(sRGB,
-                         0x00ff0000,
-                         0x0000ff00,
-                         0x000000ff,
-                         0xff000000,
-                         DataBuffer.TYPE_INT,
-                         true);
-
-        BISpecifier[BufferedImage.TYPE_INT_BGR] =
-            createPacked(sRGB,
-                         0x000000ff,
-                         0x0000ff00,
-                         0x00ff0000,
-                         0x0,
-                         DataBuffer.TYPE_INT,
-                         false);
-
-        int[] bOffsRGB = { 2, 1, 0 };
-        BISpecifier[BufferedImage.TYPE_3BYTE_BGR] =
-            createInterleaved(sRGB,
-                              bOffsRGB,
-                              DataBuffer.TYPE_BYTE,
-                              false,
-                              false);
-
-        int[] bOffsABGR = { 3, 2, 1, 0 };
-        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR] =
-            createInterleaved(sRGB,
-                              bOffsABGR,
-                              DataBuffer.TYPE_BYTE,
-                              true,
-                              false);
-
-        BISpecifier[BufferedImage.TYPE_4BYTE_ABGR_PRE] =
-            createInterleaved(sRGB,
-                              bOffsABGR,
-                              DataBuffer.TYPE_BYTE,
-                              true,
-                              true);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_565_RGB] =
-            createPacked(sRGB,
-                         0xF800,
-                         0x07E0,
-                         0x001F,
-                         0x0,
-                         DataBuffer.TYPE_USHORT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_555_RGB] =
-            createPacked(sRGB,
-                         0x7C00,
-                         0x03E0,
-                         0x001F,
-                         0x0,
-                         DataBuffer.TYPE_USHORT,
-                         false);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_GRAY] =
-            createGrayscale(8,
-                            DataBuffer.TYPE_BYTE,
-                            false);
-
-        BISpecifier[BufferedImage.TYPE_USHORT_GRAY] =
-            createGrayscale(16,
-                            DataBuffer.TYPE_USHORT,
-                            false);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_BINARY] =
-            createGrayscale(1,
-                            DataBuffer.TYPE_BYTE,
-                            false);
-
-        BufferedImage bi =
-            new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
-        IndexColorModel icm = (IndexColorModel)bi.getColorModel();
-        int mapSize = icm.getMapSize();
-        byte[] redLUT = new byte[mapSize];
-        byte[] greenLUT = new byte[mapSize];
-        byte[] blueLUT = new byte[mapSize];
-        byte[] alphaLUT = new byte[mapSize];
-
-        icm.getReds(redLUT);
-        icm.getGreens(greenLUT);
-        icm.getBlues(blueLUT);
-        icm.getAlphas(alphaLUT);
-
-        BISpecifier[BufferedImage.TYPE_BYTE_INDEXED] =
-            createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
-                          8,
-                          DataBuffer.TYPE_BYTE);
     }
 
     /**
@@ -1011,7 +898,7 @@
         ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
         if (bufferedImageType >= BufferedImage.TYPE_INT_RGB &&
             bufferedImageType <= BufferedImage.TYPE_BYTE_INDEXED) {
-            return BISpecifier[bufferedImageType];
+            return getSpecifier(bufferedImageType);
         } else if (bufferedImageType == BufferedImage.TYPE_CUSTOM) {
             throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
         } else {
@@ -1041,7 +928,7 @@
         if (image instanceof BufferedImage) {
             int bufferedImageType = ((BufferedImage)image).getType();
             if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
-                return BISpecifier[bufferedImageType];
+                return getSpecifier(bufferedImageType);
             }
         }
 
@@ -1225,4 +1112,130 @@
     public int hashCode() {
         return (9 * colorModel.hashCode()) + (14 * sampleModel.hashCode());
     }
+
+    private static ImageTypeSpecifier getSpecifier(int type) {
+        if (BISpecifier[type] == null) {
+            BISpecifier[type] = createSpecifier(type);
+        }
+        return BISpecifier[type];
+    }
+
+    private static ImageTypeSpecifier createSpecifier(int type) {
+        switch(type) {
+          case BufferedImage.TYPE_INT_RGB:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0x0,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_INT_ARGB:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0xff000000,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_INT_ARGB_PRE:
+              return createPacked(sRGB,
+                                  0x00ff0000,
+                                  0x0000ff00,
+                                  0x000000ff,
+                                  0xff000000,
+                                  DataBuffer.TYPE_INT,
+                                  true);
+
+          case BufferedImage.TYPE_INT_BGR:
+              return createPacked(sRGB,
+                                  0x000000ff,
+                                  0x0000ff00,
+                                  0x00ff0000,
+                                  0x0,
+                                  DataBuffer.TYPE_INT,
+                                  false);
+
+          case BufferedImage.TYPE_3BYTE_BGR:
+              return createInterleaved(sRGB,
+                                       new int[] { 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       false,
+                                       false);
+
+          case BufferedImage.TYPE_4BYTE_ABGR:
+              return createInterleaved(sRGB,
+                                       new int[] { 3, 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       true,
+                                       false);
+
+          case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+              return createInterleaved(sRGB,
+                                       new int[] { 3, 2, 1, 0 },
+                                       DataBuffer.TYPE_BYTE,
+                                       true,
+                                       true);
+
+          case BufferedImage.TYPE_USHORT_565_RGB:
+              return createPacked(sRGB,
+                                  0xF800,
+                                  0x07E0,
+                                  0x001F,
+                                  0x0,
+                                  DataBuffer.TYPE_USHORT,
+                                  false);
+
+          case BufferedImage.TYPE_USHORT_555_RGB:
+              return createPacked(sRGB,
+                                  0x7C00,
+                                  0x03E0,
+                                  0x001F,
+                                  0x0,
+                                  DataBuffer.TYPE_USHORT,
+                                  false);
+
+          case BufferedImage.TYPE_BYTE_GRAY:
+            return createGrayscale(8,
+                                   DataBuffer.TYPE_BYTE,
+                                   false);
+
+          case BufferedImage.TYPE_USHORT_GRAY:
+            return createGrayscale(16,
+                                   DataBuffer.TYPE_USHORT,
+                                   false);
+
+          case BufferedImage.TYPE_BYTE_BINARY:
+              return createGrayscale(1,
+                                     DataBuffer.TYPE_BYTE,
+                                     false);
+
+          case BufferedImage.TYPE_BYTE_INDEXED:
+          {
+
+              BufferedImage bi =
+                  new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
+              IndexColorModel icm = (IndexColorModel)bi.getColorModel();
+              int mapSize = icm.getMapSize();
+              byte[] redLUT = new byte[mapSize];
+              byte[] greenLUT = new byte[mapSize];
+              byte[] blueLUT = new byte[mapSize];
+              byte[] alphaLUT = new byte[mapSize];
+
+              icm.getReds(redLUT);
+              icm.getGreens(greenLUT);
+              icm.getBlues(blueLUT);
+              icm.getAlphas(alphaLUT);
+
+              return createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
+                                   8,
+                                   DataBuffer.TYPE_BYTE);
+          }
+          default:
+              throw new IllegalArgumentException("Invalid BufferedImage type!");
+        }
+    }
+
 }
--- a/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/imageio/metadata/IIOMetadataFormat.java	Tue Apr 14 16:51:38 2009 +0100
@@ -242,8 +242,12 @@
 
     /**
      * A constant returned by <code>getAttributeDataType</code>
-     * indicating that the value of an attribute is one of 'true' or
-     * 'false'.
+     * indicating that the value of an attribute is one of the boolean
+     * values 'true' or 'false'.
+     * Attribute values of type DATATYPE_BOOLEAN should be marked as
+     * enumerations, and the permitted values should be the string
+     * literal values "TRUE" or "FALSE", although a plugin may also
+     * recognise lower or mixed case equivalents.
      */
     int DATATYPE_BOOLEAN = 1;
 
--- a/src/share/classes/javax/management/monitor/CounterMonitor.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/management/monitor/CounterMonitor.java	Tue Apr 14 16:51:38 2009 +0100
@@ -599,7 +599,7 @@
      */
     @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/management/monitor/GaugeMonitor.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/management/monitor/GaugeMonitor.java	Tue Apr 14 16:51:38 2009 +0100
@@ -481,7 +481,7 @@
      */
     @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/management/monitor/Monitor.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/management/monitor/Monitor.java	Tue Apr 14 16:51:38 2009 +0100
@@ -32,7 +32,10 @@
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -163,7 +166,10 @@
     /**
      * AccessControlContext of the Monitor.start() caller.
      */
-    private AccessControlContext acc;
+    private static final AccessControlContext noPermissionsACC =
+            new AccessControlContext(
+            new ProtectionDomain[] {new ProtectionDomain(null, null)});
+    private volatile AccessControlContext acc = noPermissionsACC;
 
     /**
      * Scheduler Service.
@@ -173,14 +179,20 @@
             new DaemonThreadFactory("Scheduler"));
 
     /**
+     * Map containing the thread pool executor per thread group.
+     */
+    private static final Map<ThreadPoolExecutor, Void> executors =
+            new WeakHashMap<ThreadPoolExecutor, Void>();
+
+    /**
+     * Lock for executors map.
+     */
+    private static final Object executorsLock = new Object();
+
+    /**
      * Maximum Pool Size
      */
     private static final int maximumPoolSize;
-
-    /**
-     * Executor Service.
-     */
-    private static final ThreadPoolExecutor executor;
     static {
         final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
         final String maximumPoolSizeStr = AccessController.doPrivileged(
@@ -210,22 +222,9 @@
                 maximumPoolSize = maximumPoolSizeTmp;
             }
         }
-        executor = new ThreadPoolExecutor(
-                maximumPoolSize,
-                maximumPoolSize,
-                60L,
-                TimeUnit.SECONDS,
-                new LinkedBlockingQueue<Runnable>(),
-                new DaemonThreadFactory("Executor"));
-        executor.allowCoreThreadTimeOut(true);
     }
 
     /**
-     * Monitor task to be executed by the Executor Service.
-     */
-    private final MonitorTask monitorTask = new MonitorTask();
-
-    /**
      * Future associated to the current monitor task.
      */
     private Future<?> monitorFuture;
@@ -233,7 +232,7 @@
     /**
      * Scheduler task to be executed by the Scheduler Service.
      */
-    private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);
+    private final SchedulerTask schedulerTask = new SchedulerTask();
 
     /**
      * ScheduledFuture associated to the current scheduler task.
@@ -719,6 +718,7 @@
             // Start the scheduler.
             //
             cleanupFutures();
+            schedulerTask.setMonitorTask(new MonitorTask());
             schedulerFuture = scheduler.schedule(schedulerTask,
                                                  getGranularityPeriod(),
                                                  TimeUnit.MILLISECONDS);
@@ -748,7 +748,7 @@
 
             // Reset the AccessControlContext.
             //
-            acc = null;
+            acc = noPermissionsACC;
 
             // Reset the complex type attribute information
             // such that it is recalculated again.
@@ -1467,7 +1467,7 @@
      */
     private class SchedulerTask implements Runnable {
 
-        private Runnable task = null;
+        private MonitorTask task;
 
         /*
          * ------------------------------------------
@@ -1475,7 +1475,16 @@
          * ------------------------------------------
          */
 
-        public SchedulerTask(Runnable task) {
+        public SchedulerTask() {
+        }
+
+        /*
+         * ------------------------------------------
+         *  GETTERS/SETTERS
+         * ------------------------------------------
+         */
+
+        public void setMonitorTask(MonitorTask task) {
             this.task = task;
         }
 
@@ -1487,7 +1496,7 @@
 
         public void run() {
             synchronized (Monitor.this) {
-                Monitor.this.monitorFuture = executor.submit(task);
+                Monitor.this.monitorFuture = task.submit();
             }
         }
     }
@@ -1500,6 +1509,8 @@
      */
     private class MonitorTask implements Runnable {
 
+        private ThreadPoolExecutor executor;
+
         /*
          * ------------------------------------------
          *  CONSTRUCTORS
@@ -1507,6 +1518,38 @@
          */
 
         public MonitorTask() {
+            // Find out if there's already an existing executor for the calling
+            // thread and reuse it. Otherwise, create a new one and store it in
+            // the executors map. If there is a SecurityManager, the group of
+            // System.getSecurityManager() is used, else the group of the thread
+            // instantiating this MonitorTask, i.e. the group of the thread that
+            // calls "Monitor.start()".
+            SecurityManager s = System.getSecurityManager();
+            ThreadGroup group = (s != null) ? s.getThreadGroup() :
+                Thread.currentThread().getThreadGroup();
+            synchronized (executorsLock) {
+                for (ThreadPoolExecutor e : executors.keySet()) {
+                    DaemonThreadFactory tf =
+                            (DaemonThreadFactory) e.getThreadFactory();
+                    ThreadGroup tg = tf.getThreadGroup();
+                    if (tg == group) {
+                        executor = e;
+                        break;
+                    }
+                }
+                if (executor == null) {
+                    executor = new ThreadPoolExecutor(
+                            maximumPoolSize,
+                            maximumPoolSize,
+                            60L,
+                            TimeUnit.SECONDS,
+                            new LinkedBlockingQueue<Runnable>(),
+                            new DaemonThreadFactory("ThreadGroup<" +
+                            group.getName() + "> Executor", group));
+                    executor.allowCoreThreadTimeOut(true);
+                    executors.put(executor, null);
+                }
+            }
         }
 
         /*
@@ -1515,12 +1558,18 @@
          * ------------------------------------------
          */
 
+        public Future<?> submit() {
+            return executor.submit(this);
+        }
+
         public void run() {
             final ScheduledFuture<?> sf;
+            final AccessControlContext ac;
             synchronized (Monitor.this) {
                 sf = Monitor.this.schedulerFuture;
+                ac = Monitor.this.acc;
             }
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
                 public Void run() {
                     if (Monitor.this.isActive()) {
                         final int an[] = alreadyNotifieds;
@@ -1533,7 +1582,11 @@
                     }
                     return null;
                 }
-            }, Monitor.this.acc);
+            };
+            if (ac == null) {
+                throw new SecurityException("AccessControlContext cannot be null");
+            }
+            AccessController.doPrivileged(action, ac);
             synchronized (Monitor.this) {
                 if (Monitor.this.isActive() &&
                     Monitor.this.schedulerFuture == sf) {
@@ -1573,6 +1626,15 @@
             namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
         }
 
+        public DaemonThreadFactory(String poolName, ThreadGroup threadGroup) {
+            group = threadGroup;
+            namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
+        }
+
+        public ThreadGroup getThreadGroup() {
+            return group;
+        }
+
         public Thread newThread(Runnable r) {
             Thread t = new Thread(group,
                                   r,
--- a/src/share/classes/javax/management/monitor/StringMonitor.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/management/monitor/StringMonitor.java	Tue Apr 14 16:51:38 2009 +0100
@@ -184,6 +184,7 @@
      * @return The derived gauge of the specified object.
      *
      */
+    @Override
     public synchronized String getDerivedGauge(ObjectName object) {
         return (String) super.getDerivedGauge(object);
     }
@@ -199,6 +200,7 @@
      * @return The derived gauge timestamp of the specified object.
      *
      */
+    @Override
     public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
         return super.getDerivedGaugeTimeStamp(object);
     }
@@ -341,8 +343,9 @@
      * the Java class of the notification and the notification types sent by
      * the string monitor.
      */
+    @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/print/attribute/standard/MediaSize.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/javax/print/attribute/standard/MediaSize.java	Tue Apr 14 16:51:38 2009 +0100
@@ -123,8 +123,10 @@
         if (x > y) {
             throw new IllegalArgumentException("X dimension > Y dimension");
         }
-        mediaName = media;
-        mediaMap.put(mediaName, this);
+        if (media != null && mediaMap.get(media) == null) {
+            mediaName = media;
+            mediaMap.put(mediaName, this);
+        }
         sizeVector.add(this);
     }
 
@@ -147,8 +149,10 @@
         if (x > y) {
             throw new IllegalArgumentException("X dimension > Y dimension");
         }
-        mediaName = media;
-        mediaMap.put(mediaName, this);
+        if (media != null && mediaMap.get(media) == null) {
+            mediaName = media;
+            mediaMap.put(mediaName, this);
+        }
         sizeVector.add(this);
     }
 
--- a/src/share/classes/sun/awt/FontConfiguration.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/awt/FontConfiguration.java	Tue Apr 14 16:51:38 2009 +0100
@@ -98,7 +98,7 @@
         if (!inited) {
             this.preferLocaleFonts = false;
             this.preferPropFonts = false;
-            fontConfig = this;      /* static initialization */
+            setFontConfiguration();
             readFontConfigFile(fontConfigFile);
             initFontConfig();
             inited = true;
@@ -1244,6 +1244,10 @@
         return fontConfig;
     }
 
+    protected void setFontConfiguration() {
+        fontConfig = this;      /* static initialization */
+    }
+
     //////////////////////////////////////////////////////////////////////
     // FontConfig data tables and the index constants in binary file    //
     //////////////////////////////////////////////////////////////////////
--- a/src/share/classes/sun/awt/image/GifImageDecoder.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/awt/image/GifImageDecoder.java	Tue Apr 14 16:51:38 2009 +0100
@@ -585,9 +585,16 @@
             System.out.print("Reading a " + width + " by " + height + " " +
                       (interlace ? "" : "non-") + "interlaced image...");
         }
-
+        int initCodeSize = ExtractByte(block, 9);
+        if (initCodeSize >= 12) {
+            if (verbose) {
+                System.out.println("Invalid initial code size: " +
+                                   initCodeSize);
+            }
+            return false;
+        }
         boolean ret = parseImage(x, y, width, height,
-                                 interlace, ExtractByte(block, 9),
+                                 interlace, initCodeSize,
                                  block, rasline, model);
 
         if (!ret) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/font/CreatedFontTracker.java	Tue Apr 14 16:51:38 2009 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+public class CreatedFontTracker {
+
+    public static final int MAX_FILE_SIZE = 32 * 1024 * 1024;
+    public static final int MAX_TOTAL_BYTES = 10 * MAX_FILE_SIZE;
+
+    static int numBytes;
+    static CreatedFontTracker tracker;
+
+    public static synchronized CreatedFontTracker getTracker() {
+        if (tracker == null) {
+            tracker = new CreatedFontTracker();
+        }
+        return tracker;
+    }
+
+    public synchronized int getNumBytes() {
+        return numBytes;
+    }
+
+    public synchronized void addBytes(int sz) {
+        numBytes += sz;
+    }
+
+    public synchronized void subBytes(int sz) {
+        numBytes -= sz;
+    }
+}
--- a/src/share/classes/sun/font/FileFont.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/FileFont.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -125,9 +125,9 @@
         return true;
     }
 
-    void setFileToRemove(File file) {
+    void setFileToRemove(File file, CreatedFontTracker tracker) {
         Disposer.addObjectRecord(this,
-                                 new CreatedFontFileDisposerRecord(file));
+                         new CreatedFontFileDisposerRecord(file, tracker));
     }
 
     /* This is called when a font scaler is determined to
@@ -246,12 +246,16 @@
         return getScaler().getUnitsPerEm();
     }
 
-    private static class CreatedFontFileDisposerRecord implements DisposerRecord {
+    private static class CreatedFontFileDisposerRecord
+        implements DisposerRecord {
 
         File fontFile = null;
+        CreatedFontTracker tracker;
 
-        private CreatedFontFileDisposerRecord(File file) {
+        private CreatedFontFileDisposerRecord(File file,
+                                              CreatedFontTracker tracker) {
             fontFile = file;
+            this.tracker = tracker;
         }
 
         public void dispose() {
@@ -260,6 +264,9 @@
                       public Object run() {
                           if (fontFile != null) {
                               try {
+                                  if (tracker != null) {
+                                      tracker.subBytes((int)fontFile.length());
+                                  }
                                   /* REMIND: is it possible that the file is
                                    * still open? It will be closed when the
                                    * font2D is disposed but could this code
--- a/src/share/classes/sun/font/FileFontStrike.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/FileFontStrike.java	Tue Apr 14 16:51:38 2009 +0100
@@ -26,6 +26,7 @@
 package sun.font;
 
 import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
 import java.awt.Font;
 import java.awt.GraphicsEnvironment;
 import java.awt.Rectangle;
@@ -842,8 +843,36 @@
         return fileFont.getGlyphOutlineBounds(pScalerContext, glyphCode);
     }
 
+    private
+        WeakReference<ConcurrentHashMap<Integer,GeneralPath>> outlineMapRef;
+
     GeneralPath getGlyphOutline(int glyphCode, float x, float y) {
-        return fileFont.getGlyphOutline(pScalerContext, glyphCode, x, y);
+
+        GeneralPath gp = null;
+        ConcurrentHashMap<Integer, GeneralPath> outlineMap = null;
+
+        if (outlineMapRef != null) {
+            outlineMap = outlineMapRef.get();
+            if (outlineMap != null) {
+                gp = (GeneralPath)outlineMap.get(glyphCode);
+            }
+        }
+
+        if (gp == null) {
+            gp = fileFont.getGlyphOutline(pScalerContext, glyphCode, 0, 0);
+            if (outlineMap == null) {
+                outlineMap = new ConcurrentHashMap<Integer, GeneralPath>();
+                outlineMapRef =
+                   new WeakReference
+                       <ConcurrentHashMap<Integer,GeneralPath>>(outlineMap);
+            }
+            outlineMap.put(glyphCode, gp);
+        }
+        gp = (GeneralPath)gp.clone(); // mutable!
+        if (x != 0f || y != 0f) {
+            gp.transform(AffineTransform.getTranslateInstance(x, y));
+        }
+        return gp;
     }
 
     GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) {
--- a/src/share/classes/sun/font/FontManager.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/FontManager.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1601,18 +1601,27 @@
     /* Path may be absolute or a base file name relative to one of
      * the platform font directories
      */
-    private static String getPathName(String s) {
+    private static String getPathName(final String s) {
         File f = new File(s);
         if (f.isAbsolute()) {
             return s;
         } else if (pathDirs.length==1) {
             return pathDirs[0] + File.separator + s;
         } else {
-            for (int p=0; p<pathDirs.length; p++) {
-                f = new File(pathDirs[p] + File.separator + s);
-                if (f.exists()) {
-                    return f.getAbsolutePath();
-                }
+            String path = java.security.AccessController.doPrivileged(
+                 new java.security.PrivilegedAction<String>() {
+                     public String run() {
+                         for (int p=0; p<pathDirs.length; p++) {
+                             File f = new File(pathDirs[p] +File.separator+ s);
+                             if (f.exists()) {
+                                 return f.getAbsolutePath();
+                             }
+                         }
+                         return null;
+                     }
+                });
+            if (path != null) {
+                return path;
             }
         }
         return s; // shouldn't happen, but harmless
@@ -2348,19 +2357,21 @@
     static Vector<File> tmpFontFiles = null;
 
     public static Font2D createFont2D(File fontFile, int fontFormat,
-                                      boolean isCopy)
+				      boolean isCopy,
+				      CreatedFontTracker tracker)
         throws FontFormatException {
 
         String fontFilePath = fontFile.getPath();
         FileFont font2D = null;
         final File fFile = fontFile;
+        final CreatedFontTracker _tracker = tracker;
         try {
             switch (fontFormat) {
             case Font.TRUETYPE_FONT:
                 font2D = new TrueTypeFont(fontFilePath, null, 0, true);
                 break;
             case Font.TYPE1_FONT:
-                font2D = new Type1Font(fontFilePath, null);
+                font2D = new Type1Font(fontFilePath, null, isCopy);
                 break;
             default:
                 throw new FontFormatException("Unrecognised Font Format");
@@ -2370,6 +2381,9 @@
                 java.security.AccessController.doPrivileged(
                      new java.security.PrivilegedAction() {
                           public Object run() {
+                              if (_tracker != null) {
+                                  _tracker.subBytes((int)fFile.length());
+                              }
                               fFile.delete();
                               return null;
                           }
@@ -2378,7 +2392,7 @@
             throw(e);
         }
         if (isCopy) {
-            font2D.setFileToRemove(fontFile);
+            font2D.setFileToRemove(fontFile, tracker);
             synchronized (FontManager.class) {
 
                 if (tmpFontFiles == null) {
--- a/src/share/classes/sun/font/GlyphLayout.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/GlyphLayout.java	Tue Apr 14 16:51:38 2009 +0100
@@ -338,6 +338,8 @@
                     cache = new ConcurrentHashMap<SDKey, SDCache>(10);
                     cacheRef = new
                        SoftReference<ConcurrentHashMap<SDKey, SDCache>>(cache);
+                } else if (cache.size() >= 512) {
+                    cache.clear();
                 }
                 cache.put(key, res);
             }
--- a/src/share/classes/sun/font/StrikeCache.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/StrikeCache.java	Tue Apr 14 16:51:38 2009 +0100
@@ -232,6 +232,16 @@
             if (disposer.pScalerContext != 0L) {
                 freeLongMemory(new long[0], disposer.pScalerContext);
             }
+        } else if (disposer.pScalerContext != 0L) {
+            /* Rarely a strike may have been created that never cached
+             * any glyphs. In this case we still want to free the scaler
+             * context.
+             */
+            if (FontManager.longAddresses) {
+                freeLongMemory(new long[0], disposer.pScalerContext);
+            } else {
+                freeIntMemory(new int[0], disposer.pScalerContext);
+            }
         }
     }
 
--- a/src/share/classes/sun/font/TrueTypeFont.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/TrueTypeFont.java	Tue Apr 14 16:51:38 2009 +0100
@@ -175,8 +175,17 @@
         super(platname, nativeNames);
         useJavaRasterizer = javaRasterizer;
         fontRank = Font2D.TTF_RANK;
-        verify();
-        init(fIndex);
+        try {
+            verify();
+            init(fIndex);
+        } catch (Throwable t) {
+            close();
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            } else {
+                throw new FontFormatException("Unexpected runtime exception.");
+            }
+        }
         Disposer.addObjectRecord(this, disposerRecord);
     }
 
--- a/src/share/classes/sun/font/Type1Font.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/font/Type1Font.java	Tue Apr 14 16:51:38 2009 +0100
@@ -39,6 +39,7 @@
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
 import java.util.HashSet;
 import java.util.HashMap;
 import java.awt.Font;
@@ -76,6 +77,27 @@
  */
 public class Type1Font extends FileFont {
 
+     private static class T1DisposerRecord  implements DisposerRecord {
+        String fileName = null;
+
+        T1DisposerRecord(String name) {
+            fileName = name;
+        }
+
+        public synchronized void dispose() {
+            java.security.AccessController.doPrivileged(
+	        new java.security.PrivilegedAction() {
+	            public Object run() {
+
+                        if (fileName != null) {
+                            (new java.io.File(fileName)).delete();
+                        }
+                        return null;
+		    }
+	     });
+        }
+    }
+
     WeakReference bufferRef = new WeakReference(null);
 
     private String psName = null;
@@ -125,18 +147,42 @@
 
 
     /**
+     * Constructs a Type1 Font.
+     * @param platname - Platform identifier of the font. Typically file name.
+     * @param nativeNames - Native names - typically XLFDs on Unix.
+     */
+    public Type1Font(String platname, Object nativeNames)
+        throws FontFormatException {
+
+        this(platname, nativeNames, false);
+    }
+
+    /**
      * - does basic verification of the file
      * - reads the names (full, family).
      * - determines the style of the font.
      * @throws FontFormatException - if the font can't be opened
      * or fails verification,  or there's no usable cmap
      */
-    public Type1Font(String platname, Object nativeNames)
+    public Type1Font(String platname, Object nativeNames, boolean createdCopy)
         throws FontFormatException {
         super(platname, nativeNames);
         fontRank = Font2D.TYPE1_RANK;
         checkedNatives = true;
-        verify();
+        try {
+            verify();
+        } catch (Throwable t) {
+            if (createdCopy) {
+                T1DisposerRecord ref = new T1DisposerRecord(platname);
+                Disposer.addObjectRecord(bufferRef, ref);
+                bufferRef = null;
+            }
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            } else {
+                throw new FontFormatException("Unexpected runtime exception.");
+            }
+        }
     }
 
     private synchronized ByteBuffer getBuffer() throws FontFormatException {
--- a/src/share/classes/sun/java2d/cmm/ProfileActivator.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/java2d/cmm/ProfileActivator.java	Tue Apr 14 16:51:38 2009 +0100
@@ -25,6 +25,7 @@
 
 package sun.java2d.cmm;
 
+import java.awt.color.ProfileDataException;
 
 /**
  * An interface to allow the ProfileDeferralMgr to activate a
@@ -35,6 +36,6 @@
     /**
      * Activate a previously deferred ICC_Profile object.
      */
-    public void activate();
+    public void activate() throws ProfileDataException;
 
 }
--- a/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/java2d/cmm/ProfileDeferralMgr.java	Tue Apr 14 16:51:38 2009 +0100
@@ -25,6 +25,7 @@
 
 package sun.java2d.cmm;
 
+import java.awt.color.ProfileDataException;
 import java.util.Vector;
 
 
@@ -39,7 +40,7 @@
 public class ProfileDeferralMgr {
 
     public static boolean deferring = true;
-    private static Vector aVector;
+    private static Vector<ProfileActivator> aVector;
 
     /**
      * Records a ProfileActivator object whose activate method will
@@ -51,7 +52,7 @@
             return;
         }
         if (aVector == null) {
-            aVector = new Vector(3, 3);
+            aVector = new Vector<ProfileActivator>(3, 3);
         }
         aVector.addElement(pa);
         return;
@@ -89,8 +90,26 @@
             return;
         }
         n = aVector.size();
-        for (i = 0; i < n; i++) {
-            ((ProfileActivator) aVector.get(i)).activate();
+        for (ProfileActivator pa : aVector) {
+            try {
+                pa.activate();
+            } catch (ProfileDataException e) {
+                /*
+                 * Ignore profile activation error for now:
+                 * such exception is pssible due to absence
+                 * or corruption of standard color profile.
+                 * As for now we expect all profiles should
+                 * be shiped with jre and presence of this
+                 * exception is indication of some configuration
+                 * problem in jre installation.
+                 *
+                 * NB: we still are greedy loading deferred profiles
+                 * and load them all if any of them is needed.
+                 * Therefore broken profile (if any) might be never used.
+                 * If there will be attempt to use broken profile then
+                 * it will result in CMMException.
+                 */
+            }
         }
         aVector.removeAllElements();
         aVector = null;
--- a/src/share/classes/sun/java2d/pisces/Dasher.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/java2d/pisces/Dasher.java	Tue Apr 14 16:51:38 2009 +0100
@@ -120,7 +120,7 @@
 
         // Normalize so 0 <= phase < dash[0]
         int idx = 0;
-        dashOn = false;
+        dashOn = true;
         int d;
         while (phase >= (d = dash[idx])) {
             phase -= d;
--- a/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Tue Apr 14 16:51:38 2009 +0100
@@ -245,6 +245,7 @@
                              FloatToS15_16(coords[1]));
                 break;
             case PathIterator.SEG_CLOSE:
+                lsink.lineJoin();
                 lsink.close();
                 break;
             default:
--- a/src/share/classes/sun/misc/Launcher.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/misc/Launcher.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,10 @@
      * The class loader used for loading installed extensions.
      */
     static class ExtClassLoader extends URLClassLoader {
-        private File[] dirs;
+
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
 
         /**
          * create an ExtClassLoader. The ExtClassLoader is created
@@ -146,12 +149,12 @@
                         }
                     });
             } catch (java.security.PrivilegedActionException e) {
-                    throw (IOException) e.getException();
+                throw (IOException) e.getException();
             }
         }
 
         void addExtURL(URL url) {
-                super.addURL(url);
+            super.addURL(url);
         }
 
         /*
@@ -159,7 +162,6 @@
          */
         public ExtClassLoader(File[] dirs) throws IOException {
             super(getExtURLs(dirs), null, factory);
-            this.dirs = dirs;
         }
 
         private static File[] getExtDirs() {
@@ -206,20 +208,27 @@
          */
         public String findLibrary(String name) {
             name = System.mapLibraryName(name);
-            for (int i = 0; i < dirs.length; i++) {
-                // Look in architecture-specific subdirectory first
-                String arch = System.getProperty("os.arch");
-                if (arch != null) {
-                    File file = new File(new File(dirs[i], arch), name);
+            URL[] urls = super.getURLs();
+            File prevDir = null;
+            for (int i = 0; i < urls.length; i++) {
+                // Get the ext directory from the URL
+                File dir = new File(urls[i].getPath()).getParentFile();
+                if (dir != null && !dir.equals(prevDir)) {
+                    // Look in architecture-specific subdirectory first
+                    String arch = System.getProperty("os.arch");
+                    if (arch != null) {
+                        File file = new File(new File(dir, arch), name);
+                        if (file.exists()) {
+                            return file.getAbsolutePath();
+                        }
+                    }
+                    // Then check the extension directory
+                    File file = new File(dir, name);
                     if (file.exists()) {
                         return file.getAbsolutePath();
                     }
                 }
-                // Then check the extension directory
-                File file = new File(dirs[i], name);
-                if (file.exists()) {
-                    return file.getAbsolutePath();
-                }
+                prevDir = dir;
             }
             return null;
         }
@@ -248,6 +257,10 @@
      */
     static class AppClassLoader extends URLClassLoader {
 
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+
         public static ClassLoader getAppClassLoader(final ClassLoader extcl)
             throws IOException
         {
@@ -281,7 +294,7 @@
         /**
          * Override loadClass so we can checkPackageAccess.
          */
-        public synchronized Class loadClass(String name, boolean resolve)
+        public Class loadClass(String name, boolean resolve)
             throws ClassNotFoundException
         {
             int i = name.lastIndexOf('.');
--- a/src/share/classes/sun/net/httpserver/Request.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/net/httpserver/Request.java	Tue Apr 14 16:51:38 2009 +0100
@@ -52,6 +52,9 @@
         os = rawout;
         do {
             startLine = readLine();
+            if (startLine == null) {
+                return;
+            }
             /* skip blank lines */
         } while (startLine == null ? false : startLine.equals (""));
     }
--- a/src/share/classes/sun/net/httpserver/ServerImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/net/httpserver/ServerImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -433,6 +433,7 @@
                         rawin = sslStreams.getInputStream();
                         rawout = sslStreams.getOutputStream();
                         engine = sslStreams.getSSLEngine();
+                        connection.sslStreams = sslStreams;
                     } else {
                         rawin = new BufferedInputStream(
                             new Request.ReadStream (
@@ -442,6 +443,8 @@
                             ServerImpl.this, chan
                         );
                     }
+                    connection.raw = rawin;
+                    connection.rawout = rawout;
                 }
                 Request req = new Request (rawin, rawout);
                 requestLine = req.requestLine();
--- a/src/share/classes/sun/net/spi/DefaultProxySelector.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/net/spi/DefaultProxySelector.java	Tue Apr 14 16:51:38 2009 +0100
@@ -78,7 +78,6 @@
     };
 
     private static boolean hasSystemProxies = false;
-    private static Properties defprops = new Properties();
 
     static {
         final String key = "java.net.useSystemProxies";
@@ -107,6 +106,9 @@
         RegexpPool hostsPool;
         String property;
 
+        static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
+        static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
+
         NonProxyInfo(String p, String s, RegexpPool pool) {
             property = p;
             hostsSource = s;
@@ -114,8 +116,6 @@
         }
     }
 
-    private static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
-    private static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
 
     /**
      * select() method. Where all the hard work is done.
@@ -175,13 +175,13 @@
         NonProxyInfo pinfo = null;
 
         if ("http".equalsIgnoreCase(protocol)) {
-            pinfo = httpNonProxyInfo;
+            pinfo = NonProxyInfo.httpNonProxyInfo;
         } else if ("https".equalsIgnoreCase(protocol)) {
             // HTTPS uses the same property as HTTP, for backward
             // compatibility
-            pinfo = httpNonProxyInfo;
+            pinfo = NonProxyInfo.httpNonProxyInfo;
         } else if ("ftp".equalsIgnoreCase(protocol)) {
-            pinfo = ftpNonProxyInfo;
+            pinfo = NonProxyInfo.ftpNonProxyInfo;
         }
 
         /**
@@ -334,7 +334,6 @@
         }
     }
 
-    private static final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
     private boolean isLoopback(String host) {
         if (host == null || host.length() == 0)
             return false;
@@ -364,6 +363,7 @@
         }
 
         if (host.endsWith(":1")) {
+            final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
             return p6.matcher(host).matches();
         }
         return false;
--- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -37,6 +37,7 @@
 import java.util.Collections;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import sun.net.NetHooks;
 
 /**
  * Base implementation of AsynchronousServerSocketChannel.
@@ -131,6 +132,7 @@
             synchronized (stateLock) {
                 if (localAddress != null)
                     throw new AlreadyBoundException();
+                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
                 Net.bind(fd, isa.getAddress(), isa.getPort());
                 Net.listen(fd, backlog < 1 ? 50 : backlog);
                 localAddress = Net.localAddress(fd);
--- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -38,6 +38,7 @@
 import java.util.Collections;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
+import sun.net.NetHooks;
 
 /**
  * Base implementation of AsynchronousSocketChannel
@@ -387,6 +388,7 @@
                     throw new AlreadyBoundException();
                 InetSocketAddress isa = (local == null) ?
                     new InetSocketAddress(0) : Net.checkAddress(local);
+                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
                 Net.bind(fd, isa.getAddress(), isa.getPort());
                 localAddress = Net.localAddress(fd);
             }
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -313,11 +313,9 @@
             throw new NullPointerException();
         synchronized (readLock) {
             ensureOpen();
-            // If socket is not bound then behave as if nothing received
-            // Will be fixed by 6621699
-            if (localAddress() == null) {
-                return null;
-            }
+            // Socket was not bound before attempting receive
+            if (localAddress() == null)
+                bind(null);
             int n = 0;
             ByteBuffer bb = null;
             try {
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -128,9 +128,10 @@
             throw new NonReadableChannelException();
         synchronized (positionLock) {
             int n = 0;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return 0;
                 do {
@@ -151,9 +152,10 @@
             throw new NonReadableChannelException();
         synchronized (positionLock) {
             long n = 0;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return 0;
                 do {
@@ -183,9 +185,10 @@
             throw new NonWritableChannelException();
         synchronized (positionLock) {
             int n = 0;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return 0;
                 do {
@@ -206,9 +209,10 @@
             throw new NonWritableChannelException();
         synchronized (positionLock) {
             long n = 0;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return 0;
                 do {
@@ -239,9 +243,10 @@
         ensureOpen();
         synchronized (positionLock) {
             long p = -1;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return 0;
                 do {
@@ -262,9 +267,10 @@
             throw new IllegalArgumentException();
         synchronized (positionLock) {
             long p = -1;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return null;
                 do {
@@ -283,9 +289,10 @@
         ensureOpen();
         synchronized (positionLock) {
             long s = -1;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return -1;
                 do {
@@ -311,9 +318,10 @@
         synchronized (positionLock) {
             int rv = -1;
             long p = -1;
-            int ti = threads.add();
+            int ti = -1;
             try {
                 begin();
+                ti = threads.add();
                 if (!isOpen())
                     return null;
 
@@ -350,9 +358,10 @@
     public void force(boolean metaData) throws IOException {
         ensureOpen();
         int rv = -1;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return;
             do {
@@ -406,9 +415,10 @@
             return IOStatus.UNSUPPORTED;
 
         long n = -1;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return -1;
             do {
@@ -612,9 +622,10 @@
             throw new NonReadableChannelException();
         ensureOpen();
         int n = 0;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return -1;
             do {
@@ -637,9 +648,10 @@
             throw new NonWritableChannelException();
         ensureOpen();
         int n = 0;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return -1;
             do {
@@ -731,9 +743,10 @@
             throw new NonReadableChannelException();
 
         long addr = -1;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return null;
             if (size() < position + size) { // Extend file size
@@ -900,9 +913,10 @@
         FileLockTable flt = fileLockTable();
         flt.add(fli);
         boolean i = true;
-        int ti = threads.add();
+        int ti = -1;
         try {
             begin();
+            ti = threads.add();
             if (!isOpen())
                 return null;
             int result = nd.lock(fd, true, position, size, shared);
--- a/src/share/classes/sun/nio/ch/SelChImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/SelChImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -25,6 +25,7 @@
 
 package sun.nio.ch;
 
+import java.nio.channels.Channel;
 import java.io.FileDescriptor;
 import java.io.IOException;
 
@@ -35,7 +36,7 @@
  * @since 1.4
  */
 
-interface SelChImpl {
+interface SelChImpl extends Channel {
 
     FileDescriptor getFD();
 
--- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -31,6 +31,7 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
+import sun.net.NetHooks;
 
 
 /**
@@ -191,6 +192,7 @@
             SecurityManager sm = System.getSecurityManager();
             if (sm != null)
                 sm.checkListen(isa.getPort());
+            NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
             Net.bind(fd, isa.getAddress(), isa.getPort());
             Net.listen(fd, backlog < 1 ? 50 : backlog);
             synchronized (stateLock) {
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Apr 14 16:51:38 2009 +0100
@@ -32,6 +32,7 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
+import sun.net.NetHooks;
 
 
 /**
@@ -526,6 +527,7 @@
                         throw new AlreadyBoundException();
                     InetSocketAddress isa = (local == null) ?
                         new InetSocketAddress(0) : Net.checkAddress(local);
+                    NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
                     Net.bind(fd, isa.getAddress(), isa.getPort());
                     localAddress = Net.localAddress(fd);
                 }
@@ -577,6 +579,12 @@
                                 if (!isOpen()) {
                                     return false;
                                 }
+                                // notify hook only if unbound
+                                if (localAddress == null) {
+                                    NetHooks.beforeTcpConnect(fd,
+                                                           isa.getAddress(),
+                                                           isa.getPort());
+                                }
                                 readerThread = NativeThread.current();
                             }
                             for (;;) {
--- a/src/share/classes/sun/print/ServiceDialog.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/print/ServiceDialog.java	Tue Apr 14 16:51:38 2009 +0100
@@ -2149,55 +2149,51 @@
                         }
                     }
                 }
-
-                rbPortrait.setEnabled(pSupported);
-                rbLandscape.setEnabled(lSupported);
-                rbRevPortrait.setEnabled(rpSupported);
-                rbRevLandscape.setEnabled(rlSupported);
-
-                OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
-                if (or == null ||
-                    !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
-
-                    or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
-                    // need to validate if default is not supported
-                    if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
-                        or = null;
-                        values =
-                            psCurrent.getSupportedAttributeValues(orCategory,
-                                                                  docFlavor,
-                                                                  asCurrent);
-                        if (values instanceof OrientationRequested[]) {
-                            OrientationRequested[] orValues =
-                                                (OrientationRequested[])values;
-                            if (orValues.length > 1) {
-                                // get the first in the list
-                                or = orValues[0];
-                            }
+            }
+
+
+            rbPortrait.setEnabled(pSupported);
+            rbLandscape.setEnabled(lSupported);
+            rbRevPortrait.setEnabled(rpSupported);
+            rbRevLandscape.setEnabled(rlSupported);
+
+            OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
+            if (or == null ||
+                !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
+
+                or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
+                // need to validate if default is not supported
+                if ((or != null) &&
+                   !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
+                    or = null;
+                    Object values =
+                        psCurrent.getSupportedAttributeValues(orCategory,
+                                                              docFlavor,
+                                                              asCurrent);
+                    if (values instanceof OrientationRequested[]) {
+                        OrientationRequested[] orValues =
+                                            (OrientationRequested[])values;
+                        if (orValues.length > 1) {
+                            // get the first in the list
+                            or = orValues[0];
                         }
                     }
-
-                    if (or == null) {
-                        or = OrientationRequested.PORTRAIT;
-                    }
-                    asCurrent.add(or);
                 }
 
-                if (or == OrientationRequested.PORTRAIT) {
-                    rbPortrait.setSelected(true);
-                } else if (or == OrientationRequested.LANDSCAPE) {
-                    rbLandscape.setSelected(true);
-                } else if (or == OrientationRequested.REVERSE_PORTRAIT) {
-                    rbRevPortrait.setSelected(true);
-                } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
-                    rbRevLandscape.setSelected(true);
+                if (or == null) {
+                    or = OrientationRequested.PORTRAIT;
                 }
-                } else {
-                rbPortrait.setEnabled(pSupported);
-                rbLandscape.setEnabled(lSupported);
-                rbRevPortrait.setEnabled(rpSupported);
-                rbRevLandscape.setEnabled(rlSupported);
-
+                asCurrent.add(or);
+            }
+
+            if (or == OrientationRequested.PORTRAIT) {
+                rbPortrait.setSelected(true);
+            } else if (or == OrientationRequested.LANDSCAPE) {
+                rbLandscape.setSelected(true);
+            } else if (or == OrientationRequested.REVERSE_PORTRAIT) {
+                rbRevPortrait.setSelected(true);
+            } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
+                rbRevLandscape.setSelected(true);
             }
         }
     }
--- a/src/share/classes/sun/security/jca/ProviderConfig.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/security/jca/ProviderConfig.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,37 +60,6 @@
     // use by doLoadProvider()
     private final static Class[] CL_STRING = { String.class };
 
-    // lock to use while loading a provider. it ensures that each provider
-    // is loaded only once and that we can detect recursion.
-    // NOTE that because of 4944382 we use the system classloader as lock.
-    // By using the same lock to load classes as to load providers we avoid
-    // deadlock due to lock ordering. However, this class may be initialized
-    // early in the startup when the system classloader has not yet been set
-    // up. Use a temporary lock object if that is the case.
-    // Any of this may break if the class loading implementation is changed.
-    private static volatile Object LOCK = new Object();
-
-    private static Object getLock() {
-        Object o = LOCK;
-        // check if lock is already set to the class loader
-        if (o instanceof ClassLoader) {
-            return o;
-        }
-        Object cl = AccessController.doPrivileged(
-                                new PrivilegedAction<Object>() {
-            public Object run() {
-                return ClassLoader.getSystemClassLoader();
-            }
-        });
-        // check if class loader initialized now (non-null)
-        if (cl != null) {
-            LOCK = cl;
-            o = cl;
-        }
-        return o;
-    }
-
-
     // name of the provider class
     private final String className;
 
@@ -194,7 +163,7 @@
     /**
      * Get the provider object. Loads the provider if it is not already loaded.
      */
-    Provider getProvider() {
+    synchronized Provider getProvider() {
         // volatile variable load
         Provider p = provider;
         if (p != null) {
@@ -203,30 +172,23 @@
         if (shouldLoad() == false) {
             return null;
         }
-        synchronized (getLock()) {
-            p = provider;
-            if (p != null) {
-                // loaded by another thread while we were blocked on lock
-                return p;
+        if (isLoading) {
+            // because this method is synchronized, this can only
+            // happen if there is recursion.
+            if (debug != null) {
+                debug.println("Recursion loading provider: " + this);
+                new Exception("Call trace").printStackTrace();
             }
-            if (isLoading) {
-                // because this method is synchronized, this can only
-                // happen if there is recursion.
-                if (debug != null) {
-                    debug.println("Recursion loading provider: " + this);
-                    new Exception("Call trace").printStackTrace();
-                }
-                return null;
-            }
-            try {
-                isLoading = true;
-                tries++;
-                p = doLoadProvider();
-            } finally {
-                isLoading = false;
-            }
-            provider = p;
+            return null;
         }
+        try {
+            isLoading = true;
+            tries++;
+            p = doLoadProvider();
+        } finally {
+            isLoading = false;
+        }
+        provider = p;
         return p;
     }
 
--- a/src/share/classes/sun/security/tools/JarSigner.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/security/tools/JarSigner.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,28 +32,44 @@
 import java.math.BigInteger;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.SocketTimeoutException;
 import java.text.Collator;
 import java.text.MessageFormat;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
 import java.security.*;
 import java.lang.reflect.Constructor;
 
 import com.sun.jarsigner.ContentSigner;
 import com.sun.jarsigner.ContentSignerParameters;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.util.Map.Entry;
 import sun.security.x509.*;
 import sun.security.util.*;
 import sun.misc.BASE64Encoder;
 
+
 /**
  * <p>The jarsigner utility.
  *
+ * The exit codes for the main method are:
+ *
+ * 0: success
+ * 1: any error that the jar cannot be signed or verified, including:
+ *      keystore loading error
+ *      TSP communciation error
+ *      jarsigner command line error...
+ * otherwise: error codes from -strict
+ *
  * @author Roland Schemers
  * @author Jan Luehe
  */
@@ -84,8 +100,6 @@
 
     // Attention:
     // This is the entry that get launched by the security tool jarsigner.
-    // It's marked as exported private per AppServer Team's request.
-    // See http://ccc.sfbay/6428446
     public static void main(String args[]) throws Exception {
         JarSigner js = new JarSigner();
         js.run(args);
@@ -93,31 +107,32 @@
 
     static final String VERSION = "1.0";
 
-    static final int IN_KEYSTORE = 0x01;
+    static final int IN_KEYSTORE = 0x01;        // signer is in keystore
     static final int IN_SCOPE = 0x02;
+    static final int NOT_ALIAS = 0x04;          // alias list is NOT empty and
+                                                // signer is not in alias list
+    static final int SIGNED_BY_ALIAS = 0x08;    // signer is in alias list
 
-    // signer's certificate chain (when composing)
-    X509Certificate[] certChain;
-
-    /*
-     * private key
-     */
-    PrivateKey privateKey;
-    KeyStore store;
+    X509Certificate[] certChain;    // signer's cert chain (when composing)
+    PrivateKey privateKey;          // private key
+    KeyStore store;                 // the keystore specified by -keystore
+                                    // or the default keystore, never null
 
     IdentityScope scope;
 
     String keystore; // key store file
     boolean nullStream = false; // null keystore input stream (NONE)
     boolean token = false; // token-based keystore
-    String jarfile;  // jar file to sign
+    String jarfile;  // jar file to sign or verify
     String alias;    // alias to sign jar with
+    List<String> ckaliases = new ArrayList<String>(); // aliases in -verify
     char[] storepass; // keystore password
     boolean protectedPath; // protected authentication path
     String storetype; // keystore type
     String providerName; // provider name
     Vector<String> providers = null; // list of providers
-    HashMap<String,String> providerArgs = new HashMap<String, String>(); // arguments for provider constructors
+    // arguments for provider constructors
+    HashMap<String,String> providerArgs = new HashMap<String, String>();
     char[] keypass; // private key password
     String sigfile; // name of .SF file
     String sigalg; // name of signature algorithm
@@ -125,12 +140,14 @@
     String signedjar; // output filename
     String tsaUrl; // location of the Timestamping Authority
     String tsaAlias; // alias for the Timestamping Authority's certificate
+    String altCertChain; // file to read alternative cert chain from
     boolean verify = false; // verify the jar
-    boolean verbose = false; // verbose output when signing/verifying
+    String verbose = null; // verbose output when signing/verifying
     boolean showcerts = false; // show certs when verifying
     boolean debug = false; // debug
     boolean signManifest = true; // "sign" the whole manifest
     boolean externalSF = true; // leave the .SF out of the PKCS7 block
+    boolean strict = false;  // treat warnings as error
 
     // read zip entry raw bytes
     private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
@@ -139,14 +156,22 @@
     private String altSignerClass = null;
     private String altSignerClasspath = null;
     private ZipFile zipFile = null;
+
     private boolean hasExpiredCert = false;
     private boolean hasExpiringCert = false;
     private boolean notYetValidCert = false;
-
+    private boolean chainNotValidated = false;
+    private boolean notSignedByAlias = false;
+    private boolean aliasNotInStore = false;
+    private boolean hasUnsignedEntry = false;
     private boolean badKeyUsage = false;
     private boolean badExtendedKeyUsage = false;
     private boolean badNetscapeCertType = false;
 
+    CertificateFactory certificateFactory;
+    CertPathValidator validator;
+    PKIXParameters pkixParameters;
+
     public void run(String args[]) {
         try {
             parseArgs(args);
@@ -184,14 +209,6 @@
                 }
             }
 
-            hasExpiredCert = false;
-            hasExpiringCert = false;
-            notYetValidCert = false;
-
-            badKeyUsage = false;
-            badExtendedKeyUsage = false;
-            badNetscapeCertType = false;
-
             if (verify) {
                 try {
                     loadKeyStore(keystore, false);
@@ -238,6 +255,29 @@
                 storepass = null;
             }
         }
+
+        if (strict) {
+            int exitCode = 0;
+            if (hasExpiringCert) {
+                exitCode |= 2;
+            }
+            if (chainNotValidated) {
+                // hasExpiredCert and notYetValidCert included in this case
+                exitCode |= 4;
+            }
+            if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
+                exitCode |= 8;
+            }
+            if (hasUnsignedEntry) {
+                exitCode |= 16;
+            }
+            if (notSignedByAlias || aliasNotInStore) {
+                exitCode |= 32;
+            }
+            if (exitCode != 0) {
+                System.exit(exitCode);
+            }
+        }
     }
 
     /*
@@ -247,25 +287,26 @@
         /* parse flags */
         int n = 0;
 
-        for (n=0; (n < args.length) && args[n].startsWith("-"); n++) {
+        if (args.length == 0) fullusage();
+        for (n=0; n < args.length; n++) {
 
             String flags = args[n];
 
             if (collator.compare(flags, "-keystore") == 0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 keystore = args[n];
             } else if (collator.compare(flags, "-storepass") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 storepass = args[n].toCharArray();
             } else if (collator.compare(flags, "-storetype") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 storetype = args[n];
             } else if (collator.compare(flags, "-providerName") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 providerName = args[n];
             } else if ((collator.compare(flags, "-provider") == 0) ||
                         (collator.compare(flags, "-providerClass") == 0)) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 if (providers == null) {
                     providers = new Vector<String>(3);
                 }
@@ -274,35 +315,38 @@
                 if (args.length > (n+1)) {
                     flags = args[n+1];
                     if (collator.compare(flags, "-providerArg") == 0) {
-                        if (args.length == (n+2)) usage();
+                        if (args.length == (n+2)) usageNoArg();
                         providerArgs.put(args[n], args[n+2]);
                         n += 2;
                     }
                 }
             } else if (collator.compare(flags, "-protected") ==0) {
                 protectedPath = true;
+            } else if (collator.compare(flags, "-certchain") ==0) {
+                if (++n == args.length) usageNoArg();
+                altCertChain = args[n];
             } else if (collator.compare(flags, "-debug") ==0) {
                 debug = true;
             } else if (collator.compare(flags, "-keypass") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 keypass = args[n].toCharArray();
             } else if (collator.compare(flags, "-sigfile") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 sigfile = args[n];
             } else if (collator.compare(flags, "-signedjar") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 signedjar = args[n];
             } else if (collator.compare(flags, "-tsa") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 tsaUrl = args[n];
             } else if (collator.compare(flags, "-tsacert") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 tsaAlias = args[n];
             } else if (collator.compare(flags, "-altsigner") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 altSignerClass = args[n];
             } else if (collator.compare(flags, "-altsignerpath") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 altSignerClasspath = args[n];
             } else if (collator.compare(flags, "-sectionsonly") ==0) {
                 signManifest = false;
@@ -311,30 +355,56 @@
             } else if (collator.compare(flags, "-verify") ==0) {
                 verify = true;
             } else if (collator.compare(flags, "-verbose") ==0) {
-                verbose = true;
+                verbose = "all";
+            } else if (collator.compare(flags, "-verbose:all") ==0) {
+                verbose = "all";
+            } else if (collator.compare(flags, "-verbose:summary") ==0) {
+                verbose = "summary";
+            } else if (collator.compare(flags, "-verbose:grouped") ==0) {
+                verbose = "grouped";
             } else if (collator.compare(flags, "-sigalg") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 sigalg = args[n];
             } else if (collator.compare(flags, "-digestalg") ==0) {
-                if (++n == args.length) usage();
+                if (++n == args.length) usageNoArg();
                 digestalg = args[n];
             } else if (collator.compare(flags, "-certs") ==0) {
                 showcerts = true;
+            } else if (collator.compare(flags, "-strict") ==0) {
+                strict = true;
             } else if (collator.compare(flags, "-h") == 0 ||
                         collator.compare(flags, "-help") == 0) {
-                usage();
+                fullusage();
             } else {
-                System.err.println(rb.getString("Illegal option: ") + flags);
-                usage();
+                if (!flags.startsWith("-")) {
+                    if (jarfile == null) {
+                        jarfile = flags;
+                    } else {
+                        alias = flags;
+                        ckaliases.add(alias);
+                    }
+                } else {
+                    System.err.println(
+                            rb.getString("Illegal option: ") + flags);
+                    usage();
+                }
             }
         }
 
-        if (n == args.length) usage();
-        jarfile = args[n++];
+        // -certs must always be specified with -verbose
+        if (verbose == null) showcerts = false;
 
-        if (!verify) {
-            if (n == args.length) usage();
-            alias = args[n++];
+        if (jarfile == null) {
+            System.err.println(rb.getString("Please specify jarfile name"));
+            usage();
+        }
+        if (!verify && alias == null) {
+            System.err.println(rb.getString("Please specify alias name"));
+            usage();
+        }
+        if (!verify && ckaliases.size() > 1) {
+            System.err.println(rb.getString("Only one alias can be specified"));
+            usage();
         }
 
         if (storetype == null) {
@@ -357,7 +427,6 @@
         if (token && !nullStream) {
             System.err.println(MessageFormat.format(rb.getString
                 ("-keystore must be NONE if -storetype is {0}"), storetype));
-            System.err.println();
             usage();
         }
 
@@ -365,7 +434,6 @@
             System.err.println(MessageFormat.format(rb.getString
                 ("-keypass can not be specified " +
                 "if -storetype is {0}"), storetype));
-            System.err.println();
             usage();
         }
 
@@ -374,7 +442,6 @@
                 System.err.println(rb.getString
                         ("If -protected is specified, " +
                         "then -storepass and -keypass must not be specified"));
-                System.err.println();
                 usage();
             }
         }
@@ -383,17 +450,27 @@
                 System.err.println(rb.getString
                         ("If keystore is not password protected, " +
                         "then -storepass and -keypass must not be specified"));
-                System.err.println();
                 usage();
             }
         }
     }
 
+    void usageNoArg() {
+        System.out.println(rb.getString("Option lacks argument"));
+        usage();
+    }
+
     void usage() {
+        System.out.println();
+        System.out.println(rb.getString("Please type jarsigner -help for usage"));
+        System.exit(1);
+    }
+
+    void fullusage() {
         System.out.println(rb.getString
                 ("Usage: jarsigner [options] jar-file alias"));
         System.out.println(rb.getString
-                ("       jarsigner -verify [options] jar-file"));
+                ("       jarsigner -verify [options] jar-file [alias...]"));
         System.out.println();
         System.out.println(rb.getString
                 ("[-keystore <url>]           keystore location"));
@@ -408,6 +485,9 @@
                 ("[-keypass <password>]       password for private key (if different)"));
         System.out.println();
         System.out.println(rb.getString
+                ("[-certchain <file>]         name of alternative certchain file"));
+        System.out.println();
+        System.out.println(rb.getString
                 ("[-sigfile <file>]           name of .SF/.DSA file"));
         System.out.println();
         System.out.println(rb.getString
@@ -423,7 +503,9 @@
                 ("[-verify]                   verify a signed JAR file"));
         System.out.println();
         System.out.println(rb.getString
-                ("[-verbose]                  verbose output when signing/verifying"));
+                ("[-verbose[:suboptions]]     verbose output when signing/verifying."));
+        System.out.println(rb.getString
+                ("                            suboptions can be all, grouped or summary"));
         System.out.println();
         System.out.println(rb.getString
                 ("[-certs]                    display certificates when verbose and verifying"));
@@ -457,15 +539,17 @@
         System.out.println(rb.getString
                 ("  [-providerArg <arg>]] ... master class file and constructor argument"));
         System.out.println();
+        System.out.println(rb.getString
+                ("[-strict]                   treat warnings as errors"));
+        System.out.println();
 
-        System.exit(1);
+        System.exit(0);
     }
 
     void verifyJar(String jarName)
         throws Exception
     {
-        boolean anySigned = false;
-        boolean hasUnsignedEntry = false;
+        boolean anySigned = false;  // if there exists entry inside jar signed
         JarFile jf = null;
 
         try {
@@ -494,11 +578,18 @@
 
             Manifest man = jf.getManifest();
 
+            // The map to record display info, only used when -verbose provided
+            //      key: signer info string
+            //      value: the list of files with common key
+            Map<String,List<String>> output =
+                    new LinkedHashMap<String,List<String>>();
+
             if (man != null) {
-                if (verbose) System.out.println();
+                if (verbose != null) System.out.println();
                 Enumeration<JarEntry> e = entriesVec.elements();
 
                 long now = System.currentTimeMillis();
+                String tab = rb.getString("      ");
 
                 while (e.hasMoreElements()) {
                     JarEntry je = e.nextElement();
@@ -509,77 +600,118 @@
                     hasUnsignedEntry |= !je.isDirectory() && !isSigned
                                         && !signatureRelated(name);
 
-                    if (verbose) {
-                        int inStoreOrScope = inKeyStore(signers);
-                        boolean inStore = (inStoreOrScope & IN_KEYSTORE) != 0;
-                        boolean inScope = (inStoreOrScope & IN_SCOPE) != 0;
+                    int inStoreOrScope = inKeyStore(signers);
+
+                    boolean inStore = (inStoreOrScope & IN_KEYSTORE) != 0;
+                    boolean inScope = (inStoreOrScope & IN_SCOPE) != 0;
+
+                    notSignedByAlias |= (inStoreOrScope & NOT_ALIAS) != 0;
+                    aliasNotInStore |= isSigned && (!inStore && !inScope);
+
+                    // Only used when -verbose provided
+                    StringBuffer sb = null;
+                    if (verbose != null) {
+                        sb = new StringBuffer();
                         boolean inManifest =
                             ((man.getAttributes(name) != null) ||
                              (man.getAttributes("./"+name) != null) ||
                              (man.getAttributes("/"+name) != null));
-                        System.out.print(
+                        sb.append(
                           (isSigned ? rb.getString("s") : rb.getString(" ")) +
                           (inManifest ? rb.getString("m") : rb.getString(" ")) +
                           (inStore ? rb.getString("k") : rb.getString(" ")) +
                           (inScope ? rb.getString("i") : rb.getString(" ")) +
-                          rb.getString("  "));
-                        StringBuffer sb = new StringBuffer();
-                        String s = Long.toString(je.getSize());
-                        for (int i = 6 - s.length(); i > 0; --i) {
-                            sb.append(' ');
+                          ((inStoreOrScope & NOT_ALIAS) != 0 ?"X":" ") +
+                          rb.getString(" "));
+                        sb.append("|");
+                    }
+
+                    // When -certs provided, display info has extra empty
+                    // lines at the beginning and end.
+                    if (isSigned) {
+                        if (showcerts) sb.append('\n');
+                        for (CodeSigner signer: signers) {
+                            // signerInfo() must be called even if -verbose
+                            // not provided. The method updates various
+                            // warning flags.
+                            String si = signerInfo(signer, tab, now);
+                            if (showcerts) {
+                                sb.append(si);
+                                sb.append('\n');
+                            }
                         }
-                        sb.append(s).append(' ').
-                                    append(new Date(je.getTime()).toString());
-                        sb.append(' ').append(je.getName());
-                        System.out.println(sb.toString());
-
-                        if (signers != null && showcerts) {
-                            String tab = rb.getString("      ");
-                            for (int i = 0; i < signers.length; i++) {
-                                System.out.println();
-                                List<? extends Certificate> certs =
-                                    signers[i].getSignerCertPath()
-                                        .getCertificates();
-                                // display the signature timestamp, if present
-                                Timestamp timestamp = signers[i].getTimestamp();
-                                if (timestamp != null) {
-                                    System.out.println(
-                                        printTimestamp(tab, timestamp));
-                                }
-                                // display the certificate(s)
-                                for (Certificate c : certs) {
-                                    System.out.println(
-                                        printCert(tab, c, true, now));
-                                }
-                            }
-                            System.out.println();
-                        }
-
-                    }
-                    if (isSigned) {
-                        for (int i = 0; i < signers.length; i++) {
-                            Certificate cert =
-                                signers[i].getSignerCertPath()
-                                    .getCertificates().get(0);
-                            if (cert instanceof X509Certificate) {
-                                checkCertUsage((X509Certificate)cert, null);
-                                if (!showcerts) {
-                                    long notAfter = ((X509Certificate)cert)
-                                        .getNotAfter().getTime();
-
-                                    if (notAfter < now) {
-                                        hasExpiredCert = true;
-                                    } else if (notAfter < now + SIX_MONTHS) {
-                                        hasExpiringCert = true;
-                                    }
-                                }
-                            }
+                    } else if (showcerts && !verbose.equals("all")) {
+                        // Print no info for unsigned entries when -verbose:all,
+                        // to be consistent with old behavior.
+                        if (signatureRelated(name)) {
+                            sb.append("\n" + tab + rb.getString(
+                                    "(Signature related entries)") + "\n\n");
+                        } else {
+                            sb.append("\n" + tab + rb.getString(
+                                    "(Unsigned entries)") + "\n\n");
                         }
                     }
 
+                    if (verbose != null) {
+                        String label = sb.toString();
+                        if (signatureRelated(name)) {
+                            // Entries inside META-INF and other unsigned
+                            // entries are grouped separately.
+                            label = "-" + label.substring(1);
+                        }
+
+                        // The label finally contains 2 parts separated by '|':
+                        // The legend displayed before the entry names, and
+                        // the cert info (if -certs specfied).
+
+                        if (!output.containsKey(label)) {
+                            output.put(label, new ArrayList<String>());
+                        }
+
+                        StringBuffer fb = new StringBuffer();
+                        String s = Long.toString(je.getSize());
+                        for (int i = 6 - s.length(); i > 0; --i) {
+                            fb.append(' ');
+                        }
+                        fb.append(s).append(' ').
+                                append(new Date(je.getTime()).toString());
+                        fb.append(' ').append(name);
+
+                        output.get(label).add(fb.toString());
+                    }
                 }
             }
-            if (verbose) {
+            if (verbose != null) {
+                for (Entry<String,List<String>> s: output.entrySet()) {
+                    List<String> files = s.getValue();
+                    String key = s.getKey();
+                    if (key.charAt(0) == '-') { // the signature-related group
+                        key = ' ' + key.substring(1);
+                    }
+                    int pipe = key.indexOf('|');
+                    if (verbose.equals("all")) {
+                        for (String f: files) {
+                            System.out.println(key.substring(0, pipe) + f);
+                            System.out.printf(key.substring(pipe+1));
+                        }
+                    } else {
+                        if (verbose.equals("grouped")) {
+                            for (String f: files) {
+                                System.out.println(key.substring(0, pipe) + f);
+                            }
+                        } else if (verbose.equals("summary")) {
+                            System.out.print(key.substring(0, pipe));
+                            if (files.size() > 1) {
+                                System.out.println(files.get(0) + " " +
+                                        String.format(rb.getString(
+                                        "(and %d more)"), files.size()-1));
+                            } else {
+                                System.out.println(files.get(0));
+                            }
+                        }
+                        System.out.printf(key.substring(pipe+1));
+                    }
+                }
                 System.out.println();
                 System.out.println(rb.getString(
                     "  s = signature was verified "));
@@ -589,9 +721,12 @@
                     "  k = at least one certificate was found in keystore"));
                 System.out.println(rb.getString(
                     "  i = at least one certificate was found in identity scope"));
+                if (ckaliases.size() > 0) {
+                    System.out.println((
+                        "  X = not signed by specified alias(es)"));
+                }
                 System.out.println();
             }
-
             if (man == null)
                 System.out.println(rb.getString("no manifest."));
 
@@ -602,7 +737,8 @@
                 System.out.println(rb.getString("jar verified."));
                 if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert ||
                     badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
-                    notYetValidCert) {
+                    notYetValidCert || chainNotValidated ||
+                    aliasNotInStore || notSignedByAlias) {
 
                     System.out.println();
                     System.out.println(rb.getString("Warning: "));
@@ -638,14 +774,27 @@
                             "This jar contains entries whose signer certificate is not yet valid. "));
                     }
 
-                    if (! (verbose && showcerts)) {
+                    if (chainNotValidated) {
+                        System.out.println(
+                                rb.getString("This jar contains entries whose certificate chain is not validated."));
+                    }
+
+                    if (notSignedByAlias) {
+                        System.out.println(
+                                rb.getString("This jar contains signed entries which is not signed by the specified alias(es)."));
+                    }
+
+                    if (aliasNotInStore) {
+                        System.out.println(rb.getString("This jar contains signed entries that's not signed by alias in this keystore."));
+                    }
+                    if (! (verbose != null && showcerts)) {
                         System.out.println();
                         System.out.println(rb.getString(
                             "Re-run with the -verbose and -certs options for more details."));
                     }
                 }
             }
-            System.exit(0);
+            return;
         } catch (Exception e) {
             System.out.println(rb.getString("jarsigner: ") + e);
             if (debug) {
@@ -660,15 +809,6 @@
         System.exit(1);
     }
 
-    /*
-     * Display some details about a certificate:
-     *
-     * <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
-     */
-    String printCert(Certificate c) {
-        return printCert("", c, false, 0);
-    }
-
     private static MessageFormat validityTimeForm = null;
     private static MessageFormat notYetTimeForm = null;
     private static MessageFormat expiredTimeForm = null;
@@ -679,6 +819,8 @@
      *
      * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
      * [<validity-period> | <expiry-warning>]
+     *
+     * Note: no newline character at the end
      */
     String printCert(String tab, Certificate c, boolean checkValidityPeriod,
         long now) {
@@ -788,54 +930,75 @@
             .append(signTimeForm.format(source)).append("]").toString();
     }
 
+    private Map<CodeSigner,Integer> cacheForInKS =
+            new IdentityHashMap<CodeSigner,Integer>();
+
+    private int inKeyStoreForOneSigner(CodeSigner signer) {
+        if (cacheForInKS.containsKey(signer)) {
+            return cacheForInKS.get(signer);
+        }
+
+        boolean found = false;
+        int result = 0;
+        List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
+        for (Certificate c : certs) {
+            String alias = storeHash.get(c);
+            if (alias != null) {
+                if (alias.startsWith("(")) {
+                    result |= IN_KEYSTORE;
+                } else if (alias.startsWith("[")) {
+                    result |= IN_SCOPE;
+                }
+                if (ckaliases.contains(alias.substring(1, alias.length() - 1))) {
+                    result |= SIGNED_BY_ALIAS;
+                }
+            } else {
+                if (store != null) {
+                    try {
+                        alias = store.getCertificateAlias(c);
+                    } catch (KeyStoreException kse) {
+                        // never happens, because keystore has been loaded
+                    }
+                    if (alias != null) {
+                        storeHash.put(c, "(" + alias + ")");
+                        found = true;
+                        result |= IN_KEYSTORE;
+                    }
+                }
+                if (!found && (scope != null)) {
+                    Identity id = scope.getIdentity(c.getPublicKey());
+                    if (id != null) {
+                        result |= IN_SCOPE;
+                        storeHash.put(c, "[" + id.getName() + "]");
+                    }
+                }
+                if (ckaliases.contains(alias)) {
+                    result |= SIGNED_BY_ALIAS;
+                }
+            }
+        }
+        cacheForInKS.put(signer, result);
+        return result;
+    }
+
     Hashtable<Certificate, String> storeHash =
                                 new Hashtable<Certificate, String>();
 
     int inKeyStore(CodeSigner[] signers) {
-        int result = 0;
 
         if (signers == null)
             return 0;
 
-        boolean found = false;
+        int output = 0;
 
-        for (int i = 0; i < signers.length; i++) {
-            found = false;
-            List<? extends Certificate> certs =
-                signers[i].getSignerCertPath().getCertificates();
-
-            for (Certificate c : certs) {
-                String alias = storeHash.get(c);
-
-                if (alias != null) {
-                    if (alias.startsWith("("))
-                            result |= IN_KEYSTORE;
-                    else if (alias.startsWith("["))
-                            result |= IN_SCOPE;
-                } else {
-                    if (store != null) {
-                        try {
-                            alias = store.getCertificateAlias(c);
-                        } catch (KeyStoreException kse) {
-                            // never happens, because keystore has been loaded
-                        }
-                        if (alias != null) {
-                            storeHash.put(c, "("+alias+")");
-                            found = true;
-                            result |= IN_KEYSTORE;
-                        }
-                    }
-                    if (!found && (scope != null)) {
-                        Identity id = scope.getIdentity(c.getPublicKey());
-                        if (id != null) {
-                            result |= IN_SCOPE;
-                            storeHash.put(c, "["+id.getName()+"]");
-                        }
-                    }
-                }
-            }
+        for (CodeSigner signer: signers) {
+            int result = inKeyStoreForOneSigner(signer);
+            output |= result;
         }
-        return result;
+        if (ckaliases.size() > 0 && (output & SIGNED_BY_ALIAS) == 0) {
+            output |= NOT_ALIAS;
+        }
+        return output;
     }
 
     void signJar(String jarName, String alias, String[] args)
@@ -1025,7 +1188,7 @@
                 // manifest file has new length
                 mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
             }
-            if (verbose) {
+            if (verbose != null) {
                 if (mfCreated) {
                     System.out.println(rb.getString("   adding: ") +
                                         mfFile.getName());
@@ -1076,7 +1239,7 @@
             // signature file
             zos.putNextEntry(sfFile);
             sf.write(zos);
-            if (verbose) {
+            if (verbose != null) {
                 if (zipFile.getEntry(sfFilename) != null) {
                     System.out.println(rb.getString(" updating: ") +
                                 sfFilename);
@@ -1086,7 +1249,7 @@
                 }
             }
 
-            if (verbose) {
+            if (verbose != null) {
                 if (tsaUrl != null || tsaCert != null) {
                     System.out.println(
                         rb.getString("requesting a signature timestamp"));
@@ -1101,8 +1264,8 @@
                         System.out.println(rb.getString("TSA location: ") +
                             certUrl);
                     }
-                    System.out.println(
-                        rb.getString("TSA certificate: ") + printCert(tsaCert));
+                    System.out.println(rb.getString("TSA certificate: ") +
+                        printCert("", tsaCert, false, 0));
                 }
                 if (signingMechanism != null) {
                     System.out.println(
@@ -1113,7 +1276,7 @@
             // signature block file
             zos.putNextEntry(bkFile);
             block.write(zos);
-            if (verbose) {
+            if (verbose != null) {
                 if (zipFile.getEntry(bkFilename) != null) {
                     System.out.println(rb.getString(" updating: ") +
                         bkFilename);
@@ -1140,7 +1303,7 @@
                 ZipEntry ze = enum_.nextElement();
 
                 if (!ze.getName().startsWith(META_INF)) {
-                    if (verbose) {
+                    if (verbose != null) {
                         if (manifest.getAttributes(ze.getName()) != null)
                           System.out.println(rb.getString("  signing: ") +
                                 ze.getName());
@@ -1194,7 +1357,8 @@
             }
 
             if (hasExpiredCert || hasExpiringCert || notYetValidCert
-                    || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
+                    || badKeyUsage || badExtendedKeyUsage
+                    || badNetscapeCertType || chainNotValidated) {
                 System.out.println();
 
                 System.out.println(rb.getString("Warning: "));
@@ -1223,6 +1387,11 @@
                     System.out.println(
                         rb.getString("The signer certificate is not yet valid."));
                 }
+
+                if (chainNotValidated) {
+                    System.out.println(
+                            rb.getString("The signer's certificate chain is not validated."));
+                }
             }
 
         // no IOException thrown in the above try clause, so disable
@@ -1274,6 +1443,40 @@
         return false;
     }
 
+    Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<CodeSigner,String>();
+
+    /**
+     * Returns a string of singer info, with a newline at the end
+     */
+    private String signerInfo(CodeSigner signer, String tab, long now) {
+        if (cacheForSignerInfo.containsKey(signer)) {
+            return cacheForSignerInfo.get(signer);
+        }
+        StringBuffer s = new StringBuffer();
+        List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
+        // display the signature timestamp, if present
+        Timestamp timestamp = signer.getTimestamp();
+        if (timestamp != null) {
+            s.append(printTimestamp(tab, timestamp));
+        }
+        // display the certificate(s)
+        for (Certificate c : certs) {
+            s.append(printCert(tab, c, true, now));
+            s.append('\n');
+        }
+        try {
+            CertPath cp = certificateFactory.generateCertPath(certs);
+            validator.validate(cp, pkixParameters);
+        } catch (Exception e) {
+            chainNotValidated = true;
+            s.append(tab + rb.getString("[CertPath not validated: ") +
+                    e.getLocalizedMessage() + "]\n");   // TODO
+        }
+        String result = s.toString();
+        cacheForSignerInfo.put(signer, result);
+        return result;
+    }
+
     private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze)
     throws IOException
     {
@@ -1360,6 +1563,48 @@
                     }
                 }
             }
+            Set<TrustAnchor> tas = new HashSet<TrustAnchor>();
+            try {
+                KeyStore caks = KeyTool.getCacertsKeyStore();
+                if (caks != null) {
+                    Enumeration<String> aliases = caks.aliases();
+                    while (aliases.hasMoreElements()) {
+                        String a = aliases.nextElement();
+                        try {
+                            tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
+                        } catch (Exception e2) {
+                            // ignore, when a SecretkeyEntry does not include a cert
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                // Ignore, if cacerts cannot be loaded
+            }
+            if (store != null) {
+                Enumeration<String> aliases = store.aliases();
+                while (aliases.hasMoreElements()) {
+                    String a = aliases.nextElement();
+                    try {
+                        X509Certificate c = (X509Certificate)store.getCertificate(a);
+                        // Only add TrustedCertificateEntry and self-signed
+                        // PrivateKeyEntry
+                        if (store.isCertificateEntry(a) ||
+                                c.getSubjectDN().equals(c.getIssuerDN())) {
+                            tas.add(new TrustAnchor(c, null));
+                        }
+                    } catch (Exception e2) {
+                        // ignore, when a SecretkeyEntry does not include a cert
+                    }
+                }
+            }
+            certificateFactory = CertificateFactory.getInstance("X.509");
+            validator = CertPathValidator.getInstance("PKIX");
+            try {
+                pkixParameters = new PKIXParameters(tas);
+                pkixParameters.setRevocationEnabled(false);
+            } catch (InvalidAlgorithmParameterException ex) {
+                // Only if tas is empty
+            }
         } catch (IOException ioe) {
             throw new RuntimeException(rb.getString("keystore load: ") +
                                         ioe.getMessage());
@@ -1408,7 +1653,8 @@
     void checkCertUsage(X509Certificate userCert, boolean[] bad) {
 
         // Can act as a signer?
-        // 1. if KeyUsage, then [0] should be true
+        // 1. if KeyUsage, then [0:digitalSignature] or
+        //    [1:nonRepudiation] should be true
         // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING
         // 3. if NetscapeCertType, then should contains OBJECT_SIGNING
         // 1,2,3 must be true
@@ -1419,10 +1665,10 @@
 
         boolean[] keyUsage = userCert.getKeyUsage();
         if (keyUsage != null) {
-            if (keyUsage.length < 1 || !keyUsage[0]) {
+            keyUsage = Arrays.copyOf(keyUsage, 9);
+            if (!keyUsage[0] && !keyUsage[1]) {
                 if (bad != null) {
                     bad[0] = true;
-                } else {
                     badKeyUsage = true;
                 }
             }
@@ -1435,7 +1681,6 @@
                         && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) {  // codeSigning
                     if (bad != null) {
                         bad[1] = true;
-                    } else {
                         badExtendedKeyUsage = true;
                     }
                 }
@@ -1462,7 +1707,6 @@
                 if (!val) {
                     if (bad != null) {
                         bad[2] = true;
-                    } else {
                         badNetscapeCertType = true;
                     }
                 }
@@ -1477,19 +1721,36 @@
         Key key = null;
 
         try {
-
             java.security.cert.Certificate[] cs = null;
-
-            try {
-                cs = store.getCertificateChain(alias);
-            } catch (KeyStoreException kse) {
-                // this never happens, because keystore has been loaded
+            if (altCertChain != null) {
+                try {
+                    cs = CertificateFactory.getInstance("X.509").
+                            generateCertificates(new FileInputStream(altCertChain)).
+                            toArray(new Certificate[0]);
+                } catch (CertificateException ex) {
+                    error(rb.getString("Cannot restore certchain from file specified"));
+                } catch (FileNotFoundException ex) {
+                    error(rb.getString("File specified by -certchain does not exist"));
+                }
+            } else {
+                try {
+                    cs = store.getCertificateChain(alias);
+                } catch (KeyStoreException kse) {
+                    // this never happens, because keystore has been loaded
+                }
             }
-            if (cs == null) {
-                MessageFormat form = new MessageFormat(rb.getString
-                    ("Certificate chain not found for: alias.  alias must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."));
-                Object[] source = {alias, alias};
-                error(form.format(source));
+            if (cs == null || cs.length == 0) {
+                if (altCertChain != null) {
+                    error(rb.getString
+                            ("Certificate chain not found in the file specified."));
+                } else {
+                    MessageFormat form = new MessageFormat(rb.getString
+                        ("Certificate chain not found for: alias.  alias must" +
+                        " reference a valid KeyStore key entry containing a" +
+                        " private key and corresponding public key certificate chain."));
+                    Object[] source = {alias, alias};
+                    error(form.format(source));
+                }
             }
 
             certChain = new X509Certificate[cs.length];
@@ -1501,56 +1762,15 @@
                 certChain[i] = (X509Certificate)cs[i];
             }
 
-            // order the cert chain if necessary (put user cert first,
-            // root-cert last in the chain)
-            X509Certificate userCert
-                = (X509Certificate)store.getCertificate(alias);
+            // We don't meant to print anything, the next call
+            // checks validity and keyUsage etc
+            printCert("", certChain[0], true, 0);
 
-            // check validity of signer certificate
             try {
-                userCert.checkValidity();
-
-                if (userCert.getNotAfter().getTime() <
-                    System.currentTimeMillis() + SIX_MONTHS) {
-
-                    hasExpiringCert = true;
-                }
-            } catch (CertificateExpiredException cee) {
-                hasExpiredCert = true;
-
-            } catch (CertificateNotYetValidException cnyve) {
-                notYetValidCert = true;
-            }
-
-            checkCertUsage(userCert, null);
-
-            if (!userCert.equals(certChain[0])) {
-                // need to order ...
-                X509Certificate[] certChainTmp
-                    = new X509Certificate[certChain.length];
-                certChainTmp[0] = userCert;
-                Principal issuer = userCert.getIssuerDN();
-                for (int i=1; i<certChain.length; i++) {
-                    int j;
-                    // look for the cert whose subject corresponds to the
-                    // given issuer
-                    for (j=0; j<certChainTmp.length; j++) {
-                        if (certChainTmp[j] == null)
-                            continue;
-                        Principal subject = certChainTmp[j].getSubjectDN();
-                        if (issuer.equals(subject)) {
-                            certChain[i] = certChainTmp[j];
-                            issuer = certChainTmp[j].getIssuerDN();
-                            certChainTmp[j] = null;
-                            break;
-                        }
-                    }
-                    if (j == certChainTmp.length) {
-                        error(rb.getString("incomplete certificate chain"));
-                    }
-
-                }
-                certChain = certChainTmp; // ordered
+                CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain));
+                validator.validate(cp, pkixParameters);
+            } catch (Exception e) {
+                chainNotValidated = true;
             }
 
             try {
--- a/src/share/classes/sun/security/tools/JarSignerResources.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/security/tools/JarSignerResources.java	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,8 +54,8 @@
                  "If keystore is not password protected, then -storepass and -keypass must not be specified"},
         {"Usage: jarsigner [options] jar-file alias",
                 "Usage: jarsigner [options] jar-file alias"},
-        {"       jarsigner -verify [options] jar-file",
-                "       jarsigner -verify [options] jar-file"},
+        {"       jarsigner -verify [options] jar-file [alias...]",
+                "       jarsigner -verify [options] jar-file [alias...]"},
         {"[-keystore <url>]           keystore location",
                 "[-keystore <url>]           keystore location"},
         {"[-storepass <password>]     password for keystore integrity",
@@ -64,6 +64,8 @@
                 "[-storetype <type>]         keystore type"},
         {"[-keypass <password>]       password for private key (if different)",
                 "[-keypass <password>]       password for private key (if different)"},
+        {"[-certchain <file>]         name of alternative certchain file",
+                "[-certchain <file>]         name of alternative certchain file"},
         {"[-sigfile <file>]           name of .SF/.DSA file",
                 "[-sigfile <file>]           name of .SF/.DSA file"},
         {"[-signedjar <file>]         name of signed JAR file",
@@ -74,8 +76,10 @@
                 "[-sigalg <algorithm>]       name of signature algorithm"},
         {"[-verify]                   verify a signed JAR file",
                 "[-verify]                   verify a signed JAR file"},
-        {"[-verbose]                  verbose output when signing/verifying",
-                "[-verbose]                  verbose output when signing/verifying"},
+        {"[-verbose[:suboptions]]     verbose output when signing/verifying.",
+                "[-verbose[:suboptions]]     verbose output when signing/verifying."},
+        {"                            suboptions can be all, grouped or summary",
+                "                            suboptions can be all, grouped or summary"},
         {"[-certs]                    display certificates when verbose and verifying",
                 "[-certs]                    display certificates when verbose and verifying"},
         {"[-tsa <url>]                location of the Timestamping Authority",
@@ -98,10 +102,22 @@
                 "[-providerClass <class>     name of cryptographic service provider's"},
         {"  [-providerArg <arg>]] ... master class file and constructor argument",
                 "  [-providerArg <arg>]] ... master class file and constructor argument"},
+        {"[-strict]                   treat warnings as errors",
+                "[-strict]                   treat warnings as errors"},
+        {"Option lacks argument", "Option lacks argument"},
+        {"Please type jarsigner -help for usage", "Please type jarsigner -help for usage"},
+        {"Please specify jarfile name", "Please specify jarfile name"},
+        {"Please specify alias name", "Please specify alias name"},
+        {"Only one alias can be specified", "Only one alias can be specified"},
+        {"This jar contains signed entries which is not signed by the specified alias(es).",
+                 "This jar contains signed entries which is not signed by the specified alias(es)."},
+        {"This jar contains signed entries that's not signed by alias in this keystore.",
+                  "This jar contains signed entries that's not signed by alias in this keystore."},
         {"s", "s"},
         {"m", "m"},
         {"k", "k"},
         {"i", "i"},
+        {"(and %d more)", "(and %d more)"},
         {"  s = signature was verified ",
                 "  s = signature was verified "},
         {"  m = entry is listed in manifest",
@@ -110,7 +126,11 @@
                 "  k = at least one certificate was found in keystore"},
         {"  i = at least one certificate was found in identity scope",
                 "  i = at least one certificate was found in identity scope"},
+        {"  X = not signed by specified alias(es)",
+                "  X = not signed by specified alias(es)"},
         {"no manifest.", "no manifest."},
+        {"(Signature related entries)","(Signature related entries)"},
+        {"(Unsigned entries)", "(Unsigned entries)"},
         {"jar is unsigned. (signatures missing or not parsable)",
                 "jar is unsigned. (signatures missing or not parsable)"},
         {"jar verified.", "jar verified."},
@@ -134,6 +154,12 @@
                 "unable to instantiate keystore class: "},
         {"Certificate chain not found for: alias.  alias must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.",
                 "Certificate chain not found for: {0}.  {1} must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."},
+        {"File specified by -certchain does not exist",
+                "File specified by -certchain does not exist"},
+        {"Cannot restore certchain from file specified",
+                "Cannot restore certchain from file specified"},
+        {"Certificate chain not found in the file specified.",
+                "Certificate chain not found in the file specified."},
         {"found non-X.509 certificate in signer's chain",
                 "found non-X.509 certificate in signer's chain"},
         {"incomplete certificate chain", "incomplete certificate chain"},
@@ -149,6 +175,7 @@
         {"certificate is not valid until",
                 "certificate is not valid until {0}"},
         {"certificate will expire on", "certificate will expire on {0}"},
+        {"[CertPath not validated: ", "[CertPath not validated: "},
         {"requesting a signature timestamp",
                 "requesting a signature timestamp"},
         {"TSA location: ", "TSA location: "},
@@ -189,14 +216,18 @@
                  "The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
         {"The signer certificate's NetscapeCertType extension doesn't allow code signing.",
                  "The signer certificate's NetscapeCertType extension doesn't allow code signing."},
-         {"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing.",
-                  "This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
-         {"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing.",
-                  "This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
-         {"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing.",
-                  "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
+        {"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing.",
+                 "This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
+        {"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing.",
+                 "This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
+        {"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing.",
+                 "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
         {"[{0} extension does not support code signing]",
                  "[{0} extension does not support code signing]"},
+        {"The signer's certificate chain is not validated.",
+                "The signer's certificate chain is not validated."},
+        {"This jar contains entries whose certificate chain is not validated.",
+                 "This jar contains entries whose certificate chain is not validated."},
     };
 
     /**
--- a/src/share/classes/sun/security/tools/KeyTool.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/security/tools/KeyTool.java	Tue Apr 14 16:51:38 2009 +0100
@@ -2545,7 +2545,19 @@
      * Returns true if the certificate is self-signed, false otherwise.
      */
     private boolean isSelfSigned(X509Certificate cert) {
-        return cert.getSubjectDN().equals(cert.getIssuerDN());
+        return signedBy(cert, cert);
+    }
+
+    private boolean signedBy(X509Certificate end, X509Certificate ca) {
+        if (!ca.getSubjectDN().equals(end.getIssuerDN())) {
+            return false;
+        }
+        try {
+            end.verify(ca.getPublicKey());
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     /**
@@ -2869,20 +2881,18 @@
         Certificate tmpCert = replyCerts[0];
         replyCerts[0] = replyCerts[i];
         replyCerts[i] = tmpCert;
-        Principal issuer = ((X509Certificate)replyCerts[0]).getIssuerDN();
+
+        X509Certificate thisCert = (X509Certificate)replyCerts[0];
 
         for (i=1; i < replyCerts.length-1; i++) {
-            // find a cert in the reply whose "subject" is the same as the
-            // given "issuer"
+            // find a cert in the reply who signs thisCert
             int j;
             for (j=i; j<replyCerts.length; j++) {
-                Principal subject;
-                subject = ((X509Certificate)replyCerts[j]).getSubjectDN();
-                if (subject.equals(issuer)) {
+                if (signedBy(thisCert, (X509Certificate)replyCerts[j])) {
                     tmpCert = replyCerts[i];
                     replyCerts[i] = replyCerts[j];
                     replyCerts[j] = tmpCert;
-                    issuer = ((X509Certificate)replyCerts[i]).getIssuerDN();
+                    thisCert = (X509Certificate)replyCerts[i];
                     break;
                 }
             }
@@ -2892,18 +2902,6 @@
             }
         }
 
-        // now verify each cert in the ordered chain
-        for (i=0; i<replyCerts.length-1; i++) {
-            PublicKey pubKey = replyCerts[i+1].getPublicKey();
-            try {
-                replyCerts[i].verify(pubKey);
-            } catch (Exception e) {
-                throw new Exception(rb.getString
-                        ("Certificate chain in reply does not verify: ") +
-                        e.getMessage());
-            }
-        }
-
         if (noprompt) {
             return replyCerts;
         }
@@ -3035,9 +3033,8 @@
     private boolean buildChain(X509Certificate certToVerify,
                         Vector<Certificate> chain,
                         Hashtable<Principal, Vector<Certificate>> certs) {
-        Principal subject = certToVerify.getSubjectDN();
         Principal issuer = certToVerify.getIssuerDN();
-        if (subject.equals(issuer)) {
+        if (isSelfSigned(certToVerify)) {
             // reached self-signed root cert;
             // no verification needed because it's trusted.
             chain.addElement(certToVerify);
@@ -3108,7 +3105,7 @@
     /**
      * Returns the keystore with the configured CA certificates.
      */
-    private KeyStore getCacertsKeyStore()
+    public static KeyStore getCacertsKeyStore()
         throws Exception
     {
         String sep = File.separator;
--- a/src/share/classes/sun/security/util/ManifestEntryVerifier.java	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/classes/sun/security/util/ManifestEntryVerifier.java	Tue Apr 14 16:51:38 2009 +0100
@@ -44,8 +44,6 @@
 
     private static final Debug debug = Debug.getInstance("jar");
 
-    private static final Provider digestProvider = Providers.getSunProvider();
-
     /** the created digest objects */
     HashMap<String, MessageDigest> createdDigests;
 
@@ -127,7 +125,7 @@
                     try {
 
                         digest = MessageDigest.getInstance
-                                        (algorithm, digestProvider);
+                                        (algorithm, Providers.getSunProvider());
                         createdDigests.put(algorithm, digest);
                     } catch (NoSuchAlgorithmException nsae) {
                         // ignore
--- a/src/share/lib/management/jmxremote.access	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/lib/management/jmxremote.access	Tue Apr 14 16:51:38 2009 +0100
@@ -8,7 +8,7 @@
 # passwords.  To be functional, a role must have an entry in
 # both the password and the access files.
 #
-# Default location of this file is $JRE/lib/management/jmxremote.access
+# The default location of this file is $JRE/lib/management/jmxremote.access
 # You can specify an alternate location by specifying a property in 
 # the management config file $JRE/lib/management/management.properties
 # (See that file for details)
@@ -16,7 +16,7 @@
 # The file format for password and access files is syntactically the same
 # as the Properties file format.  The syntax is described in the Javadoc
 # for java.util.Properties.load.
-# Typical access file has multiple  lines, where each line is blank,
+# A typical access file has multiple lines, where each line is blank,
 # a comment (like this one), or an access control entry.
 #
 # An access control entry consists of a role name, and an
@@ -29,10 +29,38 @@
 #                   role can read measurements but cannot perform any action
 #                   that changes the environment of the running program.
 #       "readwrite" grants access to read and write attributes of MBeans,
-#                   to invoke operations on them, and to create or remove them.
-#		    This access should be granted to only trusted clients, 
-#                   since they can potentially interfere with the smooth
-#		    operation of a running program 
+#                   to invoke operations on them, and optionally
+#                   to create or remove them. This access should be granted
+#                   only to trusted clients, since they can potentially
+#                   interfere with the smooth operation of a running program.
+#
+# The "readwrite" access level can optionally be followed by the "create" and/or
+# "unregister" keywords.  The "unregister" keyword grants access to unregister
+# (delete) MBeans.  The "create" keyword grants access to create MBeans of a
+# particular class or of any class matching a particular pattern.  Access
+# should only be granted to create MBeans of known and trusted classes.
+#
+# For example, the following entry would grant readwrite access
+# to "controlRole", as well as access to create MBeans of the class
+# javax.management.monitor.CounterMonitor and to unregister any MBean:
+#  controlRole readwrite \
+#              create javax.management.monitor.CounterMonitorMBean \
+#              unregister
+# or equivalently:
+#  controlRole readwrite unregister create javax.management.monitor.CounterMBean
+#
+# The following entry would grant readwrite access as well as access to create
+# MBeans of any class in the packages javax.management.monitor and
+# javax.management.timer:
+#  controlRole readwrite \
+#              create javax.management.monitor.*,javax.management.timer.* \
+#              unregister
+#
+# The \ character is defined in the Properties file syntax to allow continuation
+# lines as shown here.  A * in a class pattern matches a sequence of characters
+# other than dot (.), so javax.management.monitor.* matches
+# javax.management.monitor.CounterMonitor but not
+# javax.management.monitor.foo.Bar.
 #
 # A given role should have at most one entry in this file.  If a role
 # has no entry, it has no access.
@@ -42,7 +70,10 @@
 #
 # Default access control entries:
 # o The "monitorRole" role has readonly access.  
-# o The "controlRole" role has readwrite access.
+# o The "controlRole" role has readwrite access and can create the standard
+#   Timer and Monitor MBeans defined by the JMX API.
 
 monitorRole   readonly
-controlRole   readwrite
+controlRole   readwrite \
+              create javax.management.monitor.*,javax.management.timer.* \
+              unregister
--- a/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -94,6 +94,7 @@
       assert(!valc->isMalloc);
     }
     xvs.init(u->rp, u->rplimit, valc);
+    CHECK;
     int X = xvs.getInt();
     if (valc->S() != 0) {
       assert(valc->min <= -256);
@@ -117,6 +118,7 @@
     byte XB_byte = (byte) XB;
     byte* XB_ptr = &XB_byte;
     cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
+    CHECK;
   } else {
     NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
     assert(u->meta_rp != null);
@@ -215,8 +217,19 @@
   if (length == 0)  return 0;
   if (total_memo > 0)  return total_memo-1;
   int total = getInt();
+  // overflow checks require that none of the addends are <0,
+  // and that the partial sums never overflow (wrap negative)
+  if (total < 0) {
+    abort("overflow detected");
+    return 0;
+  }
   for (int k = length-1; k > 0; k--) {
-    total += vs[0].getInt();
+    int prev_total = total;
+    total += vs[0].getInt(); 
+    if (total < prev_total) {
+      abort("overflow detected");
+      return 0;
+    }
   }
   rewind();
   total_memo = total+1;
--- a/src/share/native/com/sun/java/util/jar/pack/coding.cpp	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/com/sun/java/util/jar/pack/coding.cpp	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -814,6 +814,7 @@
     }
     band_rp = vs.rp;
   }
+  CHECK;
 
   // Get an accurate upper limit now.
   vs0.rplimit = band_rp;
--- a/src/share/native/com/sun/java/util/jar/pack/defines.h	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/com/sun/java/util/jar/pack/defines.h	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,6 +153,8 @@
 #define CHECK_NULL_(y,p)        _CHECK_DO((p)==null, return y)
 #define CHECK_NULL_0(p)         _CHECK_DO((p)==null, return 0)
 
+#define CHECK_COUNT(t)          if (t < 0){abort("bad value count");} CHECK
+
 #define STR_TRUE   "true"
 #define STR_FALSE  "false"
 
--- a/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -523,15 +523,40 @@
   enum {
     MAGIC_BYTES = 4,
     AH_LENGTH_0 = 3,  //minver, majver, options are outside of archive_size
+    AH_LENGTH_0_MAX = AH_LENGTH_0 + 1,  // options might have 2 bytes
     AH_LENGTH   = 26, //maximum archive header length (w/ all fields)
     // Length contributions from optional header fields:
     AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
+    AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
     AH_CP_NUMBER_LEN = 4,  // int/float/long/double
     AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
     AH_LENGTH_MIN = AH_LENGTH
         -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
+    ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
     FIRST_READ  = MAGIC_BYTES + AH_LENGTH_MIN
   };
+
+
+  assert(AH_LENGTH_MIN    == 15); // # of UNSIGNED5 fields required after archive_magic
+  assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
+  // An absolute minimum null archive is magic[4], {minver,majver,options}[3],
+  // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
+  // (Note that archive_size is optional; it may be 0..10 bytes in length.)
+  // The first read must capture everything up through the options field.
+  // This happens to work even if {minver,majver,options} is a pathological
+  // 15 bytes long.  Legal pack files limit those three fields to 1+1+2 bytes.
+  assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
+
+  // Up through archive_size, the largest possible archive header is
+  // magic[4], {minver,majver,options}[4], archive_size[10].
+  // (Note only the low 12 bits of options are allowed to be non-zero.)
+  // In order to parse archive_size, we need at least this many bytes
+  // in the first read.  Of course, if archive_size_hi is more than
+  // a byte, we probably will fail to allocate the buffer, since it
+  // will be many gigabytes long.  This is a practical, not an
+  // architectural limit to Pack200 archive sizes.
+  assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX);
+
   bool foreign_buf = (read_input_fn == null);
   byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200];  // 200 is for JAR I/O
   if (foreign_buf) {
@@ -547,7 +572,7 @@
     // There is no way to tell the caller that we used only part of them.
     // Therefore, the caller must use only a bare minimum of read-ahead.
     if (inbytes.len > FIRST_READ) {
-      abort("too much pushback");
+      abort("too much read-ahead");
       return;
     }
     input.set(initbuf, sizeof(initbuf));
@@ -557,7 +582,7 @@
     rplimit += inbytes.len;
     bytes_read += inbytes.len;
   }
-  // Read only 19 bytes, which is certain to contain #archive_size fields,
+  // Read only 19 bytes, which is certain to contain #archive_options fields,
   // but is certain not to overflow past the archive_header.
   input.b.len = FIRST_READ;
   if (!ensure_input(FIRST_READ))
@@ -630,8 +655,8 @@
   if ((archive_options & ~OPTION_LIMIT) != 0) {
     fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
             archive_options);
-    // Do not abort.  If the format really changes, version numbers will bump.
-    //abort("illegal archive options");
+    abort("illegal archive options");
+    return;
   }
 
   if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
@@ -663,8 +688,17 @@
       return;
     }
   } else if (archive_size > 0) {
+    if (archive_size < ARCHIVE_SIZE_MIN) {
+      abort("impossible archive size");  // bad input data
+      return;
+    }
+    if (archive_size < header_size_1) {
+      abort("too much read-ahead");  // somehow we pre-fetched too much?
+      return;
+    }   
     input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)),
               (size_t) header_size_0 + (size_t)archive_size);
+    CHECK;
     assert(input.limit()[0] == 0);
     // Move all the bytes we read initially into the real buffer.
     input.b.copyFrom(initbuf, header_size);
@@ -680,6 +714,7 @@
     rp = rplimit = input.base();
     // Set up input buffer as if we already read the header:
     input.b.copyFrom(initbuf, header_size);
+    CHECK;
     rplimit += header_size;
     while (ensure_input(input.limit() - rp)) {
       size_t dataSoFar = input_remaining();
@@ -715,8 +750,10 @@
 
   if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
     archive_next_count = hdr.getInt();
+    CHECK_COUNT(archive_next_count);
     archive_modtime = hdr.getInt();
     file_count = hdr.getInt();
+    CHECK_COUNT(file_count);
     hdrVals += 3;
   } else {
     hdrValsSkipped += 3;
@@ -724,7 +761,9 @@
 
   if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
     band_headers_size = hdr.getInt();
+    CHECK_COUNT(band_headers_size);
     attr_definition_count = hdr.getInt();
+    CHECK_COUNT(attr_definition_count);
     hdrVals += 2;
   } else {
     hdrValsSkipped += 2;
@@ -744,13 +783,16 @@
       }
     }
     cp_counts[k] = hdr.getInt();
+    CHECK_COUNT(cp_counts[k]);
     hdrVals += 1;
   }
 
   ic_count = hdr.getInt();
+  CHECK_COUNT(ic_count);
   default_class_minver = hdr.getInt();
   default_class_majver = hdr.getInt();
   class_count = hdr.getInt();
+  CHECK_COUNT(class_count);
   hdrVals += 4;
 
   // done with archive_header
@@ -807,7 +849,6 @@
   bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
 }
 
-
 void unpacker::finish() {
   if (verbose >= 1) {
     fprintf(errstrm,
@@ -2117,13 +2158,14 @@
 
   field_descr.readData(field_count);
   read_attrs(ATTR_CONTEXT_FIELD, field_count);
+  CHECK;
 
   method_descr.readData(method_count);
   read_attrs(ATTR_CONTEXT_METHOD, method_count);
-
   CHECK;
 
   read_attrs(ATTR_CONTEXT_CLASS, class_count);
+  CHECK;
 
   read_code_headers();
 
@@ -2150,10 +2192,12 @@
   assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
   if (haveLongFlags)
     xxx_flags_hi.readData(obj_count);
+  CHECK;
 
   band& xxx_flags_lo = ad.xxx_flags_lo();
   assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
   xxx_flags_lo.readData(obj_count);
+  CHECK;
 
   // pre-scan flags, counting occurrences of each index bit
   julong indexMask = ad.flagIndexMask();  // which flag bits are index bits?
@@ -2176,11 +2220,13 @@
   assert(endsWith(xxx_attr_count.name, "_attr_count"));
   // There is one count element for each 1<<16 bit set in flags:
   xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
+  CHECK;
 
   band& xxx_attr_indexes = ad.xxx_attr_indexes();
   assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
   int overflowIndexCount = xxx_attr_count.getIntTotal();
   xxx_attr_indexes.readData(overflowIndexCount);
+  CHECK;
   // pre-scan attr indexes, counting occurrences of each value
   for (i = 0; i < overflowIndexCount; i++) {
     idx = xxx_attr_indexes.getInt();
@@ -2211,6 +2257,7 @@
     }
   }
   ad.xxx_attr_calls().readData(backwardCounts);
+  CHECK;
 
   // Read built-in bands.
   // Mostly, these are hand-coded equivalents to readBandData().
@@ -2219,42 +2266,53 @@
 
     count = ad.predefCount(CLASS_ATTR_SourceFile);
     class_SourceFile_RUN.readData(count);
+    CHECK;
 
     count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
     class_EnclosingMethod_RC.readData(count);
     class_EnclosingMethod_RDN.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     class_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
 
     count = ad.predefCount(CLASS_ATTR_InnerClasses);
     class_InnerClasses_N.readData(count);
+    CHECK;
+
     count = class_InnerClasses_N.getIntTotal();
     class_InnerClasses_RC.readData(count);
     class_InnerClasses_F.readData(count);
+    CHECK;
     // Drop remaining columns wherever flags are zero:
     count -= class_InnerClasses_F.getIntCount(0);
     class_InnerClasses_outer_RCN.readData(count);
     class_InnerClasses_name_RUN.readData(count);
+    CHECK;
 
     count = ad.predefCount(CLASS_ATTR_ClassFile_version);
     class_ClassFile_version_minor_H.readData(count);
     class_ClassFile_version_major_H.readData(count);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_FIELD:
 
     count = ad.predefCount(FIELD_ATTR_ConstantValue);
     field_ConstantValue_KQ.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     field_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_METHOD:
@@ -2266,15 +2324,18 @@
     method_Exceptions_N.readData(count);
     count = method_Exceptions_N.getIntTotal();
     method_Exceptions_RC.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     method_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
     ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
     ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
     ad.readBandData(METHOD_ATTR_AnnotationDefault);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_CODE:
@@ -2286,8 +2347,10 @@
       return;
     }
     code_StackMapTable_N.readData(count);
+    CHECK;
     count = code_StackMapTable_N.getIntTotal();
     code_StackMapTable_frame_T.readData(count);
+    CHECK;
     // the rest of it depends in a complicated way on frame tags
     {
       int fat_frame_count = 0;
@@ -2321,18 +2384,23 @@
       // deal completely with fat frames:
       offset_count += fat_frame_count;
       code_StackMapTable_local_N.readData(fat_frame_count);
+      CHECK;
       type_count += code_StackMapTable_local_N.getIntTotal();
       code_StackMapTable_stack_N.readData(fat_frame_count);
       type_count += code_StackMapTable_stack_N.getIntTotal();
+      CHECK;
       // read the rest:
       code_StackMapTable_offset.readData(offset_count);
       code_StackMapTable_T.readData(type_count);
+      CHECK;
       // (7) [RCH]
       count = code_StackMapTable_T.getIntCount(7);
       code_StackMapTable_RC.readData(count);
+      CHECK;
       // (8) [PH]
       count = code_StackMapTable_T.getIntCount(8);
       code_StackMapTable_P.readData(count);
+      CHECK;
     }
 
     count = ad.predefCount(CODE_ATTR_LineNumberTable);
@@ -2654,6 +2722,8 @@
   code_max_na_locals.readData();
   code_handler_count.readData();
   totalHandlerCount += code_handler_count.getIntTotal();
+  CHECK;
+
 
   // Read handler specifications.
   // Cf. PackageReader.readCodeHandlers.
@@ -2661,8 +2731,10 @@
   code_handler_end_PO.readData(totalHandlerCount);
   code_handler_catch_PO.readData(totalHandlerCount);
   code_handler_class_RCN.readData(totalHandlerCount);
+  CHECK;
 
   read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
+  CHECK;
 }
 
 static inline bool is_in_range(uint n, uint min, uint max) {
--- a/src/share/native/java/lang/ClassLoader.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/java/lang/ClassLoader.c	Tue Apr 14 16:51:38 2009 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -437,3 +437,21 @@
     (*env)->ReleaseStringUTFChars(env, name, cname);
     return res;
 }
+
+JNIEXPORT jobject JNICALL
+Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
+{
+    jobjectArray jcallerStack;
+    int len;
+
+    jcallerStack = JVM_GetClassContext(env);
+    if ((*env)->ExceptionCheck(env)) {
+        return NULL;
+    }
+    len = (*env)->GetArrayLength(env, jcallerStack);
+    if (index < len) {
+        return (*env)->GetObjectArrayElement(env, jcallerStack, index);
+    }
+    return NULL;
+}
+
--- a/src/share/native/java/util/zip/zip_util.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/java/util/zip/zip_util.c	Tue Apr 14 16:51:38 2009 +0100
@@ -313,6 +313,38 @@
 }
 
 /*
+ * Searches for the ZIP64 end of central directory (END) header. The
+ * contents of the ZIP64 END header will be read and placed in end64buf.
+ * Returns the file position of the ZIP64 END header, otherwise returns
+ * -1 if the END header was not found or an error occurred.
+ *
+ * The ZIP format specifies the "position" of each related record as
+ *   ...
+ *   [central directory]
+ *   [zip64 end of central directory record]
+ *   [zip64 end of central directory locator]
+ *   [end of central directory record]
+ *
+ * The offset of zip64 end locator can be calculated from endpos as
+ * "endpos - ZIP64_LOCHDR".
+ * The "offset" of zip64 end record is stored in zip64 end locator.
+ */
+static jlong
+findEND64(jzfile *zip, void *end64buf, jlong endpos)
+{
+    char loc64[ZIP64_LOCHDR];
+    jlong end64pos;
+    if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
+        return -1;    // end64 locator not found
+    }
+    end64pos = ZIP64_LOCOFF(loc64);
+    if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) {
+        return -1;    // end64 record not found
+    }
+    return end64pos;
+}
+
+/*
  * Returns a hash code value for a C-style NUL-terminated string.
  */
 static unsigned int
@@ -463,7 +495,7 @@
 readCEN(jzfile *zip, jint knownTotal)
 {
     /* Following are unsigned 32-bit */
-    jlong endpos, cenpos, cenlen;
+    jlong endpos, end64pos, cenpos, cenlen, cenoff;
     /* Following are unsigned 16-bit */
     jint total, tablelen, i, j;
     unsigned char *cenbuf = NULL;
@@ -474,6 +506,7 @@
     jlong offset;
 #endif
     unsigned char endbuf[ENDHDR];
+    jint endhdrlen = ENDHDR;
     jzcell *entries;
     jint *table;
 
@@ -490,13 +523,27 @@
 
    /* Get position and length of central directory */
     cenlen = ENDSIZ(endbuf);
+    cenoff = ENDOFF(endbuf);
+    total  = ENDTOT(endbuf);
+    if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
+        total == ZIP64_MAGICCOUNT) {
+        unsigned char end64buf[ZIP64_ENDHDR];
+        if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
+            cenlen = ZIP64_ENDSIZ(end64buf);
+            cenoff = ZIP64_ENDOFF(end64buf);
+            total = (jint)ZIP64_ENDTOT(end64buf);
+            endpos = end64pos;
+            endhdrlen = ZIP64_ENDHDR;
+        }
+    }
+
     if (cenlen > endpos)
         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
     cenpos = endpos - cenlen;
 
     /* Get position of first local file (LOC) header, taking into
      * account that there may be a stub prefixed to the zip file. */
-    zip->locpos = cenpos - ENDOFF(endbuf);
+    zip->locpos = cenpos - cenoff;
     if (zip->locpos < 0)
         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
 
@@ -527,7 +574,7 @@
            out the page size in order to make offset to be multiples of
            page size.
         */
-        zip->mlen = cenpos - offset + cenlen + ENDHDR;
+        zip->mlen = cenpos - offset + cenlen + endhdrlen;
         zip->offset = offset;
         mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
         zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
@@ -551,8 +598,13 @@
      * is a 2-byte field, but we (and other zip implementations)
      * support approx. 2**31 entries, we do not trust ENDTOT, but
      * treat it only as a strong hint.  When we call ourselves
-     * recursively, knownTotal will have the "true" value. */
-    total = (knownTotal != -1) ? knownTotal : ENDTOT(endbuf);
+     * recursively, knownTotal will have the "true" value.
+     *
+     * Keep this path alive even with the Zip64 END support added, just
+     * for zip files that have more than 0xffff entries but don't have
+     * the Zip64 enabled.
+     */
+    total = (knownTotal != -1) ? knownTotal : total;
     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
@@ -854,6 +906,7 @@
 static jzentry *
 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
 {
+    jlong locoff;
     jint nlen, elen, clen;
     jzentry *ze;
     char *cen;
@@ -880,18 +933,55 @@
     ze->size  = CENLEN(cen);
     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
     ze->crc   = CENCRC(cen);
-    ze->pos   = -(zip->locpos + CENOFF(cen));
+    locoff    = CENOFF(cen);
+    ze->pos   = -(zip->locpos + locoff);
 
     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
     memcpy(ze->name, cen + CENHDR, nlen);
     ze->name[nlen] = '\0';
 
     if (elen > 0) {
+        char *extra = cen + CENHDR + nlen;
+
         /* This entry has "extra" data */
         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
         ze->extra[0] = (unsigned char) elen;
         ze->extra[1] = (unsigned char) (elen >> 8);
-        memcpy(ze->extra+2, cen + CENHDR + nlen, elen);
+        memcpy(ze->extra+2, extra, elen);
+        if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
+            locoff == ZIP64_MAGICVAL) {
+            jint off = 0;
+            while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
+                jint sz = SH(extra, off + 2);
+                if (SH(extra, off) == ZIP64_EXTID) {
+                    off += 4;
+                    if (ze->size == ZIP64_MAGICVAL) {
+                        // if invalid zip64 extra fields, just skip
+                        if (sz < 8 || (off + 8) > elen)
+                            break;
+                        ze->size = LL(extra, off);
+                        sz -= 8;
+                        off += 8;
+                    }
+                    if (ze->csize == ZIP64_MAGICVAL) {
+                        if (sz < 8 || (off + 8) > elen)
+                            break;
+                        ze->csize = LL(extra, off);
+                        sz -= 8;
+                        off += 8;
+                    }
+                    if (locoff == ZIP64_MAGICVAL) {
+                        if (sz < 8 || (off + 8) > elen)
+                            break;
+                        ze->pos = -(zip->locpos +  LL(extra, off));
+                        sz -= 8;
+                        off += 8;
+                    }
+                    break;
+                }
+                off += (sz + 4);
+            }
+        }
     }
 
     if (clen > 0) {
--- a/src/share/native/java/util/zip/zip_util.h	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/java/util/zip/zip_util.h	Tue Apr 14 16:51:38 2009 +0100
@@ -38,9 +38,13 @@
 #define CENSIG 0x02014b50L          /* "PK\001\002" */
 #define ENDSIG 0x06054b50L          /* "PK\005\006" */
 
+#define ZIP64_ENDSIG 0x06064b50L    /* "PK\006\006" */
+#define ZIP64_LOCSIG 0x07064b50L    /* "PK\006\007" */
+
 /*
  * Header sizes including signatures
  */
+
 #ifdef USE_MMAP
 #define SIGSIZ  4
 #endif
@@ -49,12 +53,22 @@
 #define CENHDR 46
 #define ENDHDR 22
 
+#define ZIP64_ENDHDR 56       // ZIP64 end header size
+#define ZIP64_LOCHDR 20       // ZIP64 end loc header size
+#define ZIP64_EXTHDR 24       // EXT header size
+#define ZIP64_EXTID   1       // Extra field Zip64 header ID
+
+#define ZIP64_MAGICVAL 0xffffffffLL
+#define ZIP64_MAGICCOUNT 0xffff
+
+
 /*
  * Header field access macros
  */
 #define CH(b, n) (((unsigned char *)(b))[n])
 #define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
-#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16))
+#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL)
+#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32))
 #define GETSIG(b) LG(b, 0)
 
 /*
@@ -106,6 +120,26 @@
 #define ENDCOM(b) SH(b, 20)         /* size of zip file comment */
 
 /*
+ * Macros for getting Zip64 end of central directory header fields
+ */
+#define ZIP64_ENDLEN(b) LL(b, 4)      /* size of zip64 end of central dir */
+#define ZIP64_ENDVEM(b) SH(b, 12)     /* version made by */
+#define ZIP64_ENDVER(b) SH(b, 14)     /* version needed to extract */
+#define ZIP64_ENDNMD(b) LG(b, 16)     /* number of this disk */
+#define ZIP64_ENDDSK(b) LG(b, 20)     /* disk number of start */
+#define ZIP64_ENDTOD(b) LL(b, 24)     /* total number of entries on this disk */
+#define ZIP64_ENDTOT(b) LL(b, 32)     /* total number of entries */
+#define ZIP64_ENDSIZ(b) LL(b, 40)     /* central directory size in bytes */
+#define ZIP64_ENDOFF(b) LL(b, 48)     /* offset of first CEN header */
+
+/*
+ * Macros for getting Zip64 end of central directory locator fields
+ */
+#define ZIP64_LOCDSK(b) LG(b, 4)      /* disk number start */
+#define ZIP64_LOCOFF(b) LL(b, 8)      /* offset of zip64 end */
+#define ZIP64_LOCTOT(b) LG(b, 16)     /* total number of disks */
+
+/*
  * Supported compression methods
  */
 #define STORED      0
@@ -145,7 +179,7 @@
  */
 typedef struct jzcell {
     unsigned int hash;    /* 32 bit hashcode on name */
-    unsigned int cenpos;  /* Offset of central directory file header */
+    jlong cenpos;         /* Offset of central directory file header */
     unsigned int next;    /* hash chain: index into jzfile->entries */
 } jzcell;
 
--- a/src/share/native/java/util/zip/zlib-1.1.3/zlib.h	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/java/util/zip/zlib-1.1.3/zlib.h	Tue Apr 14 16:51:38 2009 +0100
@@ -106,11 +106,11 @@
 typedef struct z_stream_s {
     Bytef    *next_in;  /* next input byte */
     uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
+    long long total_in;  /* total nb of input bytes read so far */
 
     Bytef    *next_out; /* next output byte should be put there */
     uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
+    long long total_out; /* total nb of bytes output so far */
 
     char     *msg;      /* last error message, NULL if no error */
     struct internal_state FAR *state; /* not visible by applications */
--- a/src/share/native/sun/awt/giflib/dgif_lib.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/sun/awt/giflib/dgif_lib.c	Tue Apr 14 16:51:38 2009 +0100
@@ -722,6 +722,10 @@
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
     READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
+    if (CodeSize >= 12) {
+        /* Invalid initial code size: report failure */
+        return GIF_ERROR;
+    }
     BitsPerPixel = CodeSize;
 
     Private->Buf[0] = 0;    /* Input Buffer empty. */
@@ -964,10 +968,13 @@
 
     /* If code cannot fit into RunningBits bits, must raise its size. Note
      * however that codes above 4095 are used for special signaling.  */
-    if (++Private->RunningCode > Private->MaxCode1 &&
-        Private->RunningBits < LZ_BITS) {
-        Private->MaxCode1 <<= 1;
-        Private->RunningBits++;
+    if (++Private->RunningCode > Private->MaxCode1) {
+        if (Private->RunningBits < LZ_BITS) {
+            Private->MaxCode1 <<= 1;
+            Private->RunningBits++;
+        } else {
+            Private->RunningCode = Private->MaxCode1;
+        }
     }
     return GIF_OK;
 }
--- a/src/share/native/sun/awt/image/dither.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/sun/awt/image/dither.c	Tue Apr 14 16:51:38 2009 +0100
@@ -169,6 +169,7 @@
     int cubesize = cube_dim * cube_dim * cube_dim;
     unsigned char *useFlags;
     unsigned char *newILut = (unsigned char*)malloc(cubesize);
+    int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);
     if (newILut) {
 
       useFlags = (unsigned char *)calloc(cubesize, 1);
@@ -188,7 +189,7 @@
         currentState.iLUT           = newILut;
 
         currentState.rgb = (unsigned short *)
-                                malloc(256 * sizeof(unsigned short));
+                                malloc(cmap_len * sizeof(unsigned short));
         if (currentState.rgb == NULL) {
             free(newILut);
             free(useFlags);
@@ -199,7 +200,7 @@
         }
 
         currentState.indices = (unsigned char *)
-                                malloc(256 * sizeof(unsigned char));
+                                malloc(cmap_len * sizeof(unsigned char));
         if (currentState.indices == NULL) {
             free(currentState.rgb);
             free(newILut);
@@ -210,18 +211,18 @@
             return NULL;
         }
 
-        for (i = 0; i < 128; i++) {
+        for (i = 0; i < cmap_mid; i++) {
             unsigned short rgb;
             int pixel = cmap[i];
             rgb = (pixel & 0x00f80000) >> 9;
             rgb |= (pixel & 0x0000f800) >> 6;
             rgb |=  (pixel & 0xf8) >> 3;
             INSERTNEW(currentState, rgb, i);
-            pixel = cmap[255-i];
+            pixel = cmap[cmap_len - i - 1];
             rgb = (pixel & 0x00f80000) >> 9;
             rgb |= (pixel & 0x0000f800) >> 6;
             rgb |=  (pixel & 0xf8) >> 3;
-            INSERTNEW(currentState, rgb, 255-i);
+            INSERTNEW(currentState, rgb, cmap_len - i - 1);
         }
 
         if (!recurseLevel(&currentState)) {
--- a/src/share/native/sun/awt/image/gif/gifdecoder.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/sun/awt/image/gif/gifdecoder.c	Tue Apr 14 16:51:38 2009 +0100
@@ -191,6 +191,11 @@
     int passht = passinc;
     int len;
 
+    /* We have verified the initial code size on the java layer.
+     * Here we just check bounds for particular indexes. */
+    if (freeCode >= 4096 || maxCode >= 4096) {
+        return 0;
+    }
     if (blockh == 0 || raslineh == 0
         || prefixh == 0 || suffixh == 0
         || outCodeh == 0)
--- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Mon Mar 30 23:19:55 2009 +0100
+++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Tue Apr 14 16:51:38 2009 +0100
@@ -396,7 +396,7 @@
     data->jpegObj = cinfo;
     cinfo->client_data = data;
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("new structures: data is %p, cinfo is %p\n", data, cinfo);
 #endif
 
@@ -673,7 +673,7 @@
     j_decompress_ptr decomp;
 
     qlen = (*env)->GetArrayLength(env, qtables);
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
 #endif
     for (i = 0; i < qlen; i++) {
@@ -876,7 +876,7 @@
         return FALSE;
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("Filling input buffer, remaining skip is %ld, ",
            sb->remaining_skip);
     printf("Buffer length is %d\n", sb->bufferLength);
@@ -906,7 +906,7 @@
             cinfo->err->error_exit((j_common_ptr) cinfo);
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("Buffer filled. ret = %d\n", ret);
 #endif
     /*
@@ -917,7 +917,7 @@
      */
     if (ret <= 0) {
         jobject reader = data->imageIOobj;
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("YO! Early EOI! ret = %d\n", ret);
 #endif
         RELEASE_ARRAYS(env, data, src->next_input_byte);
@@ -1216,21 +1216,24 @@
 {
     jpeg_saved_marker_ptr marker;
     int num_markers = 0;
+    int num_found_markers = 0;
     int seq_no;
     JOCTET *icc_data;
+    JOCTET *dst_ptr;
     unsigned int total_length;
 #define MAX_SEQ_NO  255         // sufficient since marker numbers are bytes
-    char marker_present[MAX_SEQ_NO+1];    // 1 if marker found
-    unsigned int data_length[MAX_SEQ_NO+1]; // size of profile data in marker
-    unsigned int data_offset[MAX_SEQ_NO+1]; // offset for data in marker
+    jpeg_saved_marker_ptr icc_markers[MAX_SEQ_NO + 1];
+    int first;         // index of the first marker in the icc_markers array
+    int last;          //