changeset 1526:83d1885b22d6

Merge
author asaha
date Tue, 21 Jul 2009 13:02:23 -0700
parents 599a7f770842 1203425b5742
children 14c81c80a7f3
files src/share/classes/java/awt/Window.java src/share/classes/java/beans/MetaData.java src/share/classes/sun/swing/AccessibleMethod.java
diffstat 168 files changed, 12316 insertions(+), 826 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Jul 15 10:46:42 2009 -0700
+++ b/.hgtags	Tue Jul 21 13:02:23 2009 -0700
@@ -38,3 +38,5 @@
 f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61
 12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62
 2ed6ed6b5bfc7dd724925b90dbb31223df59c25d jdk7-b63
+a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64
+382a27aa78d3236fa123c60577797a887fe93e09 jdk7-b65
--- a/make/com/sun/java/pack/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/com/sun/java/pack/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -91,10 +91,10 @@
   CXXFLAGS_COMMON += $(MS_RUNTIME_OPTION)
   LDOUTPUT = -Fe
 
-  # J2SE name required here
-  RC_FLAGS += /D "J2SE_FNAME=$(PGRM).exe" \
-	/D "J2SE_INTERNAL_NAME=$(PGRM)" \
-	/D "J2SE_FTYPE=0x1L"
+  # JDK name required here
+  RC_FLAGS += /D "JDK_FNAME=$(PGRM).exe" \
+	/D "JDK_INTERNAL_NAME=$(PGRM)" \
+	/D "JDK_FTYPE=0x1L"
 
   RES = $(OBJDIR)/$(PGRM).res
 else
@@ -133,13 +133,19 @@
 	$(MAKE) $(UNPACK_EXE) STANDALONE=true LDMAPFLAGS_OPT= LDMAPFLAGS_DBG=
 
 ifeq ($(PLATFORM), windows)
+IMVERSIONVALUE=$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VER).$(COOKED_BUILD_NUMBER)
+SED_ALL_MANIFEST=$(SED) -e 's%IMVERSION%$(IMVERSIONVALUE)%g'
+updatefiles:: 
+	$(CAT) $(TOPDIR)/src/windows/resource/unpack200_proto.exe.manifest | $(SED_ALL_MANIFEST) > $(OBJDIR)/unpack200.exe.manifest
 winres::  $(RES)
 else
+updatefiles::
+	$(ECHO) "Manifest not required for Unix"
 winres::
 	$(ECHO) "Resource files not required for Unix"
 endif
 
-$(UNPACK_EXE): $(UNPACK_EXE_FILES_o) winres 
+$(UNPACK_EXE): $(UNPACK_EXE_FILES_o) updatefiles winres
 	$(prep-target)
 	$(LINKER)  $(LDDFLAGS) $(UNPACK_EXE_FILES_o) $(RES) $(LIBCXX) $(LDOUTPUT)$(TEMPDIR)/unpack200$(EXE_SUFFIX)
 ifdef MT
--- a/make/common/Defs-windows.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/Defs-windows.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1999-2008 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
@@ -464,11 +464,48 @@
 JDK_RC_FVER = \
     $(JDK_MINOR_VERSION),$(JDK_MICRO_VERSION),$(JDK_UPDATE_VER),$(COOKED_BUILD_NUMBER)
 
-# J2SE name required here
-RC_FLAGS += -d "J2SE_BUILD_ID=$(JDK_RC_BUILD_ID)" \
-            -d "J2SE_COMPANY=$(JDK_RC_COMPANY)" \
-            -d "J2SE_COMPONENT=$(JDK_RC_COMPONENT)" \
-            -d "J2SE_VER=$(JDK_RC_VER)" \
-            -d "J2SE_COPYRIGHT=$(JDK_RC_COPYRIGHT)" \
-            -d "J2SE_NAME=$(JDK_RC_NAME)" \
-            -d "J2SE_FVER=$(JDK_RC_FVER)"
+# JDK name required here
+RC_FLAGS += -d "JDK_BUILD_ID=$(JDK_RC_BUILD_ID)" \
+            -d "JDK_COMPANY=$(JDK_RC_COMPANY)" \
+            -d "JDK_COMPONENT=$(JDK_RC_COMPONENT)" \
+            -d "JDK_VER=$(JDK_RC_VER)" \
+            -d "JDK_COPYRIGHT=$(JDK_RC_COPYRIGHT)" \
+            -d "JDK_NAME=$(JDK_RC_NAME)" \
+            -d "JDK_FVER=$(JDK_RC_FVER)"
+
+# Enable 7-Zip LZMA file (de)compression for Java Kernel if it is available
+ifeq ($(ARCH_DATA_MODEL), 32)
+  ifneq ($(KERNEL), off)
+    # This is a hack to use until  7-Zip (and UPX) bundles can be put
+    # under /java/devtools.
+    ifndef DEPLOY_TOPDIR
+      DEPLOY_TOPDIR=$(JDK_TOPDIR)/../deploy
+    endif
+    # Uncomment this block to cause build failure if above assumption false
+    #DCHK = $(shell if [ ! -d $(DEPLOY_TOPDIR) ] ; then \
+    #  $(ECHO) deploy_not_a_peer_of_j2se ; \
+    #fi )
+    #ifeq ($(DCHK), deploy_not_a_peer_of_j2se)
+    #  If a build failure points to control coming here it means
+    #  it means deploy is not in the same directory
+    #  as j2se. Java Kernel can't tolerate that for the time being.
+    #endif
+    EC_TMP = $(shell if [ -d $(DEPLOY_TOPDIR)/make/lzma ] ; then \
+      $(ECHO) true ; \
+    else \
+      $(ECHO) false ; \
+    fi )
+    ifeq ($(EC_TMP), true)
+      EXTRA_COMP_INSTALL_PATH = lib\\\\deploy\\\\lzma.dll
+      # Crazy but true: deploy/make/plugin/jinstall/Makefile.jkernel does
+      # not include deploy/make/common/Defs-windows.gmk, either directly
+      # or indirectly. But it does include this file, so redundantly declare
+      # these variables that are in deploy/make/common/Defs-windows.gmk for
+      # the sake of the Java Kernel part of the deploy build. Whew!
+      EXTRA_COMP_LIB_NAME = lzma.dll
+      EXTRA_COMP_PATH = $(OUTPUTDIR)/tmp/deploy/lzma/win32/obj
+      EXTRA_COMP_CMD_PATH = $(EXTRA_COMP_PATH)/lzma.exe
+      EXTRA_COMP_LIB_PATH = $(EXTRA_COMP_PATH)/$(EXTRA_COMP_LIB_NAME)
+    endif
+  endif
+endif
--- a/make/common/Library.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/Library.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -207,10 +207,10 @@
 endif
 	@$(ECHO) Created $@ 
 
-# J2SE name required here
-RC_FLAGS += /D "J2SE_FNAME=$(LIBRARY).dll" \
-            /D "J2SE_INTERNAL_NAME=$(LIBRARY)" \
-            /D "J2SE_FTYPE=0x2L"
+# JDK name required here
+RC_FLAGS += /D "JDK_FNAME=$(LIBRARY).dll" \
+            /D "JDK_INTERNAL_NAME=$(LIBRARY)" \
+            /D "JDK_FTYPE=0x2L"
 
 $(OBJDIR)/$(LIBRARY).res: $(VERSIONINFO_RESOURCE)
 ifndef LOCAL_RESOURCE_FILE
--- a/make/common/Program.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/Program.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -123,10 +123,10 @@
 #
 ifeq ($(PLATFORM), windows)
 
-# J2SE name required here
-RC_FLAGS += /D "J2SE_FNAME=$(PROGRAM)$(EXE_SUFFIX)" \
-	    /D "J2SE_INTERNAL_NAME=$(PROGRAM)" \
-	    /D "J2SE_FTYPE=0x1L"
+# JDK name required here
+RC_FLAGS += /D "JDK_FNAME=$(PROGRAM)$(EXE_SUFFIX)" \
+	    /D "JDK_INTERNAL_NAME=$(PROGRAM)" \
+	    /D "JDK_FTYPE=0x1L"
 
 $(OBJDIR)/$(PROGRAM).res: $(VERSIONINFO_RESOURCE)
 	@$(prep-target)
--- a/make/common/Release.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/Release.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -789,6 +789,11 @@
 	$(CD) $(JRE_IMAGE_DIR)/lib && \
             $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \
                   hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	@# The Java Kernel JRE image ships with a special VM.  It is not included
+	@# in the full JRE image, so remove it.  Also, is it only for 32-bit windows.
+	$(CD) $(JRE_IMAGE_DIR)/bin && $(RM) -r kernel
+  endif
 endif # Windows
 ifneq ($(PLATFORM), windows)
 	$(call copy-man-pages,$(JRE_IMAGE_DIR),$(JRE_MAN_PAGES))
--- a/make/common/shared/Compiler-msvc.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/shared/Compiler-msvc.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -35,8 +35,8 @@
   LIBEXE       = $(COMPILER_PATH)lib
   LINK         = $(COMPILER_PATH)link
   RC           = $(MSDEVTOOLS_PATH)rc
+  RSC          = $(MSDEVTOOLS_PATH)rc
   LINK32       = $(LINK)
-  RSC          = $(RC)
  
   # Fill in unknown values
   COMPILER_NAME=Unknown MSVC Compiler
@@ -98,6 +98,9 @@
     endif
     ifeq ($(CC_MAJORVER), 14)
       ifeq ($(ARCH), amd64)
+        #rebase and midl moved out of Visual Studio into the SDK:
+        REBASE     = $(MSDEVTOOLS_PATH)/rebase
+        MTL        = $(MSDEVTOOLS_PATH)/midl.exe
         ifeq ($(CC_MICROVER), 30701)
           # This should be: CC_VER=14.00.30701 LINK_VER=8.00.30701
 	  # WARNING: it says 14, but it is such an early build it doesn't
@@ -110,6 +113,8 @@
 	  COMPILER_NAME=Microsoft Platform SDK - April 2005 Edition (3790.1830)
           COMPILER_VERSION=VS2005
         endif
+      else
+        REBASE         = $(COMPILER_PATH)../rebase
       endif
     endif
     ifeq ($(CC_MAJORVER), 15)
@@ -120,7 +125,6 @@
     endif
     # This will cause problems if ALT_COMPILER_PATH is defined to ""
     # which is a directive to use the PATH.
-    REBASE         = $(COMPILER_PATH)../REBASE
     ifndef COMPILER_PATH
       COMPILER_PATH := $(error COMPILER_PATH cannot be empty here)
     endif
--- a/make/common/shared/Defs-utils.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/shared/Defs-utils.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -72,6 +72,7 @@
 AR             = $(UTILS_CCS_BIN_PATH)ar
 AS             = $(UTILS_CCS_BIN_PATH)as
 BASENAME       = $(UTILS_COMMAND_PATH)basename
+BZIP2          = $(UTILS_COMMAND_PATH)bzip2
 CAT            = $(UTILS_COMMAND_PATH)cat
 CHMOD          = $(UTILS_COMMAND_PATH)chmod
 CMP            = $(UTILS_USR_BIN_PATH)cmp
@@ -157,6 +158,7 @@
   endif
   # Re-define some utilities
   LEX            =# override GNU Make intrinsic: no lex on windows
+  SHA1SUM        = $(UNIXCOMMAND_PATH)openssl sha1
 endif
 
 # Linux specific
--- a/make/common/shared/Defs-windows.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/shared/Defs-windows.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -520,7 +520,7 @@
   xALT_INSTALL_MSSDK :="$(subst \,/,$(ALT_INSTALL_MSSDK))"
   INSTALL_MSSDK      :=$(call FullPath,$(xALT_INSTALL_MSSDK))
 else
-  INSTALL_MSSDK      :=$(_psdk)
+  INSTALL_MSSDK      :=$(_ms_sdk)
 endif
 INSTALL_MSSDK:=$(call AltCheckSpaces,INSTALL_MSSDK)
 
@@ -631,7 +631,12 @@
 ifdef ALT_HOTSPOT_IMPORT_PATH
   HOTSPOT_IMPORT_PATH :=$(call FullPath,$(ALT_HOTSPOT_IMPORT_PATH))
 else
-  HOTSPOT_IMPORT_PATH =$(JDK_IMPORT_PATH)
+  # Default locations include the current $OUTPUTDIR, RE Promotions,
+  # and a JDK.  Please be aware the JDK does not include a Kernel VM.
+  _HOTSPOT_IMPORT_PATH1 = $(OUTPUTDIR)/hotspot/import
+  _HOTSPOT_IMPORT_PATH2 = $(PROMOTED_BUILD_DISTDIR)/hotspot/import
+  _HOTSPOT_IMPORT_PATH3 = $(JDK_IMPORT_PATH)
+   HOTSPOT_IMPORT_PATH := $(call DirExists,$(_HOTSPOT_IMPORT_PATH1),$(_HOTSPOT_IMPORT_PATH2),$(_HOTSPOT_IMPORT_PATH3))
 endif
 HOTSPOT_IMPORT_PATH:=$(call AltCheckSpaces,HOTSPOT_IMPORT_PATH)
 HOTSPOT_IMPORT_PATH:=$(call AltCheckValue,HOTSPOT_IMPORT_PATH)
@@ -665,4 +670,3 @@
 endif
 HOTSPOT_LIB_PATH:=$(call AltCheckSpaces,HOTSPOT_LIB_PATH)
 HOTSPOT_LIB_PATH:=$(call AltCheckValue,HOTSPOT_LIB_PATH)
-
--- a/make/common/shared/Defs.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/shared/Defs.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -292,6 +292,7 @@
 PROMOTED_RE_AREA = $(SLASH_JAVA)/re/jdk/$(JDK_VERSION)/promoted
 PROMOTED_BUILD_LATEST = latest
 PROMOTED_BUILD_BASEDIR = $(PROMOTED_RE_AREA)/$(PROMOTED_BUILD_LATEST)
+PROMOTED_BUILD_DISTDIR = $(PROMOTED_BUILD_BASEDIR)/dist/$(PLATFORM)-$(ARCH)
 PROMOTED_BUILD_BINARIES = $(PROMOTED_BUILD_BASEDIR)/binaries
 
 # PARALLEL_COMPILE_JOBS: is the number of compiles done in parallel.
--- a/make/common/shared/Sanity.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/common/shared/Sanity.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -1568,10 +1568,50 @@
 	    "" >> $(ERROR_FILE) ; \
 	fi
   endif
+	@#
+	@# Check for presence of headers required for new Java Plug-In ("plugin2")
+	@#
+	@if [ ! -r $(subst \,/,$(MOZILLA_HEADERS_PATH))/plugin2_mozilla_headers/npapi.h ]; then \
+	  $(ECHO) "ERROR: You do not have access to valid Mozilla header files for the new Java Plug-In. \n" \
+	    "      Please check your access to \n" \
+	    "          $(subst \,/,$(MOZILLA_HEADERS_PATH))/plugin2_mozilla_headers/npapi.h \n" \
+	    "      and/or check your value of ALT_JDK_DEVTOOLS_DIR, ALT_MOZILLA_HEADERS_PATH, \n" \
+	    "" >> $(ERROR_FILE) ; \
+	fi
 endif
 
 
 ######################################################
+# Make sure Java Kernel VM is accessible
+######################################################
+sane-kernel-vm:
+ifeq ($(PLATFORM), windows)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	@if [ ! -r $(HOTSPOT_KERNEL_PATH)/jvm.dll ]; then \
+	    $(ECHO) "WARNING: Your HOTSPOT_IMPORT_PATH does not include a Kernel VM... \n" \
+		    "     The kernel installer may not be built (unless hotspot is also). \n" \
+		    "     $(HOTSPOT_KERNEL_PATH)/jvm.dll \n" \
+		    "     Please check the value of ALT_HOTSPOT_IMPORT_PATH. \n" \
+		    >> $(WARNING_FILE) ; \
+	fi
+  endif
+endif
+
+
+######################################################
+# SECURITY_BASELINE_131 test
+######################################################
+security_baseline_131:
+ifeq ($(PLATFORM), windows)
+	@if [ -z "$(SECURITY_BASELINE_131)" ]; then \
+	    $(ECHO) "WARNING: Your SECURITY_BASELINE_131 setting is empty.\n" \
+		"        Setting it to the default value of 1.3.1_20.\n" \
+		"        It is recommended to set SECURITY_BASELINE_131.\n" \
+		"" >> $(WARNING_FILE) ; \
+	fi
+endif
+
+######################################################
 # SECURITY_BASELINE_142 test
 ######################################################
 security_baseline_142:
@@ -1597,6 +1637,19 @@
 	fi
 endif
 
+######################################################
+# SECURITY_BASELINE_160 test
+######################################################
+security_baseline_160:
+ifeq ($(PLATFORM), windows)
+	@if [ -z "$(SECURITY_BASELINE_160)" ]; then \
+	    $(ECHO) "WARNING: Your SECURITY_BASELINE_160 setting is empty.\n" \
+		"        Setting it to the default value of 1.6.0_11.\n" \
+		"        It is recommended to set SECURITY_BASELINE_160.\n" \
+		"" >> $(WARNING_FILE) ; \
+	fi
+endif
+
 
 ######################################################
 # this should be the last rule in any target's sanity rule.
--- a/make/docs/CORE_PKGS.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/docs/CORE_PKGS.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -217,6 +217,7 @@
   javax.swing.plaf.basic                         \
   javax.swing.plaf.metal                         \
   javax.swing.plaf.multi                         \
+  javax.swing.plaf.nimbus                        \
   javax.swing.plaf.synth                         \
   javax.tools                                    \
   javax.transaction                              \
--- a/make/java/java/FILES_c.gmk	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/java/java/FILES_c.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -64,6 +64,7 @@
 	jio.c \
 	logging.c \
 	jni_util.c \
+	jni_util_md.c \
 	jdk_util.c \
 	jdk_util_md.c \
 	check_version.c \
--- a/make/java/redist/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/java/redist/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -119,10 +119,15 @@
 	$(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMMAP_NAME) \
 	$(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMPDB_NAME)
 
-# Hotspot client is only available on 32-bit builds
+# Add .map and .pdb files to the import path for client and kernel VMs. 
+# These are only available on 32-bit windows builds. 
 ifeq ($(ARCH_DATA_MODEL), 32)
   IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMMAP_NAME) \
                  $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMPDB_NAME)
+  ifeq ($(DO_KERNEL), true)
+    IMPORT_LIST += $(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVMMAP_NAME) \
+                   $(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVMPDB_NAME)
+  endif
 endif
 
 $(LIBDIR)/$(JVMLIB_NAME): $(HOTSPOT_LIB_PATH)/$(JVMLIB_NAME)
@@ -134,6 +139,10 @@
 	@$(prep-target)
 	-$(CP) $(HOTSPOT_CLIENT_PATH)/$(JVMMAP_NAME)  $@
 
+$(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVMMAP_NAME):
+	@$(prep-target)
+	-$(CP) $(HOTSPOT_KERNEL_PATH)/$(JVMMAP_NAME)  $@
+
 $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMMAP_NAME):
 	@$(prep-target)
 	-$(CP) $(HOTSPOT_SERVER_PATH)/$(JVMMAP_NAME) $@
@@ -142,6 +151,10 @@
 	@$(prep-target)
 	-$(CP) $(HOTSPOT_CLIENT_PATH)/$(JVMPDB_NAME)  $@
 
+$(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVMPDB_NAME):
+	@$(prep-target)
+	-$(CP) $(HOTSPOT_KERNEL_PATH)/$(JVMPDB_NAME)  $@
+
 $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMPDB_NAME): 
 	@$(prep-target)
 	-$(CP) $(HOTSPOT_SERVER_PATH)/$(JVMPDB_NAME) $@
@@ -195,6 +208,9 @@
 $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVM_NAME)
 	$(install-import-file)
 
+$(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVM_NAME): $(HOTSPOT_KERNEL_PATH)/$(JVM_NAME)
+	$(install-file)
+
 $(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_SERVER_PATH)/$(LIBJSIG_NAME)
 	$(install-import-file)
 
@@ -224,6 +240,9 @@
 $(LIB_LOCATION)/$(CLIENT_LOCATION)/Xusage.txt : $(HOTSPOT_CLIENT_PATH)/Xusage.txt
 	$(install-import-file)
 
+$(LIB_LOCATION)/$(KERNEL_LOCATION)/Xusage.txt : $(HOTSPOT_KERNEL_PATH)/Xusage.txt
+	$(install-file)
+
 ifeq ($(INCLUDE_SA), true)
 # The Serviceability Agent is built in the Hotspot workspace.
 # It contains two files:
--- a/make/jpda/tty/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/jpda/tty/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -33,6 +33,12 @@
 PROGRAM = jdb
 include $(BUILDDIR)/common/Defs.gmk
 
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
 #
 # Java Files to compile are found automatically.
 #
--- a/make/sun/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -59,7 +59,7 @@
   RENDER_SUBDIR = dcpr
 endif
 # nio need to be compiled before awt to have all charsets ready
-SUBDIRS = jar security javazic misc net audio $(RENDER_SUBDIR) image \
+SUBDIRS = jar security javazic misc jkernel net audio $(RENDER_SUBDIR) image \
 	  nio awt splashscreen $(XAWT_SUBDIR) \
           $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \
 	  font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \
--- a/make/sun/applet/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/applet/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -32,6 +32,12 @@
 PRODUCT = sun
 include $(BUILDDIR)/common/Defs.gmk
 
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
 #
 # Files to compile.
 #
--- a/make/sun/jar/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/jar/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -32,6 +32,13 @@
 PRODUCT = sun
 include $(BUILDDIR)/common/Defs.gmk
 
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+
 #
 # Files
 #
--- a/make/sun/javazic/tzdata_jdk/jdk11_full_backward	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/javazic/tzdata_jdk/jdk11_full_backward	Tue Jul 21 13:02:23 2009 -0700
@@ -54,9 +54,9 @@
 Link Pacific/Guadalcanal SST
 Link Asia/Saigon VST
 
-# The follwong link is required to generate J2SE 1.2.x and 1.3.x
+# The follwong link is required to generate JDK 1.2.x and 1.3.x
 # compatible zones. In the Olson public source, MET is defined as
-# GMT+1:00 with the C-Eur rules. In J2SE, MET is defined as an alias
+# GMT+1:00 with the C-Eur rules. In JDK, MET is defined as an alias
 # of Asia/Tehran. This line must be removed if a full set of Olson
 # zones is generated. Otherwise, MET appears twice in the
 # ZoneInfoMappings.IDs table.
--- a/make/sun/jconsole/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/jconsole/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -32,6 +32,13 @@
 PRODUCT = sun
 include $(BUILDDIR)/common/Defs.gmk
 
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+
 JARFILE = $(LIBDIR)/jconsole.jar
 
 OTHER_JAVACFLAGS += -encoding iso8859-1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/jkernel/FILES_c_windows.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,42 @@
+#
+# Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+FILES_cpp = \
+	stdafx.cpp \
+	kernel.cpp \
+	DownloadDialog.cpp \
+	DownloadHelper.cpp \
+	DownloadHelper.cpp
+
+
+FILES_rc = kernel.rc
+
+# FILES_export definitions for Win32
+
+FILES_export = \
+	sun/jkernel/DownloadManager.java \
+	sun/jkernel/Mutex.java \
+	sun/jkernel/Bundle.java \
+	sun/jkernel/BackgroundDownloader.java \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/jkernel/FILES_java.gmk	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,41 @@
+#
+# Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+FILES_java = \
+	$(TARGDIR)sun/jkernel/BackgroundDownloader.java \
+	$(TARGDIR)sun/jkernel/Bundle.java \
+	$(TARGDIR)sun/jkernel/ByteArrayToFromHexDigits.java \
+	$(TARGDIR)sun/jkernel/BundleCheck.java \
+	$(TARGDIR)sun/jkernel/DownloadManager.java \
+	$(TARGDIR)sun/jkernel/Mutex.java \
+	$(TARGDIR)sun/jkernel/StandaloneByteArrayAccess.java \
+	$(TARGDIR)sun/jkernel/StandaloneMessageDigest.java \
+	$(TARGDIR)sun/jkernel/StandaloneSHA.java \
+
+FILES_export = \
+     sun/jkernel/DownloadManager.java \
+     sun/jkernel/Mutex.java \
+     sun/jkernel/Bundle.java \
+     sun/jkernel/BackgroundDownloader.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/jkernel/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,90 @@
+#
+# Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+BUILDDIR = ../..
+PACKAGE = sun.jkernel
+LIBRARY = jkernel
+PRODUCT = sun
+
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Use highest optimization level
+#
+_OPT = $(CC_HIGHEST_OPT)
+
+# This re-directs all the class files to a separate location
+CLASSDESTDIR = $(TEMPDIR)/classes
+
+
+#
+# Java source files
+#
+include FILES_java.gmk
+AUTO_FILES_JAVA_DIRS = sun/jkernel
+
+LOCALE_SUFFIXES = $(JDK_LOCALES)
+
+#
+# Native source files
+#
+
+ifeq ($(ARCH_DATA_MODEL), 32) 
+
+ifeq ($(PLATFORM), windows)
+
+include FILES_c_windows.gmk
+
+vpath %.cpp   $(PLATFORM_SRC)/native/sun/jkernel
+
+
+VERSIONINFO_RESOURCE = $(PLATFORM_SRC)/native/sun/jkernel/kernel.rc
+
+LDLIBS += urlmon.lib wininet.lib shlwapi.lib version.lib comctl32.lib gdi32.lib -def:$(PLATFORM_SRC)/native/sun/jkernel/kernel.def
+
+include $(BUILDDIR)/common/Library.gmk
+
+endif
+
+endif
+
+#
+# Resources
+#
+include $(TOPDIR)/make/common/internal/Resources.gmk
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
+
+# If extra compression is going to be available in the deploy build enable 
+# its use here by defining the JRE-relative pathname of the shared library
+
+ifeq ($(PLATFORM), windows)
+  ifdef EXTRA_COMP_INSTALL_PATH
+    CPPFLAGS += -DEXTRA_COMP_INSTALL_PATH=$(EXTRA_COMP_INSTALL_PATH)
+  endif
+endif
--- a/make/sun/native2ascii/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/native2ascii/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -33,6 +33,13 @@
 OTHER_JAVACFLAGS += -Xlint:serial -Werror
 include $(BUILDDIR)/common/Defs.gmk
 
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+
 #
 # Files
 #
--- a/make/sun/rmi/rmic/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/rmi/rmic/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -33,6 +33,13 @@
 include $(BUILDDIR)/common/Defs.gmk
 
 #
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+#
 # Files
 #
 include FILES.gmk
--- a/make/sun/serialver/Makefile	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/serialver/Makefile	Tue Jul 21 13:02:23 2009 -0700
@@ -33,6 +33,14 @@
 include $(BUILDDIR)/common/Defs.gmk
 
 #
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+
+#
 # Files
 #
 AUTO_FILES_JAVA_DIRS = sun/tools/serialver
--- a/make/sun/xawt/mapfile-vers	Wed Jul 15 10:46:42 2009 -0700
+++ b/make/sun/xawt/mapfile-vers	Tue Jul 21 13:02:23 2009 -0700
@@ -125,6 +125,7 @@
         Java_sun_awt_X11_XlibWrapper_XFree;
         Java_sun_awt_X11_XlibWrapper_ServerVendor;
         Java_sun_awt_X11_XlibWrapper_VendorRelease;
+        Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior;
         Java_sun_awt_X11_XlibWrapper_SetToolkitErrorHandler;
         Java_sun_awt_X11_XlibWrapper_XSetErrorHandler;
         Java_sun_awt_X11_XlibWrapper_CallErrorHandler;
--- a/src/share/classes/com/sun/java/swing/SwingUtilities3.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/com/sun/java/swing/SwingUtilities3.java	Tue Jul 21 13:02:23 2009 -0700
@@ -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
@@ -27,13 +27,17 @@
 
 import sun.awt.EventQueueDelegate;
 import sun.awt.AppContext;
+import java.util.Collections;
 import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.concurrent.Callable;
 import java.awt.AWTEvent;
 import java.awt.EventQueue;
 import java.awt.Component;
+import java.awt.Container;
 import javax.swing.JComponent;
 import javax.swing.RepaintManager;
+import javax.swing.SwingUtilities;
 
 /**
  * A collection of utility methods for Swing.
@@ -69,6 +73,43 @@
                                     repaintManager);
     }
 
+    private static final Map<Container, Boolean> vsyncedMap =
+        Collections.synchronizedMap(new WeakHashMap<Container, Boolean>());
+
+    /**
+     * Sets vsyncRequested state for the {@code rootContainer}.  If
+     * {@code isRequested} is {@code true} then vsynced
+     * {@code BufferStrategy} is enabled for this {@code rootContainer}.
+     *
+     * Note: requesting vsynced painting does not guarantee one. The outcome
+     * depends on current RepaintManager's RepaintManager.PaintManager
+     * and on the capabilities of the graphics hardware/software and what not.
+     *
+     * @param rootContainer topmost container. Should be either {@code Window}
+     *  or {@code Applet}
+     * @param isRequested the value to set vsyncRequested state to
+     */
+    public static void setVsyncRequested(Container rootContainer,
+                                         boolean isRequested) {
+        assert SwingUtilities.getRoot(rootContainer) == rootContainer;
+        if (isRequested) {
+            vsyncedMap.put(rootContainer, Boolean.TRUE);
+        } else {
+            vsyncedMap.remove(rootContainer);
+        }
+    }
+
+    /**
+     * Checks if vsync painting is requested for {@code rootContainer}
+     *
+     * @param rootContainer topmost container. Should be either Window or Applet
+     * @return {@code true} if vsync painting is requested for {@code rootContainer}
+     */
+    public static boolean isVsyncRequested(Container rootContainer) {
+        assert SwingUtilities.getRoot(rootContainer) == rootContainer;
+        return Boolean.TRUE == vsyncedMap.get(rootContainer);
+    }
+
     /**
      * Returns delegate {@code RepaintManager} for {@code component} hierarchy.
      */
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Tue Jul 21 13:02:23 2009 -0700
@@ -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
@@ -139,7 +139,7 @@
                                     });
                     isSunDesktop = val.booleanValue();
             }
-            if (isSunDesktop) {
+            if (isSunDesktop && !sun.java2d.SunGraphicsEnvironment.isOpenSolaris) {
                 isSunCJK = true;
             }
         }
--- a/src/share/classes/java/awt/AWTEvent.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/AWTEvent.java	Tue Jul 21 13:02:23 2009 -0700
@@ -32,6 +32,7 @@
 import java.lang.reflect.Field;
 import java.util.logging.Logger;
 import java.util.logging.Level;
+import sun.awt.AWTAccessor;
 
 /**
  * The root event class for all AWT events.
@@ -230,6 +231,12 @@
         if (!GraphicsEnvironment.isHeadless()) {
             initIDs();
         }
+        AWTAccessor.setAWTEventAccessor(
+            new AWTAccessor.AWTEventAccessor() {
+                public void setPosted(AWTEvent ev) {
+                    ev.isPosted = true;
+                }
+            });
     }
 
     private static synchronized Field get_InputEvent_CanAccessSystemClipboard() {
--- a/src/share/classes/java/awt/Component.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/Component.java	Tue Jul 21 13:02:23 2009 -0700
@@ -861,6 +861,17 @@
             public boolean isVisible_NoClientCode(Component comp) {
                 return comp.isVisible_NoClientCode();
             }
+            public void setRequestFocusController
+                (RequestFocusController requestController)
+            {
+                 Component.setRequestFocusController(requestController);
+            }
+            public AppContext getAppContext(Component comp) {
+                 return comp.appContext;
+            }
+            public void setAppContext(Component comp, AppContext appContext) {
+                 comp.appContext = appContext;
+            }
         });
     }
 
@@ -9824,31 +9835,6 @@
 
     // ****************** END OF MIXING CODE ********************************
 
-    private static boolean doesClassImplement(Class cls, String interfaceName) {
-        if (cls == null) return false;
-
-        for (Class c : cls.getInterfaces()) {
-            if (c.getName().equals(interfaceName)) {
-                return true;
-            }
-        }
-        return doesClassImplement(cls.getSuperclass(), interfaceName);
-    }
-
-    /**
-     * Checks that the given object implements the given interface.
-     * @param obj Object to be checked
-     * @param interfaceName The name of the interface. Must be fully-qualified interface name.
-     * @return true, if this object implements the given interface,
-     *         false, otherwise, or if obj or interfaceName is null
-     */
-    static boolean doesImplement(Object obj, String interfaceName) {
-        if (obj == null) return false;
-        if (interfaceName == null) return false;
-
-        return doesClassImplement(obj.getClass(), interfaceName);
-    }
-
     // Note that the method is overriden in the Window class,
     // a window doesn't need to be updated in the Z-order.
     void updateZOrder() {
--- a/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java	Tue Jul 21 13:02:23 2009 -0700
@@ -425,15 +425,13 @@
             }
             if (log.isLoggable(Level.FINE)) log.fine("### Cycle is " + cycle);
 
-            for (int i = 0; i < cycle.size(); i++) {
-                Component comp = cycle.get(i);
+            for (Component comp : cycle) {
                 if (accept(comp)) {
                     return comp;
-                } else if (comp instanceof Container && comp != aContainer) {
-                    Container cont = (Container)comp;
-                    if (cont.isFocusTraversalPolicyProvider()) {
-                        return cont.getFocusTraversalPolicy().getDefaultComponent(cont);
-                    }
+                } else if (comp != aContainer &&
+                           (comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null)
+                {
+                    return comp;
                 }
             }
         }
--- a/src/share/classes/java/awt/Dialog.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/Dialog.java	Tue Jul 21 13:02:23 2009 -0700
@@ -262,12 +262,6 @@
         TOOLKIT_EXCLUDE
     };
 
-    /**
-     * @since 1.6
-     */
-    private final static ModalExclusionType DEFAULT_MODAL_EXCLUSION_TYPE =
-        ModalExclusionType.APPLICATION_EXCLUDE;
-
     /* operations with this list should be synchronized on tree lock*/
     transient static IdentityArrayList<Dialog> modalDialogs = new IdentityArrayList<Dialog>();
 
--- a/src/share/classes/java/awt/EventQueue.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/EventQueue.java	Tue Jul 21 13:02:23 2009 -0700
@@ -43,6 +43,7 @@
 import sun.awt.PeerEvent;
 import sun.awt.SunToolkit;
 import sun.awt.EventQueueItem;
+import sun.awt.AWTAccessor;
 
 /**
  * <code>EventQueue</code> is a platform-independent class
@@ -154,6 +155,18 @@
 
     private static final Logger eventLog = Logger.getLogger("java.awt.event.EventQueue");
 
+    static {
+        AWTAccessor.setEventQueueAccessor(
+            new AWTAccessor.EventQueueAccessor() {
+                public EventQueue getNextQueue(EventQueue eventQueue) {
+                    return eventQueue.nextQueue;
+                }
+                public Thread getDispatchThread(EventQueue eventQueue) {
+                    return eventQueue.dispatchThread;
+                }
+            });
+    }
+
     public EventQueue() {
         for (int i = 0; i < NUM_PRIORITIES; i++) {
             queues[i] = new Queue();
--- a/src/share/classes/java/awt/MenuComponent.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/MenuComponent.java	Tue Jul 21 13:02:23 2009 -0700
@@ -30,6 +30,7 @@
 import java.io.ObjectInputStream;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
+import sun.awt.AWTAccessor;
 import javax.accessibility.*;
 
 /**
@@ -109,6 +110,22 @@
      */
     private static final long serialVersionUID = -4536902356223894379L;
 
+    static {
+        AWTAccessor.setMenuComponentAccessor(
+            new AWTAccessor.MenuComponentAccessor() {
+                public AppContext getAppContext(MenuComponent menuComp) {
+                    return menuComp.appContext;
+                }
+                public void setAppContext(MenuComponent menuComp,
+                                          AppContext appContext) {
+                    menuComp.appContext = appContext;
+                }
+                public MenuContainer getParent(MenuComponent menuComp) {
+                    return menuComp.parent;
+                }
+            });
+    }
+
     /**
      * Creates a <code>MenuComponent</code>.
      * @exception HeadlessException if
--- a/src/share/classes/java/awt/PopupMenu.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/PopupMenu.java	Tue Jul 21 13:02:23 2009 -0700
@@ -28,6 +28,7 @@
 import java.awt.peer.PopupMenuPeer;
 import javax.accessibility.*;
 
+import sun.awt.AWTAccessor;
 
 /**
  * A class that implements a menu which can be dynamically popped up
@@ -48,6 +49,15 @@
 
     transient boolean isTrayIconPopup = false;
 
+    static {
+        AWTAccessor.setPopupMenuAccessor(
+            new AWTAccessor.PopupMenuAccessor() {
+                public boolean isTrayIconPopup(PopupMenu popupMenu) {
+                    return popupMenu.isTrayIconPopup;
+                }
+            });
+    }
+
     /*
      * JDK 1.1 serialVersionUID
      */
--- a/src/share/classes/java/awt/Window.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/Window.java	Tue Jul 21 13:02:23 2009 -0700
@@ -3658,7 +3658,7 @@
     private static void setLayersOpaque(Component component, boolean isOpaque) {
         // Shouldn't use instanceof to avoid loading Swing classes
         //    if it's a pure AWT application.
-        if (Component.doesImplement(component, "javax.swing.RootPaneContainer")) {
+        if (SunToolkit.isInstanceOf(component, "javax.swing.RootPaneContainer")) {
             javax.swing.RootPaneContainer rpc = (javax.swing.RootPaneContainer)component;
             javax.swing.JRootPane root = rpc.getRootPane();
             javax.swing.JLayeredPane lp = root.getLayeredPane();
@@ -3839,6 +3839,10 @@
             {
                 return window.calculateSecurityWarningPosition(x, y, w, h);
             }
+
+            public void setLWRequestStatus(Window changed, boolean status) {
+                changed.syncLWRequests = status;
+            }
         }); // WindowAccessor
     } // static
 
--- a/src/share/classes/java/awt/color/ICC_Profile.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/awt/color/ICC_Profile.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1844,10 +1844,18 @@
             }
 
         if (!f.isFile()) { /* try the directory of built-in profiles */
-                dir = System.getProperty("java.home") +
-                    File.separatorChar + "lib" + File.separatorChar + "cmm";
-                fullPath = dir + File.separatorChar + fileName;
+            dir = System.getProperty("java.home") +
+                File.separatorChar + "lib" + File.separatorChar + "cmm";
+            fullPath = dir + File.separatorChar + fileName;
                 f = new File(fullPath);
+                if (!f.isFile()) {
+                    //make sure file was installed in the kernel mode
+                    try {
+                        //kernel uses platform independent paths =>
+                        //   should not use platform separator char
+                        sun.jkernel.DownloadManager.downloadFile("lib/cmm/"+fileName);
+                    } catch (IOException ioe) {}
+                }
             }
 
         if (f.isFile()) {
--- a/src/share/classes/java/beans/MetaData.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/beans/MetaData.java	Tue Jul 21 13:02:23 2009 -0700
@@ -93,7 +93,7 @@
 
     protected Expression instantiate(Object oldInstance, Encoder out) {
         Enum e = (Enum) oldInstance;
-        return new Expression(e, Enum.class, "valueOf", new Object[]{e.getClass(), e.name()});
+        return new Expression(e, Enum.class, "valueOf", new Object[]{e.getDeclaringClass(), e.name()});
     }
 }
 
--- a/src/share/classes/java/lang/ClassLoader.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/ClassLoader.java	Tue Jul 21 13:02:23 2009 -0700
@@ -58,6 +58,7 @@
 import sun.misc.VM;
 import sun.reflect.Reflection;
 import sun.security.util.SecurityConstants;
+import sun.jkernel.DownloadManager;
 
 /**
  * A class loader is an object that is responsible for loading classes. The
@@ -1280,6 +1281,21 @@
      * Find resources from the VM's built-in classloader.
      */
     private static URL getBootstrapResource(String name) {
+        try {
+            // If this is a known JRE resource, ensure that its bundle is
+            // downloaded.  If it isn't known, we just ignore the download
+            // failure and check to see if we can find the resource anyway
+            // (which is possible if the boot class path has been modified).
+            if (sun.misc.VM.isBootedKernelVM()) {
+                sun.jkernel.DownloadManager.getBootClassPathEntryForResource(
+                    name);
+            }
+        } catch (NoClassDefFoundError e) {
+            // This happens while Java itself is being compiled; DownloadManager
+            // isn't accessible when this code is first invoked.  It isn't an
+            // issue, as if we can't find DownloadManager, we can safely assume
+            // that additional code is not available for download.
+        }
         URLClassPath ucp = getBootstrapClassPath();
         Resource res = ucp.getResource(name);
         return res != null ? res.getURL() : null;
@@ -1305,13 +1321,9 @@
 
     // Returns the URLClassPath that is used for finding system resources.
     static URLClassPath getBootstrapClassPath() {
-        if (bootstrapClassPath == null) {
-            bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath();
-        }
-        return bootstrapClassPath;
+        return sun.misc.Launcher.getBootstrapClassPath();
     }
 
-    private static URLClassPath bootstrapClassPath;
 
     /**
      * Returns an input stream for reading the specified resource.
@@ -1800,6 +1812,24 @@
     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
     static void loadLibrary(Class fromClass, String name,
                             boolean isAbsolute) {
+        try {
+            if (VM.isBootedKernelVM() && !DownloadManager.isJREComplete() &&
+                    !DownloadManager.isCurrentThreadDownloading()) {
+                DownloadManager.downloadFile("bin/" +
+                    System.mapLibraryName(name));
+                // it doesn't matter if the downloadFile call returns false --
+                // it probably just means that this is a user library, as
+                // opposed to a JRE library
+            }
+        } catch (IOException e) {
+            throw new UnsatisfiedLinkError("Error downloading library " +
+                                                name + ": " + e);
+        } catch (NoClassDefFoundError e) {
+            // This happens while Java itself is being compiled; DownloadManager
+            // isn't accessible when this code is first invoked.  It isn't an
+            // issue, as if we can't find DownloadManager, we can safely assume
+            // that additional code is not available for download.
+        }
         ClassLoader loader =
             (fromClass == null) ? null : fromClass.getClassLoader();
         if (sys_paths == null) {
--- a/src/share/classes/java/lang/ClassNotFoundException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/ClassNotFoundException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -50,7 +50,7 @@
  * @see     java.lang.ClassLoader#loadClass(java.lang.String, boolean)
  * @since   JDK1.0
  */
-public class ClassNotFoundException extends Exception {
+public class ClassNotFoundException extends ReflectiveOperationException {
     /**
      * use serialVersionUID from JDK 1.1.X for interoperability
      */
--- a/src/share/classes/java/lang/Double.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/Double.java	Tue Jul 21 13:02:23 2009 -0700
@@ -529,6 +529,7 @@
      * @param  s   the string to be parsed.
      * @return the {@code double} value represented by the string
      *         argument.
+     * @throws NullPointerException  if the string is null
      * @throws NumberFormatException if the string does not contain
      *         a parsable {@code double}.
      * @see    java.lang.Double#valueOf(String)
--- a/src/share/classes/java/lang/Float.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/Float.java	Tue Jul 21 13:02:23 2009 -0700
@@ -438,12 +438,13 @@
      * represented by the specified {@code String}, as performed
      * by the {@code valueOf} method of class {@code Float}.
      *
-     * @param      s   the string to be parsed.
+     * @param  s the string to be parsed.
      * @return the {@code float} value represented by the string
      *         argument.
-     * @throws  NumberFormatException  if the string does not contain a
+     * @throws NullPointerException  if the string is null
+     * @throws NumberFormatException if the string does not contain a
      *               parsable {@code float}.
-     * @see        java.lang.Float#valueOf(String)
+     * @see    java.lang.Float#valueOf(String)
      * @since 1.2
      */
     public static float parseFloat(String s) throws NumberFormatException {
--- a/src/share/classes/java/lang/IllegalAccessException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/IllegalAccessException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -56,7 +56,7 @@
  * @see     java.lang.reflect.Constructor#newInstance(Object[])
  * @since   JDK1.0
  */
-public class IllegalAccessException extends Exception {
+public class IllegalAccessException extends ReflectiveOperationException {
     private static final long serialVersionUID = 6616958222490762034L;
 
     /**
--- a/src/share/classes/java/lang/InstantiationException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/InstantiationException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -43,7 +43,7 @@
  * @since   JDK1.0
  */
 public
-class InstantiationException extends Exception {
+class InstantiationException extends ReflectiveOperationException {
     private static final long serialVersionUID = -8441929162975509110L;
 
     /**
--- a/src/share/classes/java/lang/NoSuchFieldException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/NoSuchFieldException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -31,7 +31,7 @@
  * @author  unascribed
  * @since   JDK1.1
  */
-public class NoSuchFieldException extends Exception {
+public class NoSuchFieldException extends ReflectiveOperationException {
     private static final long serialVersionUID = -6143714805279938260L;
 
     /**
--- a/src/share/classes/java/lang/NoSuchMethodException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/NoSuchMethodException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -32,7 +32,7 @@
  * @since      JDK1.0
  */
 public
-class NoSuchMethodException extends Exception {
+class NoSuchMethodException extends ReflectiveOperationException {
     private static final long serialVersionUID = 5034388446362600923L;
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/lang/ReflectiveOperationException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.lang;
+
+/**
+ * Common superclass of exceptions thrown by reflective operations in
+ * core reflection.
+ *
+ * @see LinkageError
+ * @since 1.7
+ */
+public class ReflectiveOperationException extends Exception {
+    static final long serialVersionUID = 123456789L;
+
+    /**
+     * Constructs a new exception with {@code null} as its detail
+     * message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public ReflectiveOperationException() {
+        super();
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     *
+     * @param   message   the detail message. The detail message is saved for
+     *          later retrieval by the {@link #getMessage()} method.
+     */
+    public ReflectiveOperationException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message
+     * and cause.
+     *
+     * <p>Note that the detail message associated with
+     * {@code cause} is <em>not</em> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param  message the detail message (which is saved for later retrieval
+     *         by the {@link #getMessage()} method).
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link #getCause()} method).  (A {@code null} value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     */
+    public ReflectiveOperationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
+     *
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link #getCause()} method).  (A {@code null} value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     */
+    public ReflectiveOperationException(Throwable cause) {
+        super(cause);
+    }
+}
--- a/src/share/classes/java/lang/System.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/System.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1106,12 +1106,22 @@
         initProperties(props);
         sun.misc.Version.init();
 
+        // Workaround until DownloadManager initialization is revisited.
+        // Make JavaLangAccess available early enough for internal
+        // Shutdown hooks to be registered
+        setJavaLangAccess();
+
         // 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.
+        // vm option -XX:AutoBoxCacheMax=<size>.
         Integer.getAndRemoveCacheProperties();
 
+        // Load the zip library now in order to keep java.util.zip.ZipFile
+        // from trying to use itself to load this library later.
+        loadLibrary("zip");
+
+
         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
         FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
         FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
@@ -1119,10 +1129,6 @@
         setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
         setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
 
-        // Load the zip library now in order to keep java.util.zip.ZipFile
-        // from trying to use itself to load this library later.
-        loadLibrary("zip");
-
         // Setup Java signal handlers for HUP, TERM, and INT (where available).
         Terminator.setup();
 
@@ -1152,7 +1158,9 @@
         // way as other threads; we must do it ourselves here.
         Thread current = Thread.currentThread();
         current.getThreadGroup().add(current);
+    }
 
+    private static void setJavaLangAccess() {
         // Allow privileged classes outside of java.lang
         sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
             public sun.reflect.ConstantPool getConstantPool(Class klass) {
--- a/src/share/classes/java/lang/reflect/InvocationTargetException.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/lang/reflect/InvocationTargetException.java	Tue Jul 21 13:02:23 2009 -0700
@@ -39,7 +39,7 @@
  * @see Method
  * @see Constructor
  */
-public class InvocationTargetException extends Exception {
+public class InvocationTargetException extends ReflectiveOperationException {
     /**
      * Use serialVersionUID from JDK 1.1.X for interoperability
      */
--- a/src/share/classes/java/security/cert/CertPathHelperImpl.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/security/cert/CertPathHelperImpl.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2006 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
@@ -46,7 +46,7 @@
     /**
      * Initialize the helper framework. This method must be called from
      * the static initializer of each class that is the target of one of
-     * the methods in this class. This ensures that the helper if initialized
+     * the methods in this class. This ensures that the helper is initialized
      * prior to a tunneled call from the Sun provider.
      */
     synchronized static void initialize() {
@@ -59,4 +59,8 @@
             Set<GeneralNameInterface> names) {
         sel.setPathToNamesInternal(names);
     }
+
+    protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
+        sel.setDateAndTime(date, skew);
+    }
 }
--- a/src/share/classes/java/security/cert/X509CRLSelector.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/security/cert/X509CRLSelector.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,6 +72,10 @@
  */
 public class X509CRLSelector implements CRLSelector {
 
+    static {
+        CertPathHelperImpl.initialize();
+    }
+
     private static final Debug debug = Debug.getInstance("certpath");
     private HashSet<Object> issuerNames;
     private HashSet<X500Principal> issuerX500Principals;
@@ -79,6 +83,7 @@
     private BigInteger maxCRL;
     private Date dateAndTime;
     private X509Certificate certChecking;
+    private long skew = 0;
 
     /**
      * Creates an <code>X509CRLSelector</code>. Initially, no criteria are set
@@ -417,7 +422,18 @@
         if (dateAndTime == null)
             this.dateAndTime = null;
         else
-            this.dateAndTime = (Date) dateAndTime.clone();
+            this.dateAndTime = new Date(dateAndTime.getTime());
+        this.skew = 0;
+    }
+
+    /**
+     * Sets the dateAndTime criterion and allows for the specified clock skew
+     * (in milliseconds) when checking against the validity period of the CRL.
+     */
+    void setDateAndTime(Date dateAndTime, long skew) {
+        this.dateAndTime =
+            (dateAndTime == null ? null : new Date(dateAndTime.getTime()));
+        this.skew = skew;
     }
 
     /**
@@ -657,8 +673,14 @@
                 }
                 return false;
             }
-            if (crlThisUpdate.after(dateAndTime)
-                  || nextUpdate.before(dateAndTime)) {
+            Date nowPlusSkew = dateAndTime;
+            Date nowMinusSkew = dateAndTime;
+            if (skew > 0) {
+                nowPlusSkew = new Date(dateAndTime.getTime() + skew);
+                nowMinusSkew = new Date(dateAndTime.getTime() - skew);
+            }
+            if (nowMinusSkew.after(nextUpdate)
+                || nowPlusSkew.before(crlThisUpdate)) {
                 if (debug != null) {
                     debug.println("X509CRLSelector.match: update out of range");
                 }
--- a/src/share/classes/java/text/SimpleDateFormat.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/text/SimpleDateFormat.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1030,9 +1030,9 @@
 
         case 1: // 'y' - YEAR
             if (calendar instanceof GregorianCalendar) {
-                if (count >= 4)
+                if (count != 2)
                     zeroPaddingNumber(value, count, maxIntCount, buffer);
-                else // count < 4
+                else // count == 2
                     zeroPaddingNumber(value, 2, 2, buffer); // clip 1996 to 96
             } else {
                 if (current == null) {
--- a/src/share/classes/java/util/zip/ZipEntry.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/java/util/zip/ZipEntry.java	Tue Jul 21 13:02:23 2009 -0700
@@ -109,7 +109,15 @@
      * @see #getTime()
      */
     public void setTime(long time) {
-        this.time = javaToDosTime(time);
+        // fix for bug 6625963: we bypass time calculations while Kernel is
+        // downloading bundles, since they aren't necessary and would cause
+        // the Kernel core to depend upon the (very large) time zone data
+        if (sun.misc.VM.isBootedKernelVM() &&
+            sun.jkernel.DownloadManager.isCurrentThreadDownloading()) {
+            this.time = sun.jkernel.DownloadManager.KERNEL_STATIC_MODTIME;
+        } else {
+            this.time = javaToDosTime(time);
+        }
     }
 
     /**
@@ -245,10 +253,14 @@
      * the first 0xFFFF bytes are output to the ZIP file entry.
      *
      * @param comment the comment string
-     *
+     * @exception IllegalArgumentException if the length of the specified
+     *            comment string is greater than 0xFFFF bytes
      * @see #getComment()
      */
     public void setComment(String comment) {
+        if (comment != null && comment.length() > 0xffff) {
+            throw new IllegalArgumentException("invalid entry comment length");
+        }
         this.comment = comment;
     }
 
--- a/src/share/classes/javax/swing/BufferStrategyPaintManager.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/BufferStrategyPaintManager.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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,9 +33,14 @@
 import java.security.AccessController;
 import java.util.*;
 import java.util.logging.*;
+
+import com.sun.java.swing.SwingUtilities3;
+
 import sun.awt.SubRegionShowable;
 import sun.java2d.SunGraphics2D;
 import sun.security.action.GetPropertyAction;
+import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
+import sun.awt.SunToolkit;
 
 /**
  * A PaintManager implementation that uses a BufferStrategy for
@@ -73,12 +78,6 @@
     private static Method COMPONENT_CREATE_BUFFER_STRATEGY_METHOD;
     private static Method COMPONENT_GET_BUFFER_STRATEGY_METHOD;
 
-    /**
-     * Indicates whether or not we should try and get a flip buffer strategy
-     * first, default is false.
-     */
-    private static boolean TRY_FLIP;
-
     private static final Logger LOGGER = Logger.getLogger(
                            "javax.swing.BufferStrategyPaintManager");
 
@@ -151,12 +150,6 @@
      */
     private boolean disposeBufferOnEnd;
 
-
-    static {
-        TRY_FLIP = "true".equals(AccessController.doPrivileged(
-              new GetPropertyAction("swing.useFlipBufferStrategy", "false")));
-    }
-
     private static Method getGetBufferStrategyMethod() {
         if (COMPONENT_GET_BUFFER_STRATEGY_METHOD == null) {
             getMethods();
@@ -257,7 +250,7 @@
         try {
             BufferInfo info = getBufferInfo(c);
             BufferStrategy bufferStrategy;
-            if (info != null && !info.usingFlip && info.isInSync() &&
+            if (info != null && info.isInSync() &&
                 (bufferStrategy = info.getBufferStrategy(false)) != null) {
                 SubRegionShowable bsSubRegion =
                         (SubRegionShowable)bufferStrategy;
@@ -579,8 +572,9 @@
         rootJ = c;
         root = c;
         xOffset = yOffset = 0;
-        while (root != null && (!(root instanceof Window) &&
-                                !(root instanceof Applet))) {
+        while (root != null &&
+               (!(root instanceof Window) &&
+                !SunToolkit.isInstanceOf(root, "java.applet.Applet"))) {
             xOffset += root.getX();
             yOffset += root.getY();
             root = root.getParent();
@@ -685,8 +679,6 @@
         // same reason.
         private WeakReference<BufferStrategy> weakBS;
         private WeakReference<Container> root;
-        // Whether or not we're using flip bs or blit.
-        private boolean usingFlip;
         // Indicates whether or not the backbuffer and display are in sync.
         // This is set to true when a full repaint on the rootpane is done.
         private boolean inSync;
@@ -764,13 +756,6 @@
         }
 
         /**
-         * Returns true if using a flip buffer strategy.
-         */
-        public boolean usingFlip() {
-            return usingFlip;
-        }
-
-        /**
          * Returns true if the buffer strategy of the component differs
          * from current buffer strategy.
          */
@@ -814,23 +799,19 @@
          * blit.
          */
         private BufferStrategy createBufferStrategy() {
-            BufferCapabilities caps;
             Container root = getRoot();
             if (root == null) {
                 return null;
             }
             BufferStrategy bs = null;
-            if (TRY_FLIP) {
-                bs = createBufferStrategy(root,BufferCapabilities.FlipContents.
-                                          COPIED);
-                usingFlip = true;
+            if (SwingUtilities3.isVsyncRequested(root)) {
+                bs = createBufferStrategy(root, true);
                 if (LOGGER.isLoggable(Level.FINER)) {
-                    LOGGER.finer("createBufferStrategy: using flip strategy");
+                    LOGGER.finer("createBufferStrategy: using vsynced strategy");
                 }
             }
             if (bs == null) {
-                bs = createBufferStrategy(root, null);
-                usingFlip = false;
+                bs = createBufferStrategy(root, false);
             }
             if (!(bs instanceof SubRegionShowable)) {
                 // We do this for two reasons:
@@ -843,17 +824,24 @@
             return bs;
         }
 
-        // Creates and returns a buffer strategy of the requested type.  If
+        // Creates and returns a buffer strategy.  If
         // there is a problem creating the buffer strategy this will
         // eat the exception and return null.
         private BufferStrategy createBufferStrategy(Container root,
-                                     BufferCapabilities.FlipContents type) {
-            BufferCapabilities caps = new BufferCapabilities(
-                    new ImageCapabilities(true),
-                    new ImageCapabilities(true),
-                    type);
+                boolean isVsynced) {
+            BufferCapabilities caps;
+            if (isVsynced) {
+                caps = new ExtendedBufferCapabilities(
+                    new ImageCapabilities(true), new ImageCapabilities(true),
+                    BufferCapabilities.FlipContents.COPIED,
+                    ExtendedBufferCapabilities.VSyncType.VSYNC_ON);
+            } else {
+                caps = new BufferCapabilities(
+                    new ImageCapabilities(true), new ImageCapabilities(true),
+                    null);
+            }
             BufferStrategy bs = null;
-            if (root instanceof Applet) {
+            if (SunToolkit.isInstanceOf(root, "java.applet.Applet")) {
                 try {
                     getCreateBufferStrategyMethod().invoke(root, 2, caps);
                     bs = (BufferStrategy)getGetBufferStrategyMethod().
--- a/src/share/classes/javax/swing/JLayeredPane.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/JLayeredPane.java	Tue Jul 21 13:02:23 2009 -0700
@@ -30,6 +30,7 @@
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Rectangle;
+import sun.awt.SunToolkit;
 
 import javax.accessibility.*;
 
@@ -195,9 +196,12 @@
 
             for (Component c : getComponents()) {
                 layer = null;
-                if(c instanceof JInternalFrame || (c instanceof JComponent &&
-                         (layer = (Integer)((JComponent)c).getClientProperty(
-                          LAYER_PROPERTY)) != null)) {
+
+                if(SunToolkit.isInstanceOf(c, "javax.swing.JInternalFrame") ||
+                       (c instanceof JComponent &&
+                        (layer = (Integer)((JComponent)c).
+                                     getClientProperty(LAYER_PROPERTY)) != null))
+                {
                     if(layer != null && layer.equals(FRAME_CONTENT_LAYER))
                         continue;
                     layeredComponentFound = true;
--- a/src/share/classes/javax/swing/LayoutFocusTraversalPolicy.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/LayoutFocusTraversalPolicy.java	Tue Jul 21 13:02:23 2009 -0700
@@ -29,6 +29,7 @@
 import java.awt.ComponentOrientation;
 import java.util.Comparator;
 import java.io.*;
+import sun.awt.SunToolkit;
 
 
 /**
@@ -226,11 +227,11 @@
      protected boolean accept(Component aComponent) {
         if (!super.accept(aComponent)) {
             return false;
-        } else if (aComponent instanceof JTable) {
+        } else if (SunToolkit.isInstanceOf(aComponent, "javax.swing.JTable")) {
             // JTable only has ancestor focus bindings, we thus force it
             // to be focusable by returning true here.
             return true;
-        } else if (aComponent instanceof JComboBox) {
+        } else if (SunToolkit.isInstanceOf(aComponent, "javax.swing.JComboBox")) {
             JComboBox box = (JComboBox)aComponent;
             return box.getUI().isFocusTraversable(box);
         } else if (aComponent instanceof JComponent) {
--- a/src/share/classes/javax/swing/LookAndFeel.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/LookAndFeel.java	Tue Jul 21 13:02:23 2009 -0700
@@ -32,6 +32,7 @@
 import java.awt.Component;
 import java.awt.SystemColor;
 import java.awt.Toolkit;
+import sun.awt.SunToolkit;
 
 import javax.swing.text.*;
 import javax.swing.border.*;
@@ -271,7 +272,7 @@
         // this is a special case because the JPasswordField's ancestor heirarchy
         // includes a class outside of javax.swing, thus we cannot call setUIProperty
         // directly.
-        if (c instanceof JPasswordField) {
+        if (SunToolkit.isInstanceOf(c, "javax.swing.JPasswordField")) {
             if (!((JPasswordField)c).customSetUIProperty(propertyName, propertyValue)) {
                 c.setUIProperty(propertyName, propertyValue);
             }
--- a/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java	Tue Jul 21 13:02:23 2009 -0700
@@ -444,11 +444,10 @@
         for (Component comp : cycle) {
             if (accept(comp)) {
                 return comp;
-            } else if (comp instanceof Container && comp != aContainer) {
-                Container cont = (Container)comp;
-                if (cont.isFocusTraversalPolicyProvider()) {
-                    return cont.getFocusTraversalPolicy().getDefaultComponent(cont);
-                }
+            } else if (comp != aContainer &&
+                       (comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null)
+            {
+                return comp;
             }
         }
         return null;
--- a/src/share/classes/javax/swing/TransferHandler.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/TransferHandler.java	Tue Jul 21 13:02:23 2009 -0700
@@ -40,6 +40,7 @@
 import sun.swing.SwingUtilities2;
 import sun.awt.AppContext;
 import sun.swing.*;
+import sun.awt.SunToolkit;
 
 /**
  * This class is used to handle the transfer of a <code>Transferable</code>
@@ -283,19 +284,9 @@
                           ? ((DropTargetDragEvent)source).getLocation()
                           : ((DropTargetDropEvent)source).getLocation();
 
-            if (component instanceof JTextComponent) {
-                try {
-                    AccessibleMethod method
-                        = new AccessibleMethod(JTextComponent.class,
-                                               "dropLocationForPoint",
-                                               Point.class);
-
-                    dropLocation =
-                        (DropLocation)method.invokeNoChecked(component, p);
-                } catch (NoSuchMethodException e) {
-                    throw new AssertionError(
-                        "Couldn't locate method JTextComponent.dropLocationForPoint");
-                }
+            if (SunToolkit.isInstanceOf(component, "javax.swing.text.JTextComponent")) {
+                dropLocation = SwingAccessor.getJTextComponentAccessor().
+                                   dropLocationForPoint((JTextComponent)component, p);
             } else if (component instanceof JComponent) {
                 dropLocation = ((JComponent)component).dropLocationForPoint(p);
             }
@@ -1373,22 +1364,9 @@
                                         ? null
                                         : support.getDropLocation();
 
-            if (component instanceof JTextComponent) {
-                try {
-                    AccessibleMethod method =
-                        new AccessibleMethod(JTextComponent.class,
-                                             "setDropLocation",
-                                             DropLocation.class,
-                                             Object.class,
-                                             Boolean.TYPE);
-
-                    state =
-                        method.invokeNoChecked(component, dropLocation,
-                                               state, forDrop);
-                } catch (NoSuchMethodException e) {
-                    throw new AssertionError(
-                        "Couldn't locate method JTextComponet.setDropLocation");
-                }
+            if (SunToolkit.isInstanceOf(component, "javax.swing.text.JTextComponent")) {
+                state = SwingAccessor.getJTextComponentAccessor().
+                            setDropLocation((JTextComponent)component, dropLocation, state, forDrop);
             } else if (component instanceof JComponent) {
                 state = ((JComponent)component).setDropLocation(dropLocation, state, forDrop);
             }
--- a/src/share/classes/javax/swing/UIManager.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/UIManager.java	Tue Jul 21 13:02:23 2009 -0700
@@ -60,6 +60,7 @@
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import sun.awt.AppContext;
+import sun.awt.AWTAccessor;
 
 
 /**
@@ -1472,21 +1473,7 @@
                         return false;
                     }
                 });
-        try {
-            Method setRequestFocusControllerM = java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedExceptionAction<Method>() {
-                        public Method run() throws Exception {
-                            Method method =
-                            Component.class.getDeclaredMethod("setRequestFocusController",
-                                                              sun.awt.RequestFocusController.class);
-                            method.setAccessible(true);
-                            return method;
-                        }
-                    });
-            setRequestFocusControllerM.invoke(null, JComponent.focusController);
-        } catch (Exception e) {
-            // perhaps we should log this
-            assert false;
-        }
+        AWTAccessor.getComponentAccessor().
+            setRequestFocusController(JComponent.focusController);
     }
 }
--- a/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java	Tue Jul 21 13:02:23 2009 -0700
@@ -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
@@ -683,6 +683,7 @@
                 }
                 getDesktopManager().endResizingFrame(frame);
                 resizing = false;
+                updateFrameCursor();
             }
             _x = 0;
             _y = 0;
--- a/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java	Tue Jul 21 13:02:23 2009 -0700
@@ -31,7 +31,6 @@
 import javax.swing.plaf.UIResource;
 import javax.swing.Painter;
 import java.awt.print.PrinterGraphics;
-import static javax.swing.plaf.nimbus.NimbusLookAndFeel.deriveARGB;
 
 /**
  * Convenient base class for defining Painter instances for rendering a
@@ -347,7 +346,7 @@
      */
     protected final Color decodeColor(Color color1, Color color2,
                                       float midPoint) {
-        return new Color(deriveARGB(color1, color2, midPoint));
+        return new Color(NimbusLookAndFeel.deriveARGB(color1, color2, midPoint));
     }
 
     /**
--- a/src/share/classes/javax/swing/plaf/nimbus/Defaults.template	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/nimbus/Defaults.template	Tue Jul 21 13:02:23 2009 -0700
@@ -278,7 +278,7 @@
      * offset (if any), and whether it is to be bold, italic, or left in its
      * default form.</p>
      */
-    public static final class DerivedFont implements UIDefaults.ActiveValue {
+    static final class DerivedFont implements UIDefaults.ActiveValue {
         private float sizeOffset;
         private Boolean bold;
         private Boolean italic;
--- a/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java	Tue Jul 21 13:02:23 2009 -0700
@@ -436,15 +436,13 @@
      */
     static int deriveARGB(Color color1, Color color2, float midPoint) {
         int r = color1.getRed() +
-                (int) ((color2.getRed() - color1.getRed()) * midPoint + 0.5f);
+                Math.round((color2.getRed() - color1.getRed()) * midPoint);
         int g = color1.getGreen() +
-                (int) ((color2.getGreen() - color1.getGreen()) * midPoint +
-                        0.5f);
+                Math.round((color2.getGreen() - color1.getGreen()) * midPoint);
         int b = color1.getBlue() +
-                (int) ((color2.getBlue() - color1.getBlue()) * midPoint + 0.5f);
+                Math.round((color2.getBlue() - color1.getBlue()) * midPoint);
         int a = color1.getAlpha() +
-                (int) ((color2.getAlpha() - color1.getAlpha()) * midPoint +
-                        0.5f);
+                Math.round((color2.getAlpha() - color1.getAlpha()) * midPoint);
         return ((a & 0xFF) << 24) |
                 ((r & 0xFF) << 16) |
                 ((g & 0xFF) << 8) |
--- a/src/share/classes/javax/swing/plaf/nimbus/PainterImpl.template	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/nimbus/PainterImpl.template	Tue Jul 21 13:02:23 2009 -0700
@@ -31,7 +31,7 @@
 import javax.swing.Painter;
 
 
-public final class ${PAINTER_NAME} extends AbstractRegionPainter {
+final class ${PAINTER_NAME} extends AbstractRegionPainter {
     //package private integers representing the available states that
     //this painter will paint. These are used when creating a new instance
     //of ${PAINTER_NAME} to determine which region/state is being painted
--- a/src/share/classes/javax/swing/plaf/nimbus/package.html	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/nimbus/package.html	Tue Jul 21 13:02:23 2009 -0700
@@ -38,7 +38,7 @@
 component states.
 
 <p>Nimbus allows customizing many of its properties, including painters, by
-altering the {@link UIDefaults} table. Here's an example:
+altering the {@link javax.swing.UIDefaults} table. Here's an example:
 <code><pre>
     UIManager.put("ProgressBar.tileWidth", myTileWidth);
     UIManager.put("ProgressBar[Enabled].backgroundPainter", myBgPainter);
--- a/src/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java	Tue Jul 21 13:02:23 2009 -0700
@@ -69,6 +69,7 @@
     }
 
     protected void installDefaults() {
+        super.installDefaults();
         updateStyle(chooser);
     }
 
--- a/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2005 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
@@ -118,12 +118,12 @@
         if (System.getSecurityManager() != null) {
             if (border != null) return border;
             return SAFE_NO_FOCUS_BORDER;
-        } else {
+        } else if (border != null) {
             if (noFocusBorder == null || noFocusBorder == DEFAULT_NO_FOCUS_BORDER) {
                 return border;
             }
-            return noFocusBorder;
         }
+        return noFocusBorder;
     }
 
     /**
--- a/src/share/classes/javax/swing/text/JTextComponent.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/javax/swing/text/JTextComponent.java	Tue Jul 21 13:02:23 2009 -0700
@@ -76,6 +76,7 @@
 import sun.swing.PrintingStatus;
 import sun.swing.SwingUtilities2;
 import sun.swing.text.TextComponentPrintable;
+import sun.swing.SwingAccessor;
 
 /**
  * <code>JTextComponent</code> is the base class for swing text
@@ -761,6 +762,23 @@
         return dropMode;
     }
 
+    static {
+        SwingAccessor.setJTextComponentAccessor(
+            new SwingAccessor.JTextComponentAccessor() {
+                public TransferHandler.DropLocation dropLocationForPoint(JTextComponent textComp,
+                                                                         Point p)
+                {
+                    return textComp.dropLocationForPoint(p);
+                }
+                public Object setDropLocation(JTextComponent textComp,
+                                              TransferHandler.DropLocation location,
+                                              Object state, boolean forDrop)
+                {
+                    return textComp.setDropLocation(location, state, forDrop);
+                }
+            });
+    }
+
 
     /**
      * Calculates a drop location in this component, representing where a
--- a/src/share/classes/sun/applet/AppletClassLoader.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/applet/AppletClassLoader.java	Tue Jul 21 13:02:23 2009 -0700
@@ -69,6 +69,7 @@
     private final Object grabReleaseSynchronizer = new Object();
 
     private boolean codebaseLookup = true;
+    private volatile boolean allowRecursiveDirectoryRead = true;
 
     /*
      * Creates a new AppletClassLoader for the specified base URL.
@@ -81,6 +82,11 @@
         acc = AccessController.getContext();
     }
 
+    public void disableRecursiveDirectoryRead() {
+        allowRecursiveDirectoryRead = false;
+    }
+
+
     /**
      * Set the codebase lookup flag.
      */
@@ -188,7 +194,21 @@
             byte[] b = (byte[]) AccessController.doPrivileged(
                                new PrivilegedExceptionAction() {
                 public Object run() throws IOException {
-                    return getBytes(new URL(base, path));
+                   try {
+                        URL finalURL = new URL(base, path);
+
+                        // Make sure the codebase won't be modified
+                        if (base.getProtocol().equals(finalURL.getProtocol()) &&
+                            base.getHost().equals(finalURL.getHost()) &&
+                            base.getPort() == finalURL.getPort()) {
+                            return getBytes(finalURL);
+                        }
+                        else {
+                            return null;
+                        }
+                    } catch (Exception e) {
+                        return null;
+                    }
                 }
             }, acc);
 
@@ -243,51 +263,48 @@
         }
 
         if (path != null) {
+            final String rawPath = path;
             if (!path.endsWith(File.separator)) {
                 int endIndex = path.lastIndexOf(File.separatorChar);
                 if (endIndex != -1) {
-                        path = path.substring(0, endIndex+1) + "-";
+                        path = path.substring(0, endIndex + 1) + "-";
                         perms.add(new FilePermission(path,
                             SecurityConstants.FILE_READ_ACTION));
                 }
             }
-            perms.add(new SocketPermission("localhost",
-                SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
-            AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    try {
-                        String host = InetAddress.getLocalHost().getHostName();
-                        perms.add(new SocketPermission(host,
-                            SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
-                    } catch (UnknownHostException uhe) {
-
-                    }
-                    return null;
-                }
-            });
+            final File f = new File(rawPath);
+            final boolean isDirectory = f.isDirectory();
+            // grant codebase recursive read permission
+            // this should only be granted to non-UNC file URL codebase and
+            // the codesource path must either be a directory, or a file
+            // that ends with .jar or .zip
+            if (allowRecursiveDirectoryRead && (isDirectory ||
+                    rawPath.toLowerCase().endsWith(".jar") ||
+                    rawPath.toLowerCase().endsWith(".zip"))) {
 
             Permission bperm;
-            try {
-                bperm = base.openConnection().getPermission();
-            } catch (java.io.IOException ioe) {
-                bperm = null;
+                try {
+                    bperm = base.openConnection().getPermission();
+                } catch (java.io.IOException ioe) {
+                    bperm = null;
+                }
+                if (bperm instanceof FilePermission) {
+                    String bpath = bperm.getName();
+                    if (bpath.endsWith(File.separator)) {
+                        bpath += "-";
+                    }
+                    perms.add(new FilePermission(bpath,
+                        SecurityConstants.FILE_READ_ACTION));
+                } else if ((bperm == null) && (base.getProtocol().equals("file"))) {
+                    String bpath = base.getFile().replace('/', File.separatorChar);
+                    bpath = ParseUtil.decode(bpath);
+                    if (bpath.endsWith(File.separator)) {
+                        bpath += "-";
+                    }
+                    perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION));
+                }
+
             }
-            if (bperm instanceof FilePermission) {
-                String bpath = bperm.getName();
-                if (bpath.endsWith(File.separator)) {
-                    bpath += "-";
-                }
-                perms.add(new FilePermission(bpath,
-                    SecurityConstants.FILE_READ_ACTION));
-            } else if ((bperm == null) && (base.getProtocol().equals("file"))) {
-                String bpath = base.getFile().replace('/', File.separatorChar);
-                bpath = ParseUtil.decode(bpath);
-                if (bpath.endsWith(File.separator)) {
-                    bpath += "-";
-                }
-                perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION));
-            }
-
         }
         return perms;
     }
@@ -702,7 +719,7 @@
      * Grab this AppletClassLoader and its ThreadGroup/AppContext, so they
      * won't be destroyed.
      */
-    void grab() {
+public     void grab() {
         synchronized(grabReleaseSynchronizer) {
             usageCount++;
         }
@@ -740,11 +757,7 @@
                 --usageCount;
             } else {
                 synchronized(threadGroupSynchronizer) {
-                    // Store app context in temp variable
-                    tempAppContext = appContext;
-                    usageCount = 0;
-                    appContext = null;
-                    threadGroup = null;
+                    tempAppContext = resetAppContext();
                 }
             }
         }
@@ -758,6 +771,29 @@
         }
     }
 
+    /*
+     * reset classloader's AppContext and ThreadGroup
+     * This method is for subclass PluginClassLoader to
+     * reset superclass's AppContext and ThreadGroup but do
+     * not dispose the AppContext. PluginClassLoader does not
+     * use UsageCount to decide whether to dispose AppContext
+     *
+     * @return previous AppContext
+     */
+    protected AppContext resetAppContext() {
+        AppContext tempAppContext = null;
+
+        synchronized(threadGroupSynchronizer) {
+            // Store app context in temp variable
+            tempAppContext = appContext;
+            usageCount = 0;
+            appContext = null;
+            threadGroup = null;
+        }
+        return tempAppContext;
+    }
+
+
     // Hash map to store applet compatibility info
     private HashMap jdk11AppletInfo = new HashMap();
     private HashMap jdk12AppletInfo = new HashMap();
--- a/src/share/classes/sun/applet/AppletPanel.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/applet/AppletPanel.java	Tue Jul 21 13:02:23 2009 -0700
@@ -80,7 +80,7 @@
     /**
      * The classloader for the applet.
      */
-    AppletClassLoader loader;
+    protected AppletClassLoader loader;
 
     /* applet event ids */
     public final static int APPLET_DISPOSE = 0;
@@ -116,7 +116,7 @@
     /**
      * The thread for the applet.
      */
-    Thread handler;
+    protected Thread handler;
 
 
     /**
--- a/src/share/classes/sun/awt/AWTAccessor.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/awt/AWTAccessor.java	Tue Jul 21 13:02:23 2009 -0700
@@ -30,6 +30,7 @@
 import java.awt.image.BufferedImage;
 
 import sun.misc.Unsafe;
+import java.awt.peer.ComponentPeer;
 
 /**
  * The AWTAccessor utility class.
@@ -98,6 +99,21 @@
          * any client code.
          */
         boolean isVisible_NoClientCode(Component comp);
+
+        /**
+         * Sets the RequestFocusController.
+         */
+        void setRequestFocusController(RequestFocusController requestController);
+
+        /**
+         * Returns the appContext of the component.
+         */
+        AppContext getAppContext(Component comp);
+
+        /**
+         * Sets the appContext of the component.
+         */
+        void setAppContext(Component comp, AppContext appContext);
     }
 
     /*
@@ -153,23 +169,21 @@
          */
         Point2D calculateSecurityWarningPosition(Window window,
                 double x, double y, double w, double h);
+
+        /** Sets the synchronous status of focus requests on lightweight
+         * components in the specified window to the specified value.
+         */
+        void setLWRequestStatus(Window changed, boolean status);
     }
 
     /*
      * An accessor for the AWTEvent class.
      */
     public interface AWTEventAccessor {
-        /*
-         *
-         * Sets the flag on this AWTEvent indicating that it was
-         * generated by the system.
+        /**
+         * Marks the event as posted.
          */
-        void setSystemGenerated(AWTEvent ev);
-        /*
-         *
-         * Indicates whether this AWTEvent was generated by the system.
-         */
-        boolean isSystemGenerated(AWTEvent ev);
+        void setPosted(AWTEvent ev);
     }
 
     /*
@@ -216,6 +230,51 @@
     }
 
     /*
+     * An accessor for the MenuComponent class.
+     */
+    public interface MenuComponentAccessor {
+        /**
+         * Returns the appContext of the menu component.
+         */
+        AppContext getAppContext(MenuComponent menuComp);
+
+        /**
+         * Sets the appContext of the menu component.
+         */
+        void setAppContext(MenuComponent menuComp, AppContext appContext);
+
+        /**
+         * Returns the menu container of the menu component
+         */
+        MenuContainer getParent(MenuComponent menuComp);
+    }
+
+    /*
+     * An accessor for the EventQueue class
+     */
+    public interface EventQueueAccessor {
+        /*
+         * Gets the next event queue.
+         */
+        EventQueue getNextQueue(EventQueue eventQueue);
+        /*
+         * Gets the event dispatch thread.
+         */
+        Thread getDispatchThread(EventQueue eventQueue);
+    }
+
+    /*
+     * An accessor for the PopupMenu class
+     */
+    public interface PopupMenuAccessor {
+        /*
+         * Returns whether the popup menu is attached to a tray
+         */
+        boolean isTrayIconPopup(PopupMenu popupMenu);
+    }
+
+
+    /*
      * The java.awt.Component class accessor object.
      */
     private static ComponentAccessor componentAccessor;
@@ -241,6 +300,21 @@
     private static KeyboardFocusManagerAccessor kfmAccessor;
 
     /*
+     * The java.awt.MenuComponent class accessor object.
+     */
+    private static MenuComponentAccessor menuComponentAccessor;
+
+    /*
+     * The java.awt.EventQueue class accessor object.
+     */
+    private static EventQueueAccessor eventQueueAccessor;
+
+    /*
+     * The java.awt.PopupMenu class accessor object.
+     */
+    private static PopupMenuAccessor popupMenuAccessor;
+
+    /*
      * Set an accessor object for the java.awt.Component class.
      */
     public static void setComponentAccessor(ComponentAccessor ca) {
@@ -286,6 +360,9 @@
      * Retrieve the accessor object for the java.awt.AWTEvent class.
      */
     public static AWTEventAccessor getAWTEventAccessor() {
+        if (awtEventAccessor == null) {
+            unsafe.ensureClassInitialized(AWTEvent.class);
+        }
         return awtEventAccessor;
     }
 
@@ -322,4 +399,55 @@
         }
         return kfmAccessor;
     }
+
+    /*
+     * Set an accessor object for the java.awt.MenuComponent class.
+     */
+    public static void setMenuComponentAccessor(MenuComponentAccessor mca) {
+        menuComponentAccessor = mca;
+    }
+
+    /*
+     * Retrieve the accessor object for the java.awt.MenuComponent class.
+     */
+    public static MenuComponentAccessor getMenuComponentAccessor() {
+        if (menuComponentAccessor == null) {
+            unsafe.ensureClassInitialized(MenuComponent.class);
+        }
+        return menuComponentAccessor;
+    }
+
+    /*
+     * Set an accessor object for the java.awt.EventQueue class.
+     */
+    public static void setEventQueueAccessor(EventQueueAccessor eqa) {
+        eventQueueAccessor = eqa;
+    }
+
+    /*
+     * Retrieve the accessor object for the java.awt.EventQueue class.
+     */
+    public static EventQueueAccessor getEventQueueAccessor() {
+        if (eventQueueAccessor == null) {
+            unsafe.ensureClassInitialized(EventQueue.class);
+        }
+        return eventQueueAccessor;
+    }
+
+    /*
+     * Set an accessor object for the java.awt.PopupMenu class.
+     */
+    public static void setPopupMenuAccessor(PopupMenuAccessor pma) {
+        popupMenuAccessor = pma;
+    }
+
+    /*
+     * Retrieve the accessor object for the java.awt.PopupMenu class.
+     */
+    public static PopupMenuAccessor getPopupMenuAccessor() {
+        if (popupMenuAccessor == null) {
+            unsafe.ensureClassInitialized(PopupMenu.class);
+        }
+        return popupMenuAccessor;
+    }
 }
--- a/src/share/classes/sun/awt/SunToolkit.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/awt/SunToolkit.java	Tue Jul 21 13:02:23 2009 -0700
@@ -77,14 +77,7 @@
      */
     public static final int GRAB_EVENT_MASK = 0x80000000;
 
-    private static Field syncLWRequestsField;
     private static Method  wakeupMethod;
-    private static Field componentKeyField;
-    private static Field menuComponentKeyField;
-    private static Field trayIconKeyField;
-    private static Field componentAppContextField;
-    private static Field menuComponentAppContextField;
-    private static Field isPostedField;
     /* The key to put()/get() the PostEventQueue into/from the AppContext.
      */
     private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
@@ -422,32 +415,21 @@
     private static final Map appContextMap =
         Collections.synchronizedMap(new WeakHashMap());
 
-
     /**
      * Sets the appContext field of target. If target is not a Component or
      * MenuComponent, this returns false.
      */
-    private static boolean setAppContext(Object target, AppContext context)
-    {
-        if (!(target instanceof Component) && !(target instanceof MenuComponent)) {
+    private static boolean setAppContext(Object target,
+                                         AppContext context) {
+        if (target instanceof Component) {
+            AWTAccessor.getComponentAccessor().
+                setAppContext((Component)target, context);
+        } else if (target instanceof MenuComponent) {
+            AWTAccessor.getMenuComponentAccessor().
+                setAppContext((MenuComponent)target, context);
+        } else {
             return false;
         }
-        try{
-            if (target instanceof Component){
-                if (componentAppContextField == null) {
-                    componentAppContextField = getField(Component.class, "appContext");
-                }
-                componentAppContextField.set(target, context);
-            } else if (target instanceof MenuComponent) {
-                if (menuComponentAppContextField == null) {
-                    menuComponentAppContextField = getField(MenuComponent.class, "appContext");
-                }
-                menuComponentAppContextField.set(target, context);
-            }
-        } catch( IllegalAccessException e){
-            assert false;
-        }
-
         return true;
     }
 
@@ -456,23 +438,15 @@
      * Component or MenuComponent this returns null.
      */
     private static AppContext getAppContext(Object target) {
-        AppContext retObj = null;
-        try{
-            if (target instanceof Component){
-                if (componentAppContextField == null) {
-                    componentAppContextField = getField(Component.class, "appContext");
-                }
-                retObj = (AppContext) componentAppContextField.get(target);
-            } else if (target instanceof MenuComponent) {
-                if (menuComponentAppContextField == null) {
-                    menuComponentAppContextField = getField(MenuComponent.class, "appContext");
-                }
-                retObj = (AppContext) menuComponentAppContextField.get(target);
-            }
-        } catch( IllegalAccessException e){
-            assert false;
+        if (target instanceof Component) {
+            return AWTAccessor.getComponentAccessor().
+                       getAppContext((Component)target);
+        } else if (target instanceof MenuComponent) {
+            return AWTAccessor.getMenuComponentAccessor().
+                       getAppContext((MenuComponent)target);
+        } else {
+            return null;
         }
-        return retObj;
     }
 
     /*
@@ -520,16 +494,7 @@
       */
 
     public static void setLWRequestStatus(Window changed,boolean status){
-        if (syncLWRequestsField == null){
-            syncLWRequestsField = getField(Window.class, "syncLWRequests");
-        }
-        try{
-            if (syncLWRequestsField != null){
-                syncLWRequestsField.setBoolean(changed, status);
-            }
-        } catch( IllegalAccessException e){
-            assert false;
-        }
+        AWTAccessor.getWindowAccessor().setLWRequestStatus(changed, status);
     };
 
     public static void checkAndSetPolicy(Container cont, boolean isSwingCont)
@@ -637,18 +602,9 @@
      * Post AWTEvent of high priority.
      */
     public static void postPriorityEvent(final AWTEvent e) {
-        if (isPostedField == null) {
-            isPostedField = getField(AWTEvent.class, "isPosted");
-        }
         PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
                 public void run() {
-                    try {
-                        isPostedField.setBoolean(e, true);
-                    } catch (IllegalArgumentException e) {
-                        assert(false);
-                    } catch (IllegalAccessException e) {
-                        assert(false);
-                    }
+                    AWTAccessor.getAWTEventAccessor().setPosted(e);
                     ((Component)e.getSource()).dispatchEvent(e);
                 }
             }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
@@ -757,36 +713,6 @@
     }
 
     /*
-     * Returns next queue for the given EventQueue which has private access
-     */
-    private static EventQueue getNextQueue(final Object o) {
-        EventQueue result = null;
-        try{
-            Field nextQueueField = getField(EventQueue.class,
-                                            "nextQueue");
-            result = (EventQueue)nextQueueField.get(o);
-        } catch( IllegalAccessException e){
-            assert false;
-        }
-        return result;
-    }
-
-    /*
-     * Returns dispatch thread for the given EventQueue which has private access
-     */
-    private static Thread getDispatchThread(final Object o) {
-        Thread result = null;
-        try{
-            Field dispatchThreadField = getField(EventQueue.class,
-                                                 "dispatchThread");
-            result = (Thread)dispatchThreadField.get(o);
-        } catch( IllegalAccessException e){
-            assert false;
-        }
-        return result;
-    }
-
-    /*
      * Returns true if the calling thread is the event dispatch thread
      * contained within AppContext which associated with the given target.
      * Use this call to ensure that a given task is being executed
@@ -796,13 +722,14 @@
         AppContext appContext = targetToAppContext(target);
         EventQueue eq = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
 
-        EventQueue next = getNextQueue(eq);
+        AWTAccessor.EventQueueAccessor accessor = AWTAccessor.getEventQueueAccessor();
+        EventQueue next = accessor.getNextQueue(eq);
         while (next != null) {
             eq = next;
-            next = getNextQueue(eq);
+            next = accessor.getNextQueue(eq);
         }
 
-        return (Thread.currentThread() == getDispatchThread(eq));
+        return (Thread.currentThread() == accessor.getDispatchThread(eq));
     }
 
     public Dimension getScreenSize() {
@@ -1356,22 +1283,7 @@
         return false;
     }
 
-    private static Dialog.ModalExclusionType DEFAULT_MODAL_EXCLUSION_TYPE;
-
-    static {
-        DEFAULT_MODAL_EXCLUSION_TYPE = (Dialog.ModalExclusionType)AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                Dialog.ModalExclusionType defaultType = Dialog.ModalExclusionType.NO_EXCLUDE;
-                try {
-                    java.lang.reflect.Field f = Dialog.class.getDeclaredField("DEFAULT_MODAL_EXCLUSION_TYPE");
-                    f.setAccessible(true);
-                    defaultType = (Dialog.ModalExclusionType)f.get(null);
-                } catch (Exception e) {
-                }
-                return defaultType;
-            }
-        });
-    }
+    private static Dialog.ModalExclusionType DEFAULT_MODAL_EXCLUSION_TYPE = null;
 
     /**
      * Returns whether the XEmbed server feature is requested by
@@ -1430,6 +1342,9 @@
      */
     public static void setModalExcluded(Window window)
     {
+        if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
+            DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
+        }
         window.setModalExclusionType(DEFAULT_MODAL_EXCLUSION_TYPE);
     }
 
@@ -1451,6 +1366,9 @@
      */
     public static boolean isModalExcluded(Window window)
     {
+        if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
+            DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
+        }
         return window.getModalExclusionType().compareTo(DEFAULT_MODAL_EXCLUSION_TYPE) >= 0;
     }
 
@@ -2104,6 +2022,42 @@
     public int getNumberOfButtons(){
         return 3;
     }
+
+    /**
+     * Checks that the given object implements/extends the given
+     * interface/class.
+     *
+     * Note that using the instanceof operator causes a class to be loaded.
+     * Using this method doesn't load a class and it can be used instead of
+     * the instanceof operator for performance reasons.
+     *
+     * @param obj Object to be checked
+     * @param type The name of the interface/class. Must be
+     * fully-qualified interface/class name.
+     * @return true, if this object implements/extends the given
+     *         interface/class, false, otherwise, or if obj or type is null
+     */
+    public static boolean isInstanceOf(Object obj, String type) {
+        if (obj == null) return false;
+        if (type == null) return false;
+
+        return isInstanceOf(obj.getClass(), type);
+    }
+
+    private static boolean isInstanceOf(Class cls, String type) {
+        if (cls == null) return false;
+
+        if (cls.getName().equals(type)) {
+            return true;
+        }
+
+        for (Class c : cls.getInterfaces()) {
+            if (c.getName().equals(type)) {
+                return true;
+            }
+        }
+        return isInstanceOf(cls.getSuperclass(), type);
+    }
 } // class SunToolkit
 
 
--- a/src/share/classes/sun/awt/shell/ShellFolder.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/awt/shell/ShellFolder.java	Tue Jul 21 13:02:23 2009 -0700
@@ -202,8 +202,16 @@
     private static ShellFolderManager shellFolderManager;
 
     static {
-        Class managerClass = (Class)Toolkit.getDefaultToolkit().
-            getDesktopProperty("Shell.shellFolderManager");
+        String managerClassName = (String)Toolkit.getDefaultToolkit().
+                                      getDesktopProperty("Shell.shellFolderManager");
+        Class managerClass = null;
+        try {
+            managerClass = Class.forName(managerClassName);
+        // swallow the exceptions below and use default shell folder
+        } catch(ClassNotFoundException e) {
+        } catch(NullPointerException e) {
+        }
+
         if (managerClass == null) {
             managerClass = ShellFolderManager.class;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/BackgroundDownloader.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+import java.io.*;
+
+/**
+ * Invoked by DownloadManager to begin (in a new JRE) the process of downloading
+ * all remaining JRE components in the background.  A mutex is used to ensure
+ * that only one BackgroundDownloader can be active at a time.
+ *
+ */
+public class BackgroundDownloader {
+    public static final String BACKGROUND_DOWNLOAD_PROPERTY = "kernel.background.download";
+    // relative to the bundle directory
+    public static final String PID_PATH = "tmp" + File.separator + "background.pid";
+
+    // Time to wait before beginning to download components.  Gives the JRE
+    // which spawned this one a chance to get its downloads going.
+    private static final int WAIT_TIME = 10000;
+
+    private static Mutex backgroundMutex;
+
+    static synchronized Mutex getBackgroundMutex() {
+        if (backgroundMutex == null)
+            backgroundMutex = Mutex.create(DownloadManager.MUTEX_PREFIX + "background");
+        return backgroundMutex;
+    }
+
+    private static void doBackgroundDownloads() {
+        if (DownloadManager.isJREComplete())
+            return;
+        if (getBackgroundMutex().acquire(0)) { // give up and exit immediately if we can't acquire mutex
+            try {
+                writePid();
+                Thread.sleep(WAIT_TIME);
+                DownloadManager.doBackgroundDownloads(false);
+                DownloadManager.performCompletionIfNeeded();
+            }
+            catch (InterruptedException e) {
+            }
+            finally {
+                getBackgroundMutex().release();
+            }
+        }
+        else {
+            System.err.println("Unable to acquire background download mutex.");
+            System.exit(1);
+        }
+    }
+
+
+    /**
+     * Writes the current process ID to a file, so that the uninstaller can
+     * find and kill this process if needed.
+     */
+    private static void writePid() {
+        try {
+            File pid = new File(DownloadManager.getBundlePath(), PID_PATH);
+            pid.getParentFile().mkdirs();
+            PrintStream out = new PrintStream(new FileOutputStream(pid));
+            pid.deleteOnExit();
+            out.println(DownloadManager.getCurrentProcessId());
+            out.close();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+
+    /**
+     * Reads from an InputStream until exhausted, writing all data to the
+     * specified OutputStream.
+     */
+    private static void send(InputStream in, OutputStream out)
+                                throws IOException {
+        int c;
+        byte[] buffer = new byte[2048];
+        while ((c = in.read(buffer)) > 0)
+            out.write(buffer, 0, c);
+    }
+
+     /*
+      * Returns the value of the BACKGROUND_DOWNLOAD_PROPERTY.
+      * Checks if system property has been set first
+      * then checks if registry key to disable background download
+      * has been set.
+      */
+     public static boolean  getBackgroundDownloadProperty(){
+         /*
+          * Check registry key value
+          */
+         boolean bgDownloadEnabled = getBackgroundDownloadKey();
+
+         /*
+          * Check system property - it should override the registry
+          * key value.
+          */
+         if (System.getProperty(BACKGROUND_DOWNLOAD_PROPERTY) != null){
+             bgDownloadEnabled = Boolean.valueOf(
+                      System.getProperty(BACKGROUND_DOWNLOAD_PROPERTY));
+         }
+         return bgDownloadEnabled;
+
+    }
+
+    // This method is to retrieve the value of registry key
+    // that disables background download.
+    static native boolean getBackgroundDownloadKey();
+
+
+    static void startBackgroundDownloads() {
+        if (!getBackgroundDownloadProperty()){
+            // If getBackgroundDownloadProperty() returns false
+            // we're doing the downloads from this VM; we don't want to
+            // spawn another one
+            return;
+        }
+
+        // if System.err isn't initialized yet, it means the charsets aren't
+        // available yet and we're going to run into trouble down below.  Wait
+        // until it's ready.
+        while (System.err == null) {
+            try {
+                Thread.sleep(1000);
+            }
+            catch (InterruptedException e) {
+                return;
+            }
+        }
+
+        try {
+            String args = "-D" + BACKGROUND_DOWNLOAD_PROPERTY + "=false -Xmx256m";
+            String backgroundDownloadURL = DownloadManager.getBaseDownloadURL();
+
+            // only set KERNEL_DOWNLOAD_URL_PROPERTY if we override
+            // the default download url
+            if (backgroundDownloadURL != null &&
+                    backgroundDownloadURL.equals(
+                    DownloadManager.DEFAULT_DOWNLOAD_URL) == false) {
+                args += " -D" + DownloadManager.KERNEL_DOWNLOAD_URL_PROPERTY +
+                        "=" + backgroundDownloadURL;
+            };
+            args += " sun.jkernel.BackgroundDownloader";
+            final Process jvm = Runtime.getRuntime().exec("\"" + new File(System.getProperty("java.home"), "bin" +
+                   File.separator + "java.exe") + "\" " + args);
+            Thread outputReader = new Thread("kernelOutputReader") {
+                public void run() {
+                    try {
+                        InputStream in = jvm.getInputStream();
+                        send(in, new PrintStream(new ByteArrayOutputStream()));
+                    }
+                    catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            };
+            outputReader.setDaemon(true);
+            outputReader.start();
+
+            Thread errorReader = new Thread("kernelErrorReader") {
+                public void run() {
+                    try {
+                        InputStream in = jvm.getErrorStream();
+                        send(in, new PrintStream(new ByteArrayOutputStream()));
+                    }
+                    catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            };
+            errorReader.setDaemon(true);
+            errorReader.start();
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+            // TODO: error handling
+        }
+    }
+
+
+    public static void main(String[] arg) {
+        doBackgroundDownloads();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/Bundle.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,922 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+import java.io.*;
+import java.net.HttpRetryException;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.jar.*;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * Represents a bundle which may or may not currently be installed.
+ *
+ *@author Ethan Nicholas
+ */
+public class Bundle {
+    static {
+        if (!DownloadManager.jkernelLibLoaded) {
+            // This code can be invoked directly by the deploy build.
+            System.loadLibrary("jkernel");
+        }
+    }
+    /**
+     * Compress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA)
+     * if available, put the uncompressed data into file destPath and
+     * return true. If not available return false and do nothing with destPath.
+     *
+     * @param srcPath path to existing uncompressed file
+     * @param destPath path for the compressed file to be created
+     * @returns true if extra algorithm used, false if not
+     * @throws IOException if the extra compression code should be available
+     *     but cannot be located or linked to, the destination file already
+     *     exists or cannot be opened for writing, or the compression fails
+     */
+    public static native boolean extraCompress(String srcPath,
+        String destPath) throws IOException;
+
+    /**
+     * Decompress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA)
+     * if available, put the uncompressed data into file destPath and
+     * return true. If not available return false and do nothing with
+     * destPath.
+     * @param srcPath path to existing compressed file
+     * @param destPath path to uncompressed file to be created
+     * @returns true if extra algorithm used, false if not
+     * @throws IOException if the extra uncompression code should be available
+     *     but cannot be located or linked to, the destination file already
+     *     exists or cannot be opened for writing, or the uncompression fails
+     */
+    public static native boolean extraUncompress(String srcPath,
+        String destPath) throws IOException;
+
+    private static final String BUNDLE_JAR_ENTRY_NAME = "classes.jar";
+
+    /** The bundle is not present. */
+    protected static final int NOT_DOWNLOADED = 0;
+
+    /**
+     * The bundle is in the download queue but has not finished downloading.
+     */
+    protected static final int QUEUED = 1;
+
+    /** The bundle has finished downloading but is not installed. */
+    protected static final int DOWNLOADED = 2;
+
+    /** The bundle is fully installed and functional. */
+    protected static final int INSTALLED = 3;
+
+    /** Thread pool used to manage dependency downloads. */
+    private static ExecutorService threadPool;
+
+    /** Size of thread pool. */
+    static final int THREADS;
+
+    static {
+        String downloads = System.getProperty(
+                DownloadManager.KERNEL_SIMULTANEOUS_DOWNLOADS_PROPERTY);
+        if (downloads != null)
+            THREADS = Integer.parseInt(downloads.trim());
+        else
+            THREADS = 1;
+    }
+
+    /** Mutex used to safely access receipts file. */
+    private static Mutex receiptsMutex;
+
+    /** Maps bundle names to known bundle instances. */
+    private static Map<String, Bundle> bundles =
+            new HashMap<String, Bundle>();
+
+    /** Contains the names of currently-installed bundles. */
+    static Set<String> receipts = new HashSet<String>();
+
+    private static int bytesDownloaded;
+
+    /** Path where bundle receipts are written. */
+    private static File receiptPath = new File(DownloadManager.getBundlePath(),
+            "receipts");
+
+    /** The size of the receipts file the last time we saw it. */
+    private static int receiptsSize;
+
+    /** The bundle name, e.g. "java_awt". */
+    private String name;
+
+    /** The path to which we are saving the downloaded bundle file. */
+    private File localPath;
+
+    /**
+     * The path of the extracted JAR file containing the bundle's classes.
+     */
+    private File jarPath;
+
+    // for vista IE7 protected mode
+    private File lowJarPath;
+    private File lowJavaPath = null;
+
+    /** The current state (DOWNLOADED, INSTALLED, etc.). */
+    protected int state;
+
+    /**
+     * True if we should delete the downloaded bundle after installing it.
+     */
+    protected boolean deleteOnInstall = true;
+
+    private static Mutex getReceiptsMutex() {
+        if (receiptsMutex == null)
+            receiptsMutex = Mutex.create(DownloadManager.MUTEX_PREFIX +
+                    "receipts");
+        return receiptsMutex;
+    }
+
+
+    /**
+     * Reads the receipts file in order to seed the list of currently
+     * installed bundles.
+     */
+    static synchronized void loadReceipts() {
+        getReceiptsMutex().acquire();
+        try {
+            if (receiptPath.exists()) {
+                int size = (int) receiptPath.length();
+                if (size != receiptsSize) { // ensure that it has actually
+                                            // been modified
+                    DataInputStream in = null;
+                    try {
+                        receipts.clear();
+                        for (String bundleName : DownloadManager.getBundleNames()) {
+                            if ("true".equals(DownloadManager.getBundleProperty(bundleName,
+                                    DownloadManager.INSTALL_PROPERTY)))
+                                receipts.add(bundleName);
+                        }
+                        if (receiptPath.exists()) {
+                            in = new DataInputStream(new BufferedInputStream(
+                                    new FileInputStream(receiptPath)));
+                            String line;
+                            while ((line = in.readLine()) != null) {
+                                receipts.add(line.trim());
+                            }
+                        }
+                        receiptsSize = size;
+                    }
+                    catch (IOException e) {
+                        DownloadManager.log(e);
+                        // safe to continue, as the worst that happens is
+                        // we re-download existing bundles
+                    } finally {
+                        if (in != null) {
+                            try {
+                                in.close();
+                            } catch (IOException ioe) {
+                                DownloadManager.log(ioe);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            getReceiptsMutex().release();
+        }
+    }
+
+
+    /** Returns the bundle corresponding to the specified name. */
+    public static synchronized Bundle getBundle(String bundleId)
+            throws IOException {
+        Bundle result =(Bundle) bundles.get(bundleId);
+        if (result == null && (bundleId.equals("merged") ||
+                Arrays.asList(DownloadManager.getBundleNames()).contains(bundleId))) {
+            result = new Bundle();
+            result.name = bundleId;
+
+            if (DownloadManager.isWindowsVista()) {
+                result.localPath =
+                        new File(DownloadManager.getLocalLowTempBundlePath(),
+                                 bundleId + ".zip");
+                result.lowJavaPath = new File(
+                        DownloadManager.getLocalLowKernelJava() + bundleId);
+            } else {
+                result.localPath = new File(DownloadManager.getBundlePath(),
+                        bundleId + ".zip");
+            }
+
+            String jarPath = DownloadManager.getBundleProperty(bundleId,
+                    DownloadManager.JAR_PATH_PROPERTY);
+            if (jarPath != null) {
+                if (DownloadManager.isWindowsVista()) {
+                    result.lowJarPath = new File(
+                        DownloadManager.getLocalLowKernelJava() + bundleId,
+                        jarPath);
+                }
+                result.jarPath = new File(DownloadManager.JAVA_HOME,
+                        jarPath);
+
+            } else {
+
+                if (DownloadManager.isWindowsVista()) {
+                    result.lowJarPath = new File(
+                        DownloadManager.getLocalLowKernelJava() + bundleId +
+                            "\\lib\\bundles",
+                        bundleId + ".jar");
+                }
+
+                result.jarPath = new File(DownloadManager.getBundlePath(),
+                        bundleId + ".jar");
+
+            }
+
+            bundles.put(bundleId, result);
+        }
+        return result;
+    }
+
+
+    /**
+     * Returns the name of this bundle.  The name is typically defined by
+     * the bundles.xml file.
+     */
+    public String getName() {
+        return name;
+    }
+
+
+    /**
+     * Sets the name of this bundle.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+
+    /**
+     * Returns the path to the bundle file on the local filesystem.  The file
+     * will only exist if the bundle has already been downloaded;  otherwise
+     * it will be created when download() is called.
+     */
+    public File getLocalPath() {
+        return localPath;
+    }
+
+
+    /**
+     * Sets the location of the bundle file on the local filesystem.  If the
+     * file already exists, the bundle will be considered downloaded;
+     * otherwise the file will be created when download() is called.
+     */
+    public void setLocalPath(File localPath) {
+        this.localPath = localPath;
+    }
+
+
+    /**
+     * Returns the path to the extracted JAR file containing this bundle's
+     * classes.  This file should only exist after the bundle has been
+     * installed.
+     */
+    public File getJarPath() {
+        return jarPath;
+    }
+
+
+    /**
+     * Sets the path to the extracted JAR file containing this bundle's
+     * classes.  This file will be created as part of installing the bundle.
+     */
+    public void setJarPath(File jarPath) {
+        this.jarPath = jarPath;
+    }
+
+
+    /**
+     * Returns the size of the bundle download in bytes.
+     */
+    public int getSize() {
+        return Integer.valueOf(DownloadManager.getBundleProperty(getName(),
+                DownloadManager.SIZE_PROPERTY));
+    }
+
+
+    /**
+     * Returns true if the bundle file (getLocalPath()) should be deleted
+     * when the bundle is successfully installed.  Defaults to true.
+     */
+    public boolean getDeleteOnInstall() {
+        return deleteOnInstall;
+    }
+
+
+    /**
+     * Sets whether the bundle file (getLocalPath()) should be deleted
+     * when the bundle is successfully installed.  Defaults to true.
+     */
+    public void setDeleteOnInstall(boolean deleteOnInstall) {
+        this.deleteOnInstall = deleteOnInstall;
+    }
+
+
+    /** Sets the current state of this bundle to match reality. */
+    protected void updateState() {
+        synchronized(Bundle.class) {
+            loadReceipts();
+            if (receipts.contains(name) ||
+                    "true".equals(DownloadManager.getBundleProperty(name,
+                    DownloadManager.INSTALL_PROPERTY)))
+                state = Bundle.INSTALLED;
+            else if (localPath.exists())
+                state = Bundle.DOWNLOADED;
+        }
+    }
+
+
+    private String getURL(boolean showUI) throws IOException {
+        Properties urls = DownloadManager.getBundleURLs(showUI);
+        String result = urls.getProperty(name + ".zip");
+        if (result == null) {
+            result = urls.getProperty(name);
+            if (result == null) {
+                DownloadManager.log("Unable to determine bundle URL for " + this);
+                DownloadManager.log("Bundle URLs: " + urls);
+                DownloadManager.sendErrorPing(DownloadManager.ERROR_NO_SUCH_BUNDLE);
+
+                throw new NullPointerException("Unable to determine URL " +
+                        "for bundle: " + this);
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Downloads the bundle.  This method blocks until the download is
+     * complete.
+     *
+     *@param showProgress true to display a progress dialog
+     */
+    private void download(boolean showProgress) {
+        if (DownloadManager.isJREComplete())
+            return;
+        Mutex mutex = Mutex.create(DownloadManager.MUTEX_PREFIX + name +
+                ".download");
+        mutex.acquire();
+        try {
+            long start = System.currentTimeMillis();
+
+            boolean retry;
+
+            do {
+                retry = false;
+                updateState();
+                if (state == DOWNLOADED || state == INSTALLED) {
+                    return;
+                }
+                File tmp = null;
+                try {
+                    tmp = new File(localPath + ".tmp");
+
+                    // tmp.deleteOnExit();
+
+                    if (DownloadManager.getBaseDownloadURL().equals(
+                            DownloadManager.RESOURCE_URL)) {
+                        // RESOURCE_URL is used during build process, to
+                        // avoid actual network traffic.  This is called in
+                        // the SplitJRE DownloadTest to determine which
+                        // classes are needed to support downloads, but we
+                        // bypass the actual HTTP download to simplify the
+                        // build process (it's all native code, so from
+                        // DownloadTest's standpoint it doesn't matter if we
+                        // really call it or not).
+                        String path = "/" + name + ".zip";
+                        InputStream in =
+                                getClass().getResourceAsStream(path);
+                        if (in == null)
+                            throw new IOException("could not locate " +
+                                    "resource: " + path);
+                        FileOutputStream out = new FileOutputStream(tmp);
+                        DownloadManager.send(in, out);
+                        in.close();
+                        out.close();
+                    }
+                    else {
+                        try {
+                            String bundleURL = getURL(showProgress);
+                            DownloadManager.log("Downloading from: " +
+                                        bundleURL);
+                            DownloadManager.downloadFromURL(bundleURL, tmp,
+                                    name.replace('_', '.'), showProgress);
+                        }
+                        catch (HttpRetryException e) {
+                            // Akamai returned a 403, get new URL
+                            DownloadManager.flushBundleURLs();
+                            String bundleURL = getURL(showProgress);
+                            DownloadManager.log("Retrying at new " +
+                                        "URL: " + bundleURL);
+                            DownloadManager.downloadFromURL(bundleURL, tmp,
+                                    name.replace('_', '.'),
+                                    showProgress);
+                            // we intentionally don't do a 403 retry
+                            // again, to avoid infinite retries
+                        }
+                    }
+                    if (!tmp.exists() || tmp.length() == 0) {
+                        if (showProgress) {
+                            // since showProgress = true, native code should
+                            // have offered to retry.  Since we ended up here,
+                            // we conclude that download failed & user opted to
+                            // cancel.  Set complete to true to stop bugging
+                            // him in the future (if one bundle fails, the
+                            // rest are virtually certain to).
+                            DownloadManager.complete = true;
+                        }
+                        DownloadManager.fatalError(DownloadManager.ERROR_UNSPECIFIED);
+                    }
+
+                    /**
+                     * Bundle security
+                     *
+                     * Check for corruption/spoofing
+                     */
+
+
+                    /* Create a bundle check from the tmp file */
+                    BundleCheck gottenCheck = BundleCheck.getInstance(tmp);
+
+                    /* Get the check expected for the Bundle */
+                    BundleCheck expectedCheck = BundleCheck.getInstance(name);
+
+                    // Do they match?
+
+                    if (expectedCheck.equals(gottenCheck)) {
+
+                        // Security check OK, uncompress the bundle file
+                        // into the local path
+
+                        long uncompressedLength = tmp.length();
+                        localPath.delete();
+
+                        File uncompressedPath = new File(tmp.getPath() +
+                            ".jar0");
+                        if (! extraUncompress(tmp.getPath(),
+                            uncompressedPath.getPath())) {
+                            // Extra uncompression not available, fall
+                            // back to alternative if it is enabled.
+                            if (DownloadManager.debug) {
+                                DownloadManager.log("Uncompressing with GZIP");
+                            }
+                            GZIPInputStream in = new GZIPInputStream( new
+                                BufferedInputStream(new FileInputStream(tmp),
+                                DownloadManager.BUFFER_SIZE));
+                            BufferedOutputStream out = new BufferedOutputStream(
+                                new FileOutputStream(uncompressedPath),
+                                DownloadManager.BUFFER_SIZE);
+                            DownloadManager.send(in,out);
+                            in.close();
+                            out.close();
+                            if (! uncompressedPath.renameTo(localPath)) {
+                                throw new IOException("unable to rename " +
+                                    uncompressedPath + " to " + localPath);
+                            }
+                        } else {
+                            if (DownloadManager.debug) {
+                                DownloadManager.log("Uncompressing with LZMA");
+                            }
+                            if (! uncompressedPath.renameTo(localPath)) {
+                                throw new IOException("unable to rename " +
+                                    uncompressedPath + " to " + localPath);
+                            }
+                        }
+                        state = DOWNLOADED;
+                        bytesDownloaded += uncompressedLength;
+                        long time = (System.currentTimeMillis() -
+                                start);
+                        DownloadManager.log("Downloaded " + name +
+                                " in " + time + "ms.  Downloaded " +
+                                bytesDownloaded + " bytes this session.");
+
+                        // Normal completion
+                    } else {
+
+                        // Security check not OK: remove the temp file
+                        // and consult the user
+
+                        tmp.delete();
+
+                        DownloadManager.log(
+                                "DownloadManager: Security check failed for " +
+                                "bundle " + name);
+
+                        // only show dialog if we are not in silent mode
+                        if (showProgress) {
+                            retry = DownloadManager.askUserToRetryDownloadOrQuit(
+                                    DownloadManager.ERROR_UNSPECIFIED);
+                        }
+
+                        if (!retry) {
+                            // User wants to give up
+                            throw new RuntimeException(
+                                "Failed bundle security check and user " +
+                                "canceled");
+                        }
+                    }
+                }
+                catch (IOException e) {
+                    // Look for "out of space" using File.getUsableSpace()
+                    // here when downloadFromURL starts throwing IOException
+                    // (or preferably a distinct exception for this case).
+                    DownloadManager.log(e);
+                }
+            } while (retry);
+        } finally {
+            mutex.release();
+        }
+    }
+
+
+    /**
+     * Calls {@link #queueDownload()} on all of this bundle's dependencies.
+     */
+    void queueDependencies(boolean showProgress) {
+        try {
+            String dependencies =
+                    DownloadManager.getBundleProperty(name,
+                    DownloadManager.DEPENDENCIES_PROPERTY);
+            if (dependencies != null) {
+                StringTokenizer st = new StringTokenizer(dependencies,
+                        " ,");
+                while (st.hasMoreTokens()) {
+                    Bundle b = getBundle(st.nextToken());
+                    if (b != null && !b.isInstalled()) {
+                        if (DownloadManager.debug) {
+                            DownloadManager.log("Queueing " + b.name +
+                                    " as a dependency of " + name + "...");
+                        }
+                        b.install(showProgress, true, false);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // shouldn't happen
+            DownloadManager.log(e);
+        }
+    }
+
+
+    static synchronized ExecutorService getThreadPool() {
+        if (threadPool == null) {
+            threadPool = Executors.newFixedThreadPool(THREADS,
+                            new ThreadFactory () {
+                                public Thread newThread(Runnable r) {
+                                    Thread result = new Thread(r);
+                                    result.setDaemon(true);
+                                    return result;
+                                }
+                            }
+                        );
+        }
+        return threadPool;
+    }
+
+
+    private void unpackBundle() throws IOException {
+        File useJarPath = null;
+        if (DownloadManager.isWindowsVista()) {
+            useJarPath = lowJarPath;
+            File jarDir = useJarPath.getParentFile();
+            if (jarDir != null) {
+                jarDir.mkdirs();
+            }
+        } else {
+            useJarPath = jarPath;
+        }
+
+        DownloadManager.log("Unpacking " + this + " to " + useJarPath);
+
+        InputStream rawStream = new FileInputStream(localPath);
+        JarInputStream in = new JarInputStream(rawStream) {
+            public void close() throws IOException {
+                // prevent any sub-processes here from actually closing the
+                // input stream; we'll use rawsStream.close() when we're
+                // done with it
+            }
+        };
+
+        try {
+            File jarTmp = null;
+            JarEntry entry;
+            while ((entry = in.getNextJarEntry()) != null) {
+                String entryName = entry.getName();
+                if (entryName.equals("classes.pack")) {
+                    File packTmp = new File(useJarPath + ".pack");
+                    packTmp.getParentFile().mkdirs();
+                    DownloadManager.log("Writing temporary .pack file " + packTmp);
+                    OutputStream tmpOut = new FileOutputStream(packTmp);
+                    try {
+                        DownloadManager.send(in, tmpOut);
+                    } finally {
+                        tmpOut.close();
+                    }
+                    // we unpack to a temporary file and then, towards the end
+                    // of this method, use a (hopefully atomic) rename to put it
+                    // into its final location; this should avoid the problem of
+                    // partially-completed downloads.  Doing the rename last
+                    // allows us to check for the presence of the JAR file to
+                    // see whether the bundle has in fact been downloaded.
+                    jarTmp = new File(useJarPath + ".tmp");
+                    DownloadManager.log("Writing temporary .jar file " + jarTmp);
+                    unpack(packTmp, jarTmp);
+                    packTmp.delete();
+                } else if (!entryName.startsWith("META-INF")) {
+                    File dest;
+                    if (DownloadManager.isWindowsVista()) {
+                        dest = new File(lowJavaPath,
+                            entryName.replace('/', File.separatorChar));
+                    } else {
+                        dest = new File(DownloadManager.JAVA_HOME,
+                            entryName.replace('/', File.separatorChar));
+                    }
+                    if (entryName.equals(BUNDLE_JAR_ENTRY_NAME))
+                        dest = useJarPath;
+                    File destTmp = new File(dest + ".tmp");
+                    boolean exists = dest.exists();
+                    if (!exists) {
+                        DownloadManager.log(dest + ".mkdirs()");
+                        dest.getParentFile().mkdirs();
+                    }
+                    try {
+                        DownloadManager.log("Using temporary file " + destTmp);
+                        FileOutputStream out =
+                                new FileOutputStream(destTmp);
+                        try {
+                            byte[] buffer = new byte[2048];
+                            int c;
+                            while ((c = in.read(buffer)) > 0)
+                                out.write(buffer, 0, c);
+                        } finally {
+                            out.close();
+                        }
+                        if (exists)
+                            dest.delete();
+                        DownloadManager.log("Renaming from " + destTmp + " to " + dest);
+                        if (!destTmp.renameTo(dest)) {
+                            throw new IOException("unable to rename " +
+                                    destTmp + " to " + dest);
+                        }
+
+                    } catch (IOException e) {
+                        if (!exists)
+                            throw e;
+                        // otherwise the file already existed and the fact
+                        // that we failed to re-write it probably just
+                        // means that it was in use
+                    }
+                }
+            }
+
+            // rename the temporary jar into its final location
+            if (jarTmp != null) {
+                if (useJarPath.exists())
+                    jarTmp.delete();
+                else if (!jarTmp.renameTo(useJarPath)) {
+                    throw new IOException("unable to rename " + jarTmp +
+                            " to " + useJarPath);
+                }
+            }
+            if (DownloadManager.isWindowsVista()) {
+                // move bundle to real location
+                DownloadManager.log("Using broker to move " + name);
+                if (!DownloadManager.moveDirWithBroker(
+                        DownloadManager.getKernelJREDir() + name)) {
+                    throw new IOException("unable to create " + name);
+                }
+                DownloadManager.log("Broker finished " + name);
+            }
+            DownloadManager.log("Finished unpacking " + this);
+        } finally {
+            rawStream.close();
+        }
+        if (deleteOnInstall) {
+            localPath.delete();
+        }
+
+    }
+
+
+    public static void unpack(File pack, File jar) throws IOException {
+        Process p = Runtime.getRuntime().exec(DownloadManager.JAVA_HOME + File.separator +
+                "bin" + File.separator + "unpack200 -Hoff \"" + pack + "\" \"" + jar + "\"");
+        try {
+            p.waitFor();
+        }
+        catch (InterruptedException e) {
+        }
+    }
+
+
+    /**
+     * Unpacks and installs the bundle.  The bundle's classes are not
+     * immediately added to the boot class path; this happens when the VM
+     * attempts to load a class and calls getBootClassPathEntryForClass().
+     */
+    public void install() throws IOException {
+        install(true, false, true);
+    }
+
+
+    /**
+     * Unpacks and installs the bundle, optionally hiding the progress
+     * indicator.  The bundle's classes are not immediately added to the
+     * boot class path; this happens when the VM attempts to load a class
+     * and calls getBootClassPathEntryForClass().
+     *
+     *@param showProgress true to display a progress dialog
+     *@param downloadOnly true to download but not install
+     *@param block true to wait until the operation is complete before returning
+     */
+    public synchronized void install(final boolean showProgress,
+            final boolean downloadOnly, boolean block) throws IOException {
+        if (DownloadManager.isJREComplete())
+            return;
+        if (state == NOT_DOWNLOADED || state == QUEUED) {
+            // we allow an already-queued bundle to be placed into the queue
+            // again, to handle the case where the bundle is queued with
+            // downloadOnly true and then we try to queue it again with
+            // downloadOnly false -- the second queue entry will actually
+            // install it.
+            if (state != QUEUED) {
+                DownloadManager.addToTotalDownloadSize(getSize());
+                state = QUEUED;
+            }
+            if (getThreadPool().isShutdown()) {
+                if (state == NOT_DOWNLOADED || state == QUEUED)
+                    doInstall(showProgress, downloadOnly);
+            }
+            else {
+                Future task = getThreadPool().submit(new Runnable() {
+                    public void run() {
+                        try {
+                            if (state == NOT_DOWNLOADED || state == QUEUED ||
+                                    (!downloadOnly && state == DOWNLOADED)) {
+                                doInstall(showProgress, downloadOnly);
+                            }
+                        }
+                        catch (IOException e) {
+                            // ignore
+                        }
+                    }
+                });
+                queueDependencies(showProgress);
+                if (block) {
+                    try {
+                        task.get();
+                    }
+                    catch (Exception e) {
+                        throw new Error(e);
+                    }
+                }
+            }
+        }
+        else if (state == DOWNLOADED && !downloadOnly)
+            doInstall(showProgress, false);
+    }
+
+
+    private void doInstall(boolean showProgress, boolean downloadOnly)
+            throws IOException {
+        Mutex mutex = Mutex.create(DownloadManager.MUTEX_PREFIX + name +
+                ".install");
+        DownloadManager.bundleInstallStart();
+        try {
+            mutex.acquire();
+            updateState();
+            if (state == NOT_DOWNLOADED || state == QUEUED) {
+                download(showProgress);
+            }
+
+            if (state == DOWNLOADED && downloadOnly) {
+                return;
+            }
+
+            if (state == INSTALLED) {
+                return;
+            }
+            if (state != DOWNLOADED) {
+                DownloadManager.fatalError(DownloadManager.ERROR_UNSPECIFIED);
+            }
+
+            DownloadManager.log("Calling unpackBundle for " + this);
+            unpackBundle();
+            DownloadManager.log("Writing receipt for " + this);
+            writeReceipt();
+            updateState();
+            DownloadManager.log("Finished installing " + this + ", state=" + state);
+        } finally {
+            if (lowJavaPath != null) {
+                lowJavaPath.delete();
+            }
+            mutex.release();
+            DownloadManager.bundleInstallComplete();
+        }
+    }
+
+
+    synchronized void setState(int state) {
+        this.state = state;
+    }
+
+
+    /** Returns <code>true</code> if this bundle has been installed. */
+    public boolean isInstalled() {
+        synchronized (Bundle.class) {
+            updateState();
+            return state == INSTALLED;
+        }
+    }
+
+
+    /**
+     * Adds an entry to the receipts file indicating that this bundle has
+     * been successfully downloaded.
+     */
+    private void writeReceipt() {
+        getReceiptsMutex().acquire();
+        File useReceiptPath = null;
+        try {
+
+            try {
+
+                receipts.add(name);
+
+                if (DownloadManager.isWindowsVista()) {
+                    // write out receipts to locallow
+                    useReceiptPath = new File(
+                            DownloadManager.getLocalLowTempBundlePath(),
+                            "receipts");
+
+                    if (receiptPath.exists()) {
+                        // copy original file to locallow location
+                        DownloadManager.copyReceiptFile(receiptPath,
+                                useReceiptPath);
+                    }
+
+                    // update receipt in locallow path
+                    // only append if original receipt path exists
+                    FileOutputStream out = new FileOutputStream(useReceiptPath,
+                            receiptPath.exists());
+                    out.write((name + System.getProperty("line.separator")).getBytes("utf-8"));
+                    out.close();
+
+                    // use broker to move back to real path
+                    if (!DownloadManager.moveFileWithBroker(
+                            DownloadManager.getKernelJREDir()
+                        + "-bundles" + File.separator + "receipts")) {
+                        throw new IOException("failed to write receipts");
+                    }
+                } else {
+                    useReceiptPath = receiptPath;
+                    FileOutputStream out = new FileOutputStream(useReceiptPath,
+                            true);
+                    out.write((name + System.getProperty("line.separator")).getBytes("utf-8"));
+                    out.close();
+                }
+
+
+            } catch (IOException e) {
+                DownloadManager.log(e);
+                // safe to continue, as the worst that happens is we
+                // re-download existing bundles
+            }
+        }
+        finally {
+            getReceiptsMutex().release();
+        }
+    }
+
+
+    public String toString() {
+        return "Bundle[" + name + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/BundleCheck.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ * The Java Kernel Bundle security check.
+ *
+ * This class is responsible for detail of creating, storing, dispensing, and
+ * updating bundle security checks and security checks for all the files
+ * extracted from a bundle. Security checks are cryptographic
+ * hashcodes that make it impractical to counterfeit a file. The security
+ * check algorithm is defined by peer class StandaloneMessageDigest. The
+ * cryptographic
+ * hashcodes are held in instances of this class as byte arrays and externally
+ * as hexidecimal string values for Bundle name Property keys. The properties
+ * are a resource in the Java Kernel core JRE rt.jar and accessed after a
+ * real or simulated bundle download by peer classes DownloadManager and
+ * Bundle. Build-time deployment class SplitJRE uses this class to create file
+ * security checks directly and via a special execution of DownloadManager.
+ * The main method of this class can be used to create a
+ * new set of security codes and updated properties for a given JRE path
+ * and set of bundle names (CWD assume to contain bundle files as <name>.zip).
+ *
+ * This is a Sun internal class defined by the Sun implementation and
+ * intended for JRE/JDK release deployment.
+ *
+ * @see sun.jkernel.DownloadManager
+ * @see sun.jkernel.Bundle
+ * @see sun.jkernel.StandaloneSHA
+ * @see sun.jkernel.ByteArrayToFromHexDigits
+ * See also deploy/src/kernel/share/classes/sun/kernel/SplitJRE.java
+ */
+
+package sun.jkernel;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+
+public class BundleCheck {
+
+    /* File buffer size */
+
+    private static final int DIGEST_STREAM_BUFFER_SIZE = 2048;
+
+    /* The bundle filename suffix */
+
+    private static final String BUNDLE_SUFFIX = ".zip";
+
+    /* Mutable static state. */
+
+    /* Properties (Bundle name/check hex String pairs) for a set of Bundles.
+       Guarded by this class' object. */
+
+    private static volatile Properties properties;
+
+    /* Mutable instance state. */
+
+    /**
+     * The bytes of the check value. Guarded by the bundle Mutex (in
+     * sun.jkernel.DownloadManager) or the fact that sun.kernel.SplitJRE
+     * and/or DownloadManager with "-download all" runs a single thread.
+     */
+
+    private byte[] checkBytes;
+
+    /* Prevent instantiation by default constructor */
+
+    private BundleCheck(){}
+
+    /**
+     * Store the bundle check values as properties to the path specified.
+     * Only invoked by SplitJRE.
+     */
+
+    public static void storeProperties(String fullPath)  {
+
+        try {
+            File f = new File(fullPath);
+            f.getParentFile().mkdirs();
+            OutputStream out = new FileOutputStream(f);
+            properties.store(out, null);
+            out.close();
+        } catch (Exception e) {
+            throw new RuntimeException(
+                "BundleCheck: storing properties threw: " + e);
+        }
+    }
+
+    /**
+     * Fetch the check value properties as a DownloadManager resource.
+     */
+
+    private static void loadProperties()  {
+        properties = new Properties();
+        try {
+            InputStream in = new BufferedInputStream(
+                DownloadManager.class.getResourceAsStream(
+                DownloadManager.CHECK_VALUES_FILE));
+            if (in == null)
+                throw new RuntimeException("BundleCheck: unable to locate " +
+                    DownloadManager.CHECK_VALUES_FILE + " as resource");
+            properties.load(in);
+            in.close();
+        } catch (Exception e) {
+            throw new RuntimeException("BundleCheck: loadProperties threw " +
+                e);
+        }
+    }
+
+    /* Get the check value Properties object */
+
+    private synchronized static Properties getProperties() {
+        if (properties == null) {
+            // If this fails it means addProperty has been used inappropriately
+            loadProperties();
+        }
+        return properties;
+    }
+
+    /* Reset the properties with an empty Properties object */
+
+    public static void resetProperties() {
+        properties = null;
+    }
+
+    /* The BundleCheck expressed as a String */
+
+    public String toString() {
+        return ByteArrayToFromHexDigits.bytesToHexString(checkBytes);
+    }
+
+    /* Add the given BundleCheck as a property to bundleCheckvalueProperties */
+
+    private void addProperty(String name) {
+        // When first called by SplitJRE just start with empty object
+        // rather than allowing a load to happen, as it does at install time.
+        if (properties == null) {
+           properties = new Properties();
+        }
+        getProperties().put(name, toString());
+    }
+
+    /* private ctor for creating/initializing a BundleCheck */
+
+    private BundleCheck(byte[] checkBytes) {
+        this.checkBytes = checkBytes;
+    }
+
+    /* private ctor for creating a BundleCheck with a given name and known
+       Property value. */
+
+    private BundleCheck(String name) {
+        String hexString = getProperties().getProperty(name);
+        if  (hexString == null) {
+            throw new RuntimeException(
+                "BundleCheck: no check property for bundle: " + name);
+        }
+        this.checkBytes = ByteArrayToFromHexDigits.hexStringToBytes(hexString);
+    }
+
+    /* Make a BundleCheck from the contents of the given file or a Bundle
+       name. Save the new object's value as a property if saveProperty is
+       true. Behavior is only defined for name or file being null, but not
+       both, and for saveProperty to be true only when both name and file
+       are not null.
+       Any IO or other exception implies an unexpected and fatal internal
+       error and results in a RuntimeException.  */
+
+    private static BundleCheck getInstance(String name,
+        File file, boolean saveProperty) {
+        if (file == null ) {
+            return new BundleCheck(name);
+
+        } else {
+            StandaloneMessageDigest checkDigest = null;
+            try {
+                FileInputStream checkFileStream = new FileInputStream(file);
+                checkDigest = StandaloneMessageDigest.getInstance("SHA-1");
+
+                // Compute a check code across all of the file bytes.
+                // NOTE that every time a bundle is created, even from
+                // the "same bits", it may be different wrt to the security
+                // code because of slight variations build to build. For
+                // example, the JVM build normally contains an
+                // auto-incrementing build number, built archives might have
+                // timestamps, etc.
+
+                int readCount;
+                byte[] messageStreamBuff =
+                    new byte[DIGEST_STREAM_BUFFER_SIZE];
+                do {
+                    readCount = checkFileStream.read(messageStreamBuff);
+                    if (readCount > 0) {
+                        checkDigest.update(messageStreamBuff,0,readCount);
+                    }
+                } while (readCount != -1);
+                checkFileStream.close();
+
+            } catch (Exception e) {
+                throw new RuntimeException(
+                    "BundleCheck.addProperty() caught: " + e);
+            }
+            BundleCheck bc = new BundleCheck(checkDigest.digest());
+            if (saveProperty) {
+                bc.addProperty(name);
+            }
+            return bc;
+        }
+    }
+
+    /* Create a BundleCheck from the given file */
+
+    public static BundleCheck getInstance(File file) {
+        return getInstance(null, file, false);
+    }
+
+    /* Create a BundleCheck from the given bundle name */
+
+    static BundleCheck getInstance(String name) {
+        return getInstance(name, null, false);
+    }
+
+    /* Create a BundleCheck from the given bundle name and file and
+       use it to make and save a security check Property value. */
+
+    public static void addProperty(String name,  File file) {
+        getInstance(name, file, true);
+    }
+
+    /* Create a bundlecheck from the given bundle name and file and
+       add a Property value for it. */
+
+    static void add(String name, File file) {
+        getInstance(name, file, true).addProperty(name);
+    }
+
+    /* Compare two BundkCheck instances for equal check values */
+
+    boolean equals(BundleCheck b) {
+        if ((checkBytes == null) || (b.checkBytes == null)) {
+            return false;
+        }
+        if (checkBytes.length != b.checkBytes.length) {
+            return false;
+        }
+        for (int i = 0; i < checkBytes.length; i++) {
+            if (checkBytes[i] != b.checkBytes[i]) {
+                if (DownloadManager.debug) {
+                    System.out.println(
+                        "BundleCheck.equals mismatch between this: " +
+                        toString() + " and param: " + b.toString());
+                }
+                return false;
+            }
+         }
+         return true;
+    }
+
+    /* After SplitJRE is used to restructure the JRE into a "core JRE" and
+       a set of Java Kernel "bundles", if extra compression is available
+       the bundles are extracted and rearchived with zero compression by
+       deploy build make steps. The newly compressed bundle names are then
+       passed to this main with the path of the kernel core JRE to have new
+       bundle security check values computed and the corresponding properties
+       updated in rt.jar. If extra compression isn't available then this main is
+       never used and the default jar/zip bundle compression and security
+       codes created by SplitJRE are left in place and ready to use. */
+
+    public static void main(String[] args) {
+        if (args.length < 2) {
+            System.err.println("Usage: java BundleCheck <jre path> " +
+                "<bundle 1 name> ... <bundle N name>");
+            return;
+        }
+
+        // Make a security check code for each bundle file
+        for (int arg = 1; arg < args.length; arg++) {
+            BundleCheck.addProperty(args[arg],
+                new File(args[arg] + BUNDLE_SUFFIX));
+        }
+
+        // Store the new check code properties below the current directory
+        BundleCheck.storeProperties(DownloadManager.CHECK_VALUES_DIR);
+
+        // Now swap the new properties file into the core rt.jar
+        try {
+            int status = Runtime.getRuntime().exec(
+                "jar uf " + args[0] + "\\lib\\rt.jar " +
+                DownloadManager.CHECK_VALUES_DIR).waitFor();
+            if (status != 0) {
+                System.err.println(
+                    "BundleCheck: exec of jar uf gave nonzero status");
+                return;
+            }
+        } catch (Exception e) {
+            System.err.println("BundleCheck: exec of jar uf threw: " + e);
+            return;
+        }
+    } // main
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/ByteArrayToFromHexDigits.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.jkernel;
+
+/**
+ * TODO: The JRE and deploy build code (SplitJRE) can be made a bit smarter
+ * then cryto hashcode byte arrays can be used directly, eliminating the need
+ * for this class altogether. So just leave this alone until it can be removed.
+ * TODO: Change "Digits" to "String" for uniformity and more intuitive names.
+ * A lightweight class to provide convert between hex digits and
+ * <code>byte[]</code>.
+ *<p>
+ * TODO: Try to get this built without the -source 1.3 -target -1.3 options,
+ * which prevent use of java.text.Format, assuming this wouldn't bloat the
+ * JK rt.jar. Also, there still might be equivalent code hiding in the JDK
+ * already, but preliminary searches havn't found it.
+ */
+
+public final class ByteArrayToFromHexDigits {
+
+    private static final char [] chars = new char[]
+        {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'};
+
+    private static final boolean debug = false;
+
+    /**
+     * Converts the <code>byte[] b</code> into a <code>String</code> of
+     * hex digits representing the integer values of all the bytes.
+     *
+     * @param b byte array to be converted
+     * @return String representing <code>b</code> in hexadecimal
+     * @throws IllegalArgumentException if <code>b</code> is null or zero length
+     */
+    public static String bytesToHexString(byte[] b) {
+        if (debug ) {
+            System.out.print("I: ");
+            for(int i=0;i<b.length;i++) {
+                System.out.format("%02X",b[i]);
+            }
+            System.out.println();
+        }
+        if ((b == null) || (b.length == 0)) {
+            throw new IllegalArgumentException("argument null or zero length");
+        }
+        StringBuffer buff = new StringBuffer(b.length * 2);
+        for (int i = 0; i < b.length; i++ ) {
+            buff.insert(i*2,chars[(b[i] >> 4) & 0xf]);
+            buff.insert(i*2+1,chars[b[i] & 0xf]);
+        }
+        if (debug ) {
+            System.out.println("O: " + buff.toString());
+        }
+        return buff.toString();
+    }
+
+    // Convert one hex character to a 4 bit byte value
+
+    private static byte hexCharToByte(char c) throws IllegalArgumentException {
+        if ((c < '0') ||
+            ( ((c < 'A') && (c > 'F')) && ((c < 'a') && (c > 'f'))) ) {
+
+            throw new IllegalArgumentException("not a hex digit");
+        }
+
+        if (c > '9') {
+            if (c > 'F') {
+                return (byte) ((c - 'a' + 10) & 0xf);
+            } else {
+                return (byte) ((c - 'A' + 10) & 0xf);
+            }
+        } else {
+            return (byte) ((c - '0') & 0xf);
+        }
+
+    }
+
+    /**
+     * Converts the <code>String d</code> assumed to contain a sequence
+     * of hexadecimal digit characters into a <code>byte[]</code>.
+     *
+     * @param d String to be converted
+     * @return  byte array representing the hex string
+     * @throws IllegalArgumentException if <code>d</code> is odd length,
+     *     contains a character outside the ranges of 0-9, a-f, and A-F,
+     *     or is zero length or null
+     */
+
+    public static byte[] hexStringToBytes(String d) throws IllegalArgumentException {
+        if (d == null) {
+            throw new IllegalArgumentException(
+                "parameter cannot be null");
+        }
+
+        if (d.length() == 0) {
+            throw new IllegalArgumentException(
+                "parameter cannot be zero length");
+        }
+
+        if ((d.length() & 1) != 0) {
+            throw new IllegalArgumentException(
+                "odd length string");
+        }
+
+        byte[] b = new byte[d.length() / 2];
+
+        // TODO Might be code in the JK initial bundle to do this better (i.e.
+        // method that tests for a hex char?)
+
+        for (int i=0;i<d.length();i+=2) {
+            b[i/2] =  (byte) (( (byte) (hexCharToByte(d.charAt(i))) << 4) +
+                (byte) hexCharToByte(d.charAt(i+1)));
+        }
+        return b;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/DigestOutputStream.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import sun.jkernel.StandaloneMessageDigest;
+
+
+/*
+ * This class provides the main functionality of <code>FilterOutputStream</code>,
+ * and accumulates a check value as bytes are written to
+ * it. The check value is available by method <code>getCheckValue</code>.
+ *<p>
+ * Operations on the public <code>out</code> field of this class should be
+ * avoided to prevent an invalid check code being generated.
+ *
+ * TODO: The javadoc HTML hasn't been generated and eyeballed for yet.
+ * TODO: There is a javadoc trick to cause the parent class javadoc to be
+ *       automagically used: try to take advantage of this.
+ * TODO: Add javadoc links instead of <code>API</code> where it would be useful.
+ * TODO: Go visit the Docs style guide again and get the periods right and
+ *       consistent for all sun.* classes.
+ * @author Pete Soper
+ * @see java.lang.FilterOutputStream
+ * @see getCheckValue
+ */
+
+public class DigestOutputStream extends FilterOutputStream {
+    private static final String DEFAULT_ALGORITHM = "SHA-1";
+
+    private final boolean debug = false;
+
+    private StandaloneMessageDigest smd = null;
+
+    private void initDigest(String algorithm) throws NoSuchAlgorithmException {
+        smd = StandaloneMessageDigest.getInstance(algorithm);
+    }
+
+    // The underlying stream.
+
+    protected volatile OutputStream out;
+
+    /**
+     * Creates a <code>DigestOutputStream</code> with stream <code>s</code>
+     * to be checked with using <code>algorithm</code>.
+     * <p>
+     * If <code>algorithm</code> is not supported then
+     * <code>NoSuchAlgorithm</code> is thrown.
+     * <p>
+     * See {linkplain sun.security.provider.StandaloneMessageDigest} for an
+     * implementation-specific list of supported algorithms.
+     *
+     * @throws NoSuchAlgorithm if <code>algorithm</code> is not supported
+     * @see sun.security.provider.StandaloneMessageDigest
+     */
+
+    /**
+     * Creates an output stream filter built on top of
+     * underlying output stream <code>out</code> for checking with
+     * algorithm <code>algorithm</code>.
+     * <p>
+     * If <code>algorithm</code> is not supported then
+     * <code>NoSuchAlgorithm</code> is thrown.
+     * <p>
+     * See {linkplain sun.security.provider.StandaloneMessageDigest} for an
+     * implementation-specific list of supported algorithms.
+     *
+     * @param out the underlying output stream to be assigned to
+     *     the field <tt>this.out</tt> for later use, or
+     *     <code>null</code> if this instance is to be
+     *     created without an underlying stream.
+     * @param algorithm the check algorithm to use.
+     * @throws NoSuchAlgorithm if <code>algorithm</code> is not supported
+     * @see sun.security.provider.StandaloneMessageDigest
+     * @see DigestInputStream(InputStream, String)
+     */
+
+    public DigestOutputStream(OutputStream out, String algorithm) throws NoSuchAlgorithmException {
+        super(out);
+        initDigest(algorithm);
+        this.out = out;
+    }
+
+    /**
+     * Creates an output stream filter built on top of
+     * underlying output stream <code>out</code> for the default checking
+     * algorithm.
+     * <p>
+     * This implemention provides "SHA-1" as the default checking algorithm.
+     *
+     * @param out the underlying output stream to be assigned to
+     *     the field <tt>this.out</tt> for later use, or
+     *     <code>null</code> if this instance is to be
+     *     created without an underlying stream.
+     * @see DigestInputStream(InputStream)
+     */
+
+    public DigestOutputStream(OutputStream out) {
+        super(out);
+        try {
+            initDigest(DEFAULT_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            // Impossible to get here, but stranger things have happened...
+            throw new RuntimeException("DigestOutputStream() unknown algorithm");
+        }
+        // superstition from a test failure this.out = out;
+    }
+
+    /**
+     * Writes a byte specified by <code>v</code> to this stream
+     * and updates the check information.
+     *
+     *
+     * @param v the byte to be written.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write(int v) throws IOException {
+        super.write(v);
+        // TODO Could create this array once
+        byte[] b = new byte[] {(byte) (v & 0xff)};
+        smd.update(b,0,1);
+    }
+
+    /**
+     * Writes the bytes in array <code>data</code>
+     * to this stream and updates the check information.
+     *
+     * @param data the data.
+     * @throws IOException  if an I/O error occurs.
+     * @throws NullPointerException  if <code>data</code> is <code>null</code>
+     */
+    public void write(byte[] data) throws IOException {
+        write(data,0,data.length);
+    }
+
+    /**
+     * Writes a sub array as a sequence of bytes to this output stream and
+     * updates the check information.
+     * @param data the data to be written
+     * @param ofs the start offset in the data
+     * @param len the number of bytes that are written
+     * @throws IOException If an I/O error has occurred.
+     * @throws NullPointerException  if <code>data</code> is <code>null</code>
+     * @throws IndexOutOfBoundsException If <code>ofs</code> is negative,
+     *     <code>len</code> is negative, or <code>len</code> is greater than
+     *     <code>b.length - ofs</code>
+     */
+    public void write(byte[] data, int ofs, int len) throws IOException {
+        if (debug) {
+            System.out.print("DigestOutputStream.write: ");
+            for (int i=ofs; i<(len - ofs); i++) {
+                System.out.format("%02X",data[i]);
+            }
+            System.out.println();
+        }
+        if (data == null) {
+            throw new NullPointerException("null array in DigestOutputStream.write");
+        } else if (ofs < 0 || len < 0 || len > data.length - ofs) {
+            throw new IndexOutOfBoundsException();
+        }
+        //super.write(data,ofs,len);
+        // WATCH OUT: FilterOutputStream does a byte at a time write(byte)
+        // TODO: Will this work all the time, or is there another caveat
+        // to publish
+        out.write(data,ofs,len);
+        if (debug) {
+            System.out.println("DigestOutputStream.write before");
+        }
+        smd.update(data,ofs,len);
+        if (debug) {
+            System.out.println("DigestOutputStream.write after");
+        }
+    }
+
+    /**
+     * Closes this file output stream and releases any system resources
+     * associated with this stream and makes the check value for the stream
+     * available via <code>getCheckValue</code>. This file output stream may
+     * no longer be used for writing bytes.
+     *
+     * @throws  IOException  if an I/O error occurs.
+     * @see getCheckValue
+     */
+    public void close() throws IOException {
+        super.close();
+    }
+
+    /**
+     * Return the check value computed for the stream and reset the state of
+     * check value generation.
+     *
+     * @return the check value bytes
+     */
+    public byte[] getCheckValue() {
+        byte[] b = smd.digest();
+        if (debug) {
+            System.out.print("DigestOutputStream.getCheckValue: ");
+            for (int i=0; i<b.length; i++) {
+                System.out.format("%02X",b[i]);
+            }
+            System.out.println();
+        }
+        smd.reset();
+        return b;
+    }
+
+    /**
+     * Flushes this output stream.
+     *
+     * @throws IOException if an I/O error occurs.
+     * @see java.io.FilterOutputStream#flush()
+     */
+    public void flush() throws IOException {
+        super.flush();
+    }
+
+    /**
+     * Compares two digests for equality. Does a simple byte compare.
+     *
+     * @param digesta one of the digests to compare.
+     *
+     * @param digestb the other digest to compare.
+     *
+     * @return true if the digests are equal, false otherwise.
+     */
+//    public static boolean isEqual(byte digesta[], byte digestb[]) {
+//        return StandaloneMessageDigest.isEqual(digesta, digestb);
+//    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/DownloadManager.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,1676 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.jar.*;
+import java.util.zip.*;
+import sun.misc.Launcher;
+
+/**
+ * Handles the downloading of additional JRE components.  The bootstrap class
+ * loader automatically invokes DownloadManager when it comes across a resource
+ * that can't be located.
+ *
+ *@author Ethan Nicholas
+ */
+public class DownloadManager {
+    public static final String KERNEL_DOWNLOAD_URL_PROPERTY =
+            "kernel.download.url";
+    public static final String KERNEL_DOWNLOAD_ENABLED_PROPERTY =
+            "kernel.download.enabled";
+
+    public static final String KERNEL_DOWNLOAD_DIALOG_PROPERTY =
+            "kernel.download.dialog";
+
+    public static final String KERNEL_DEBUG_PROPERTY = "kernel.debug";
+    // disables JRE completion when set to true, used as part of the build
+    // process
+    public static final String KERNEL_NOMERGE_PROPERTY = "kernel.nomerge";
+
+    public static final String KERNEL_SIMULTANEOUS_DOWNLOADS_PROPERTY =
+            "kernel.simultaneous.downloads";
+
+    // used to bypass some problems with JAR entry modtimes not matching.
+    // originally was set to zero, but apparently the epochs are different
+    // for zip and pack so the pack/unpack cycle was causing the modtimes
+    // to change.  With some recent changes to the reconstruction, I'm
+    // not sure if this is actually necessary anymore.
+    public static final int KERNEL_STATIC_MODTIME = 10000000;
+
+    // indicates that bundles should be grabbed using getResource(), rather
+    // than downloaded from a network path -- this is used during the build
+    // process
+    public static final String RESOURCE_URL = "internal-resource/";
+    public static final String REQUESTED_BUNDLES_PATH = "lib" + File.separator +
+            "bundles" + File.separator + "requested.list";
+
+    private static final boolean disableDownloadDialog = "false".equals(
+            System.getProperty(KERNEL_DOWNLOAD_DIALOG_PROPERTY));
+
+    static boolean debug = "true".equals(
+            System.getProperty(KERNEL_DEBUG_PROPERTY));
+    // points to stderr in case we need to println before System.err is
+    // initialized
+    private static OutputStream errorStream;
+    private static OutputStream logStream;
+
+    static String MUTEX_PREFIX;
+
+    static boolean complete;
+
+    // 1 if jbroker started; 0 otherwise
+    private static int _isJBrokerStarted = -1;
+
+    // maps bundle names to URL strings
+    private static Properties bundleURLs;
+
+    public static final String JAVA_HOME = System.getProperty("java.home");
+    public static final String USER_HOME = System.getProperty("user.home");
+    public static final String JAVA_VERSION =
+            System.getProperty("java.version");
+    static final int BUFFER_SIZE = 2048;
+
+    static volatile boolean jkernelLibLoaded = false;
+
+    public static String DEFAULT_DOWNLOAD_URL =
+        "http://javadl.sun.com/webapps/download/GetList/"
+        +  System.getProperty("java.runtime.version") + "-kernel/windows-i586/";
+
+    private static final String CUSTOM_PREFIX = "custom";
+    private static final String KERNEL_PATH_SUFFIX = "-kernel";
+
+    public static final String JAR_PATH_PROPERTY = "jarpath";
+    public static final String SIZE_PROPERTY = "size";
+    public static final String DEPENDENCIES_PROPERTY = "dependencies";
+    public static final String INSTALL_PROPERTY = "install";
+
+    private static boolean reportErrors = true;
+
+    static final int ERROR_UNSPECIFIED = 0;
+    static final int ERROR_DISK_FULL   = 1;
+    static final int ERROR_MALFORMED_BUNDLE_PROPERTIES = 2;
+    static final int ERROR_DOWNLOADING_BUNDLE_PROPERTIES = 3;
+    static final int ERROR_MALFORMED_URL = 4;
+    static final int ERROR_RETRY_CANCELLED = 5;
+    static final int ERROR_NO_SUCH_BUNDLE = 6;
+
+
+    // tracks whether the current thread is downloading.  A count of zero means
+    // not currently downloading, >0 means the current thread is downloading or
+    // installing a bundle.
+    static ThreadLocal<Integer> downloading = new ThreadLocal<Integer>() {
+        protected Integer initialValue() {
+            return 0;
+        }
+    };
+
+    private static File[] additionalBootStrapPaths = { };
+
+    private static String[] bundleNames;
+    private static String[] criticalBundleNames;
+
+    private static String downloadURL;
+
+    private static boolean visitorIdDetermined;
+    private static String visitorId;
+
+    /**
+     * File and path where the Check value properties are gotten from
+     */
+    public static String CHECK_VALUES_FILE = "check_value.properties";
+    static String CHECK_VALUES_DIR = "sun/jkernel/";
+    static String CHECK_VALUES_PATH = CHECK_VALUES_DIR + CHECK_VALUES_FILE;
+
+    /**
+     * The contents of the bundle.properties file, which contains various
+     * information about individual bundles.
+     */
+    private static Map<String, Map<String, String>> bundleProperties;
+
+
+    /**
+     * The contents of the resource_map file, which maps resources
+     * to their respective bundles.
+     */
+    private static Map<String, String> resourceMap;
+
+
+    /**
+     * The contents of the file_map file, which maps files
+     * to their respective bundles.
+     */
+    private static Map<String, String> fileMap;
+
+    private static boolean extDirDetermined;
+    private static boolean extDirIncluded;
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                if (debug)
+                    println("DownloadManager startup");
+
+                 // this mutex is global and will apply to all different
+                // version of java kernel installed on the local machine
+                MUTEX_PREFIX = "jkernel";
+                boolean downloadEnabled = !"false".equals(
+                        System.getProperty(KERNEL_DOWNLOAD_ENABLED_PROPERTY));
+                complete = !getBundlePath().exists() ||
+                        !downloadEnabled;
+
+                // only load jkernel.dll if we are not "complete".
+                // DownloadManager will be loaded during build time, before
+                // jkernel.dll is built.  We only need to load jkernel.dll
+                // when DownloadManager needs to download something, which is
+                // not necessary during build time
+                if (!complete) {
+                    loadJKernelLibrary();
+                    log("Log opened");
+
+                    if (isWindowsVista()) {
+                        getLocalLowTempBundlePath().mkdirs();
+                    }
+
+                    new Thread() {
+                        public void run() {
+                            startBackgroundDownloads();
+                        }
+                    }.start();
+
+                    try {
+                        String dummyPath;
+                        if (isWindowsVista()) {
+                            dummyPath = USER_HOME +
+                                    "\\appdata\\locallow\\dummy.kernel";
+                        } else {
+                            dummyPath = USER_HOME + "\\dummy.kernel";
+                        }
+
+                        File f = new File(dummyPath);
+                        FileOutputStream out = new FileOutputStream(f, true);
+                        out.close();
+                        f.deleteOnExit();
+
+                    } catch (IOException e) {
+                        log(e);
+                    }
+                    // end of warm up code
+
+                    new Thread("BundleDownloader") {
+                        public void run() {
+                            downloadRequestedBundles();
+                        }
+                    }.start();
+                }
+                return null;
+            }
+        });
+    }
+
+
+    static synchronized void loadJKernelLibrary() {
+        if (!jkernelLibLoaded) {
+            try {
+                System.loadLibrary("jkernel");
+                jkernelLibLoaded = true;
+                debug = getDebugProperty();
+            } catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+    }
+
+    static String appendTransactionId(String url) {
+        StringBuilder result = new StringBuilder(url);
+        String visitorId = DownloadManager.getVisitorId();
+        if (visitorId != null) {
+            if (url.indexOf("?") == -1)
+                result.append('?');
+            else
+                result.append('&');
+            result.append("transactionId=");
+            result.append(DownloadManager.getVisitorId());
+        }
+        return result.toString();
+    }
+
+
+    /**
+     * Returns the URL for the directory from which bundles should be
+     * downloaded.
+     */
+    static synchronized String getBaseDownloadURL() {
+        if (downloadURL == null) {
+            log("Determining download URL...");
+            loadJKernelLibrary();
+
+            /*
+             * First check if system property has been set - system
+             * property should take over registry key setting.
+             */
+            downloadURL = System.getProperty(
+                          DownloadManager.KERNEL_DOWNLOAD_URL_PROPERTY);
+            log("System property kernel.download.url = " + downloadURL);
+
+            /*
+             * Now check if registry key has been set
+             */
+            if (downloadURL == null){
+                downloadURL = getUrlFromRegistry();
+                log("getUrlFromRegistry = " + downloadURL);
+            }
+
+            /*
+             * Use default download url
+             */
+            if (downloadURL == null)
+                downloadURL = DEFAULT_DOWNLOAD_URL;
+            log("Final download URL: " + downloadURL);
+        }
+        return downloadURL;
+    }
+
+
+    /**
+     * Loads a file representing a node tree.  The format is described in
+     * SplitJRE.writeTreeMap().  The node paths (such as
+     * core/java/lang/Object.class) are interpreted with the root node as the
+     * value and the remaining nodes as
+     * the key, so the mapping for this entry would be java/lang/Object.class =
+     * core.
+     */
+    static Map<String, String> readTreeMap(InputStream rawIn)
+            throws IOException {
+        // "token level" refers to the 0-31 byte that occurs prior to every
+        // token in the stream, and would be e.g. <0> core <1> java <2> lang
+        // <3> Object.class <3> String.class, which gives us two mappings:
+        // java/lang/Object.class = core, and java/lang/String.class = core.
+        // See the format description in SplitJRE.writeTreeMap for more details.
+        Map<String, String> result = new HashMap<String, String>();
+        InputStream in = new BufferedInputStream(rawIn);
+        // holds the current token sequence,
+        // e.g. {"core", "java", "lang", "Object.class"}
+        List<String> tokens = new ArrayList<String>();
+        StringBuilder currentToken = new StringBuilder();
+        for (;;) {
+            int c = in.read();
+            if (c  == -1) // eof
+                break;
+            if (c < 32) { // new token level
+                if (tokens.size() > 0) {
+                    // replace the null at the end of the list with the token
+                    // we just finished reading
+                    tokens.set(tokens.size() - 1, currentToken.toString());
+                }
+
+                currentToken.setLength(0);
+
+                if (c > tokens.size()) {
+                    // can't increase by more than one token level at a step
+                    throw new InternalError("current token level is " +
+                            (tokens.size() - 1) + " but encountered token " +
+                            "level " + c);
+                }
+                else if (c == tokens.size()) {
+                    // token level increased by 1; this means we are still
+                    // adding tokens for the current mapping -- e.g. we have
+                    // read "core", "java", "lang" and are just about to read
+                    // "Object.class"
+                    // add a placeholder for the new token
+                    tokens.add(null);
+                }
+                else {
+                    // we just stayed at the same level or backed up one or more
+                    // token levels; this means that the current sequence is
+                    // complete and needs to be added to the result map
+                    StringBuilder key = new StringBuilder();
+                    // combine all tokens except the first into a single string
+                    for (int i = 1; i < tokens.size(); i++) {
+                        if (i > 1)
+                            key.append('/');
+                        key.append(tokens.get(i));
+                    }
+                    // map the combined string to the first token, e.g.
+                    // java/lang/Object.class = core
+                    result.put(key.toString(), tokens.get(0));
+                    // strip off tokens until we get back to the current token
+                    // level
+                    while (c < tokens.size())
+                        tokens.remove(c);
+                    // placeholder for upcoming token
+                    tokens.add(null);
+                }
+            }
+            else if (c < 254) // character
+                currentToken.append((char) c);
+            else if (c == 255)
+                currentToken.append(".class");
+            else { // out-of-band value
+                throw new InternalError("internal error processing " +
+                        "resource_map (can't-happen error)");
+            }
+        }
+        if (tokens.size() > 0) // add token we just finished reading
+            tokens.set(tokens.size() - 1, currentToken.toString());
+        StringBuilder key = new StringBuilder();
+        // add the last entry to the map
+        for (int i = 1; i < tokens.size(); i++) {
+            if (i > 1)
+                key.append('/');
+            key.append(tokens.get(i));
+        }
+        if (!tokens.isEmpty())
+            result.put(key.toString(), tokens.get(0));
+        in.close();
+        return Collections.unmodifiableMap(result);
+    }
+
+
+    /**
+     * Returns the contents of the resource_map file, which maps
+     * resources names to their respective bundles.
+     */
+    public static Map<String, String> getResourceMap() throws IOException {
+        if (resourceMap == null) {
+            InputStream in = DownloadManager.class.getResourceAsStream("resource_map");
+            if (in != null) {
+                in = new BufferedInputStream(in);
+                try {
+                    resourceMap = readTreeMap(in);
+                    in.close();
+                }
+                catch (IOException e) {
+                    // turns out we can be returned a broken stream instead of
+                    // just null
+                    resourceMap = new HashMap<String, String>();
+                    complete = true;
+                    log("Can't find resource_map, forcing complete to true");
+                }
+                in.close();
+            }
+            else {
+                resourceMap = new HashMap<String, String>();
+                complete = true;
+                log("Can't find resource_map, forcing complete to true");
+            }
+
+            for (int i = 1; ; i++) { // run through the numbered custom bundles
+                String name = CUSTOM_PREFIX + i;
+                File customPath = new File(getBundlePath(), name + ".jar");
+                if (customPath.exists()) {
+                    JarFile custom = new JarFile(customPath);
+                    Enumeration entries = custom.entries();
+                    while (entries.hasMoreElements()) {
+                        JarEntry entry = (JarEntry) entries.nextElement();
+                        if (!entry.isDirectory())
+                            resourceMap.put(entry.getName(), name);
+                    }
+                }
+                else
+                    break;
+            }
+        }
+        return resourceMap;
+    }
+
+
+    /**
+     * Returns the contents of the file_map file, which maps
+     * file names to their respective bundles.
+     */
+    public static Map<String, String> getFileMap() throws IOException {
+        if (fileMap == null) {
+            InputStream in = DownloadManager.class.getResourceAsStream("file_map");
+            if (in != null) {
+                in = new BufferedInputStream(in);
+                try {
+                    fileMap = readTreeMap(in);
+                    in.close();
+                }
+                catch (IOException e) {
+                    // turns out we can be returned a broken stream instead of
+                    // just null
+                    fileMap = new HashMap<String, String>();
+                    complete = true;
+                    log("Can't find file_map, forcing complete to true");
+                }
+                in.close();
+            }
+            else {
+                fileMap = new HashMap<String, String>();
+                complete = true;
+                log("Can't find file_map, forcing complete to true");
+            }
+        }
+        return fileMap;
+    }
+
+
+    /**
+     * Returns the contents of the bundle.properties file, which maps
+     * bundle names to a pipe-separated list of their properties.  Properties
+     * include:
+     * jarpath - By default, the JAR files (unpacked from classes.pack in the
+     *           bundle) are stored under lib/bundles.  The jarpath property
+     *           overrides this default setting, causing the JAR to be unpacked
+     *           at the specified location.  This is used to preserve the
+     *           identity of JRE JAR files such as lib/deploy.jar.
+     * size    - The size of the download in bytes.
+     */
+    private static synchronized Map<String, Map<String, String>> getBundleProperties()
+            throws IOException {
+        if (bundleProperties == null) {
+            InputStream in = DownloadManager.class.getResourceAsStream("bundle.properties");
+            if (in == null) {
+                complete = true;
+                log("Can't find bundle.properties, forcing complete to true");
+                return null;
+            }
+            in = new BufferedInputStream(in);
+            Properties tmp = new Properties();
+            tmp.load(in);
+            bundleProperties = new HashMap<String, Map<String, String>>();
+            for (Map.Entry e : tmp.entrySet()) {
+                String key = (String) e.getKey();
+                String[] properties = ((String) e.getValue()).split("\\|");
+                Map<String, String> map = new HashMap<String, String>();
+                for (String entry : properties) {
+                    int equals = entry.indexOf("=");
+                    if (equals == -1)
+                        throw new InternalError("error parsing bundle.properties: " +
+                            entry);
+                    map.put(entry.substring(0, equals).trim(),
+                        entry.substring(equals + 1).trim());
+                }
+                bundleProperties.put(key, map);
+            }
+            in.close();
+        }
+        return bundleProperties;
+    }
+
+
+    /**
+     * Returns a single bundle property value loaded from the bundle.properties
+     * file.
+     */
+    static String getBundleProperty(String bundleName, String property) {
+        try {
+            Map<String, Map<String, String>> props = getBundleProperties();
+            Map/*<String, String>*/ map = props != null ? props.get(bundleName) : null;
+            return map != null ? (String) map.get(property) : null;
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    /** Returns an array of all supported bundle names. */
+    static String[] getBundleNames() throws IOException {
+        if (bundleNames == null) {
+            Set<String> result = new HashSet<String>();
+            Map<String, String> resourceMap = getResourceMap();
+            if (resourceMap != null)
+                result.addAll(resourceMap.values());
+            Map<String, String> fileMap = getFileMap();
+            if (fileMap != null)
+                result.addAll(fileMap.values());
+            bundleNames = result.toArray(new String[result.size()]);
+        }
+        return bundleNames;
+    }
+
+
+    /**
+     * Returns an array of all "critical" (must be downloaded prior to
+     * completion) bundle names.
+     */
+    private static String[] getCriticalBundleNames() throws IOException {
+        if (criticalBundleNames == null) {
+            Set<String> result = new HashSet<String>();
+            Map<String, String> fileMap = getFileMap();
+            if (fileMap != null)
+                result.addAll(fileMap.values());
+            criticalBundleNames = result.toArray(new String[result.size()]);
+        }
+        return criticalBundleNames;
+    }
+
+
+    public static void send(InputStream in, OutputStream out)
+            throws IOException {
+        byte[] buffer = new byte[BUFFER_SIZE];
+        int c;
+        while ((c = in.read(buffer)) > 0)
+            out.write(buffer, 0, c);
+    }
+
+
+    /**
+     * Determine whether all bundles have been downloaded, and if so create
+     * the merged jars that will eventually replace rt.jar and resoures.jar.
+     * IMPORTANT: this method should only be called from the background
+     * download process.
+     */
+    static void performCompletionIfNeeded() {
+        if (debug)
+            log("DownloadManager.performCompletionIfNeeded: checking (" +
+                    complete + ", " + System.getProperty(KERNEL_NOMERGE_PROPERTY)
+                    + ")");
+        if (complete ||
+                "true".equals(System.getProperty(KERNEL_NOMERGE_PROPERTY)))
+            return;
+        Bundle.loadReceipts();
+        try {
+            if (debug) {
+                List critical = new ArrayList(Arrays.asList(getCriticalBundleNames()));
+                critical.removeAll(Bundle.receipts);
+                log("DownloadManager.performCompletionIfNeeded: still need " +
+                        critical.size() + " bundles (" + critical + ")");
+            }
+            if (Bundle.receipts.containsAll(Arrays.asList(getCriticalBundleNames()))) {
+                log("DownloadManager.performCompletionIfNeeded: running");
+                // all done!
+                new Thread("JarMerger") {
+                    public void run() {
+                        createMergedJars();
+                    }
+                }.start();
+            }
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    /**
+     * Returns the bundle corresponding to a given resource path (e.g.
+     * "java/lang/Object.class").  If the resource does not appear in a bundle,
+     * null is returned.
+     */
+    public static Bundle getBundleForResource(String resource)
+            throws IOException {
+        String bundleName = getResourceMap().get(resource);
+        return bundleName != null ? Bundle.getBundle(bundleName) : null;
+    }
+
+
+    /**
+     * Returns the bundle corresponding to a given JRE file path (e.g.
+     * "bin/awt.dll").  If the file does not appear in a bundle, null is
+     * returned.
+     */
+    private static Bundle getBundleForFile(String file) throws IOException {
+        String bundleName = getFileMap().get(file);
+        return bundleName != null ? Bundle.getBundle(bundleName) : null;
+    }
+
+
+    /**
+     * Returns the path to the lib/bundles directory.
+     */
+    static File getBundlePath() {
+        return new File(JAVA_HOME, "lib" + File.separatorChar + "bundles");
+    }
+
+    private static String getAppDataLocalLow() {
+        return USER_HOME + "\\appdata\\locallow\\";
+    }
+
+    public static String getKernelJREDir() {
+        return "kerneljre" + JAVA_VERSION;
+    }
+
+    static File getLocalLowTempBundlePath() {
+        return new File(getLocalLowKernelJava() + "-bundles");
+    }
+
+    static String getLocalLowKernelJava() {
+        return getAppDataLocalLow() + getKernelJREDir();
+    }
+
+    /**
+     * Returns an array of JAR files which have been added to the boot strap
+     * class path since the JVM was first booted.
+     */
+    public static synchronized File[] getAdditionalBootStrapPaths() {
+        return additionalBootStrapPaths != null ? additionalBootStrapPaths :
+                new File[0];
+    }
+
+
+    private static void addEntryToBootClassPath(File path) {
+        // Must acquire these locks in this order
+        synchronized(Launcher.class) {
+           synchronized(DownloadManager.class) {
+                File[] newBootStrapPaths = new File[
+                    additionalBootStrapPaths.length + 1];
+                System.arraycopy(additionalBootStrapPaths, 0, newBootStrapPaths,
+                        0, additionalBootStrapPaths.length);
+                newBootStrapPaths[newBootStrapPaths.length - 1] = path;
+                additionalBootStrapPaths = newBootStrapPaths;
+                Launcher.flushBootstrapClassPath();
+           }
+       }
+    }
+
+
+    /**
+     * Scan through java.ext.dirs to see if the lib/ext directory is included.
+     * If not, we shouldn't be "finding" lib/ext jars for download.
+     */
+    private static synchronized boolean extDirIsIncluded() {
+        if (!extDirDetermined) {
+            extDirDetermined = true;
+            String raw = System.getProperty("java.ext.dirs");
+            String ext = JAVA_HOME + File.separator + "lib" + File.separator + "ext";
+            int index = 0;
+            while (index < raw.length()) {
+                int newIndex = raw.indexOf(File.pathSeparator, index);
+                if (newIndex == -1)
+                    newIndex = raw.length();
+                String path = raw.substring(index, newIndex);
+                if (path.equals(ext)) {
+                    extDirIncluded = true;
+                    break;
+                }
+                index = newIndex + 1;
+            }
+        }
+        return extDirIncluded;
+    }
+
+
+    private static String doGetBootClassPathEntryForResource(
+            String resourceName) {
+        boolean retry = false;
+        do {
+            Bundle bundle = null;
+            try {
+                bundle = getBundleForResource(resourceName);
+                if (bundle != null) {
+                    File path = bundle.getJarPath();
+                    boolean isExt = path.getParentFile().getName().equals("ext");
+                    if (isExt && !extDirIsIncluded()) // this is a lib/ext jar, but
+                        return null;                  // lib/ext isn't in the path
+                    if (getBundleProperty(bundle.getName(), JAR_PATH_PROPERTY) == null) {
+                        // if the bundle doesn't have its own JAR path, that means it's
+                        // going to be merged into rt.jar.  If we already have the
+                        // merged rt.jar, we can simply point to that.
+                        Bundle merged = Bundle.getBundle("merged");
+                        if (merged != null && merged.isInstalled()) {
+                            File jar;
+                            if (resourceName.endsWith(".class"))
+                                jar = merged.getJarPath();
+                            else
+                                jar = new File(merged.getJarPath().getPath().replaceAll("merged-rt.jar",
+                                        "merged-resources.jar"));
+                            addEntryToBootClassPath(jar);
+                            return jar.getPath();
+                        }
+                    }
+                    if (!bundle.isInstalled()) {
+                        bundle.queueDependencies(true);
+                        log("On-demand downloading " +
+                                bundle.getName() + " for resource " +
+                                resourceName + "...");
+                        bundle.install();
+                        log(bundle + " install finished.");
+                    }
+                    log("Double-checking " + bundle + " state...");
+                    if (!bundle.isInstalled()) {
+                        throw new IllegalStateException("Expected state of " +
+                                bundle + " to be INSTALLED");
+                    }
+                    if (isExt) {
+                        // don't add lib/ext entries to the boot class path, add
+                        // them to the extension classloader instead
+                        Launcher.addURLToExtClassLoader(path.toURL());
+                        return null;
+                    }
+
+                    if ("javaws".equals(bundle.getName())) {
+                        Launcher.addURLToAppClassLoader(path.toURL());
+                        log("Returning null for javaws");
+                        return null;
+                    }
+
+                    if ("core".equals(bundle.getName()))
+                        return null;
+
+                    // else add to boot class path
+                    addEntryToBootClassPath(path);
+
+                    return path.getPath();
+                }
+                return null; // not one of the JRE's classes
+            }
+            catch (Throwable e) {
+                retry = handleException(e);
+                log("Error downloading bundle for " +
+                        resourceName + ":");
+                log(e);
+                if (e instanceof IOException) {
+                    // bundle did not get installed correctly, remove incomplete
+                    // bundle files
+                    if (bundle != null) {
+                        if (bundle.getJarPath() != null) {
+                            File packTmp = new File(bundle.getJarPath() + ".pack");
+                            packTmp.delete();
+                            bundle.getJarPath().delete();
+                        }
+                        if (bundle.getLocalPath() != null) {
+                            bundle.getLocalPath().delete();
+                        }
+                        bundle.setState(Bundle.NOT_DOWNLOADED);
+                    }
+                }
+            }
+        } while (retry);
+        sendErrorPing(ERROR_RETRY_CANCELLED); // bundle failed to install, user cancelled
+
+        return null; // failed, user chose not to retry
+    }
+
+    static synchronized void sendErrorPing(int code) {
+        try {
+            File bundlePath;
+            if (isWindowsVista()) {
+                bundlePath = getLocalLowTempBundlePath();
+            } else {
+                bundlePath = getBundlePath();
+            }
+            File tmp = new File(bundlePath, "tmp");
+            File errors = new File(tmp, "errors");
+            String errorString = String.valueOf(code);
+            if (errors.exists()) {
+                BufferedReader in = new BufferedReader(new FileReader(errors));
+                String line = in.readLine();
+                while (line != null) {
+                    if (line.equals(errorString))
+                        return; // we have already pinged this error
+                    line = in.readLine();
+                }
+            }
+            tmp.mkdirs();
+            Writer out = new FileWriter(errors, true);
+            out.write(errorString + System.getProperty("line.separator"));
+            out.close();
+            postDownloadError(code);
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+
+    /**
+     * Displays an error dialog and prompts the user to retry or cancel.
+     * Returns true if the user chose to retry, false if he chose to cancel.
+     */
+    static boolean handleException(Throwable e) {
+        if (e instanceof IOException) {
+            // I don't know of a better method to determine the root cause of
+            // the exception, unfortunately...
+            int code = ERROR_UNSPECIFIED;
+            if (e.getMessage().indexOf("not enough space") != -1)
+                code = ERROR_DISK_FULL;
+            return askUserToRetryDownloadOrQuit(code);
+        }
+        else
+            return false;
+    }
+
+
+    static synchronized void flushBundleURLs() {
+        bundleURLs = null;
+    }
+
+
+    static synchronized Properties getBundleURLs(boolean showUI)
+            throws IOException {
+        if (bundleURLs == null) {
+            log("Entering DownloadManager.getBundleURLs");
+            String base = getBaseDownloadURL();
+            String url = appendTransactionId(base);
+            // use PID instead of createTempFile or other random filename so as
+            // to avoid dependencies on the random number generator libraries
+            File bundlePath = null;
+            // write temp file to locallow directory on vista
+            if (isWindowsVista()) {
+                bundlePath = getLocalLowTempBundlePath();
+            } else {
+                bundlePath = getBundlePath();
+            }
+            File tmp = new File(bundlePath, "urls." + getCurrentProcessId() +
+                    ".properties");
+            try {
+                log("Downloading from " + url + " to " + tmp);
+                downloadFromURL(url, tmp, "", showUI);
+                bundleURLs = new Properties();
+                if (tmp.exists()) {
+                    addToTotalDownloadSize((int) tmp.length()); // better late than never
+                    InputStream in = new FileInputStream(tmp);
+                    in = new BufferedInputStream(in);
+                    bundleURLs.load(in);
+                    in.close();
+                    if (bundleURLs.isEmpty()) {
+                        fatalError(ERROR_MALFORMED_BUNDLE_PROPERTIES);
+                    }
+                } else {
+                    fatalError(ERROR_DOWNLOADING_BUNDLE_PROPERTIES);
+                }
+            } finally {
+                // delete the temp file
+                if (!debug)
+                    tmp.delete();
+            }
+            log("Leaving DownloadManager.getBundleURLs");
+            // else an error occurred and user chose not to retry; leave
+            // bundleURLs empty so we don't continually try to re-download it
+        }
+        return bundleURLs;
+    }
+
+    /**
+     * Checks to see if the specified resource is part of a bundle, and if so
+     * downloads it.  Returns either a string which should be added to the boot
+     * class path (the newly-downloaded JAR's location), or null to indicate
+     * that it isn't one of the JRE's resources or could not be downloaded.
+     */
+    public static String getBootClassPathEntryForResource(
+            final String resourceName) {
+        if (debug)
+            log("Entering getBootClassPathEntryForResource(" + resourceName + ")");
+        if (isJREComplete() || downloading == null ||
+                resourceName.startsWith("sun/jkernel")) {
+            if (debug)
+                log("Bailing: " + isJREComplete() + ", " + (downloading == null));
+            return null;
+        }
+        incrementDownloadCount();
+        try {
+            String result = (String) AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        return (String) doGetBootClassPathEntryForResource(
+                                resourceName);
+                    }
+                }
+            );
+            log("getBootClassPathEntryForResource(" + resourceName + ") == " + result);
+            return result;
+        }
+        finally {
+            decrementDownloadCount();
+        }
+    }
+
+
+    /**
+     * Called by the boot class loader when it encounters a class it can't find.
+     * This method will check to see if the class is part of a bundle, and if so
+     * download it.  Returns either a string which should be added to the boot
+     * class path (the newly-downloaded JAR's location), or null to indicate
+     * that it isn't one of the JRE's classes or could not be downloaded.
+     */
+    public static String getBootClassPathEntryForClass(final String className) {
+        return getBootClassPathEntryForResource(className.replace('.', '/') +
+                ".class");
+    }
+
+
+    private static boolean doDownloadFile(String relativePath)
+            throws IOException {
+        Bundle bundle = getBundleForFile(relativePath);
+        if (bundle != null) {
+            bundle.queueDependencies(true);
+            log("On-demand downloading " + bundle.getName() +
+                    " for file " + relativePath + "...");
+            bundle.install();
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Locates the bundle for the specified JRE file (e.g. "bin/awt.dll") and
+     * installs it.  Returns true if the file is indeed part of the JRE and has
+     * now been installed, false if the file is not part of the JRE, and throws
+     * an IOException if the file is part of the JRE but could not be
+     * downloaded.
+     */
+    public static boolean downloadFile(final String relativePath)
+            throws IOException {
+        if (isJREComplete() || downloading == null)
+            return false;
+
+        incrementDownloadCount();
+        try {
+            Object result =
+                    AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    File path = new File(JAVA_HOME,
+                            relativePath.replace('/', File.separatorChar));
+                    if (path.exists())
+                        return true;
+                    try {
+                        return new Boolean(doDownloadFile(relativePath));
+                    }
+                    catch (IOException e) {
+                        return e;
+                    }
+                }
+            });
+            if (result instanceof Boolean)
+                return ((Boolean) result).booleanValue();
+            else
+                throw (IOException) result;
+        }
+        finally {
+            decrementDownloadCount();
+        }
+    }
+
+
+    // increments the counter that tracks whether the current thread is involved
+    // in any download-related activities.  A non-zero count indicates that the
+    // thread is currently downloading or installing a bundle.
+    static void incrementDownloadCount() {
+        downloading.set(downloading.get() + 1);
+    }
+
+
+    // increments the counter that tracks whether the current thread is involved
+    // in any download-related activities.  A non-zero count indicates that the
+    // thread is currently downloading or installing a bundle.
+    static void decrementDownloadCount() {
+        // will generate an exception if incrementDownloadCount() hasn't been
+        // called first, this is intentional
+        downloading.set(downloading.get() - 1);
+    }
+
+
+    /**
+     * Returns <code>true</code> if the current thread is in the process of
+     * downloading a bundle.  This is called by ClassLoader.loadLibrary(), so
+     * that when we run into a library required by the download process itself,
+     * we don't call back into DownloadManager in an attempt to download it
+     * (which would lead to infinite recursion).
+     *
+     * All classes and libraries required to download classes must by
+     * definition already be present.  So if this method returns true, we are
+     * currently in the middle of performing a download, and the class or
+     * library load must be happening due to the download itself.  We can
+     * immediately abort such requests -- the class or library should already
+     * be present.  If it isn't, we're not going to be able to download it,
+     * since we have just established that it is required to perform a
+     * download, and we might as well just let the NoClassDefFoundError /
+     * UnsatisfiedLinkError occur.
+     */
+    public static boolean isCurrentThreadDownloading() {
+        return downloading != null ? downloading.get() > 0 : false;
+    }
+
+
+    /**
+     * Returns true if everything is downloaded and the JRE has been
+     * reconstructed.  Also returns true if kernel functionality is disabled
+     * for any other reason.
+     */
+    public static boolean isJREComplete() {
+        return complete;
+    }
+
+
+    // called by BackgroundDownloader
+    static void doBackgroundDownloads(boolean showProgress) {
+        if (!complete) {
+            if (!showProgress && !debug)
+                reportErrors = false;
+            try {
+                // install swing first for ergonomic reasons
+                Bundle swing = Bundle.getBundle("javax_swing_core");
+                if (!swing.isInstalled())
+                    swing.install(showProgress, false, false);
+                // install remaining bundles
+                for (String name : getCriticalBundleNames()) {
+                    Bundle bundle = Bundle.getBundle(name);
+                    if (!bundle.isInstalled()) {
+                        bundle.install(showProgress, false, true);
+                    }
+                }
+                shutdown();
+            }
+            catch (IOException e) {
+                log(e);
+            }
+        }
+    }
+
+    // copy receipt file to destination path specified
+    static void copyReceiptFile(File from, File to) throws IOException {
+        DataInputStream in = new DataInputStream(
+                new BufferedInputStream(new FileInputStream(from)));
+        OutputStream out = new FileOutputStream(to);
+        String line = in.readLine();
+        while (line != null) {
+            out.write((line + '\n').getBytes("utf-8"));
+            line = in.readLine();
+        }
+        in.close();
+        out.close();
+    }
+
+
+    private static void downloadRequestedBundles() {
+        log("Checking for requested bundles...");
+        try {
+            File list = new File(JAVA_HOME, REQUESTED_BUNDLES_PATH);
+            if (list.exists()) {
+                FileInputStream in = new FileInputStream(list);
+                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+                send(in, buffer);
+                in.close();
+
+                // split string manually to avoid relying on regexes or
+                // StringTokenizer
+                String raw = new String(buffer.toByteArray(), "utf-8");
+                List/*<String>*/ bundles = new ArrayList/*<String>*/();
+                StringBuilder token = new StringBuilder();
+                for (int i = 0; i < raw.length(); i++) {
+                    char c = raw.charAt(i);
+                    if (c == ',' || Character.isWhitespace(c)) {
+                        if (token.length() > 0) {
+                            bundles.add(token.toString());
+                            token.setLength(0);
+                        }
+                    }
+                    else
+                        token.append(c);
+                }
+                if (token.length() > 0)
+                    bundles.add(token.toString());
+                log("Requested bundles: " + bundles);
+                for (int i = 0; i < bundles.size(); i++) {
+                    Bundle bundle = Bundle.getBundle((String) bundles.get(i));
+                    if (bundle != null && !bundle.isInstalled()) {
+                        log("Downloading " + bundle + " due to requested.list");
+                        bundle.install(true, false, false);
+                    }
+                }
+            }
+        }
+        catch (IOException e) {
+            log(e);
+        }
+    }
+
+
+    static void fatalError(int code) {
+        fatalError(code, null);
+    }
+
+
+    /**
+     * Called to cleanly shut down the VM when a fatal download error has
+     * occurred.  Calls System.exit() if outside of the Java Plug-In, otherwise
+     * throws an error.
+     */
+    static void fatalError(int code, String arg) {
+        sendErrorPing(code);
+
+        for (int i = 0; i < Bundle.THREADS; i++)
+            bundleInstallComplete();
+        if (reportErrors)
+            displayError(code, arg);
+        // inPlugIn check isn't 100% reliable but should be close enough.
+        // headless is for the browser side of things in the out-of-process
+        // plug-in
+        boolean inPlugIn = (Boolean.getBoolean("java.awt.headless") ||
+           System.getProperty("javaplugin.version") != null);
+        KernelError error = new KernelError("Java Kernel bundle download failed");
+        if (inPlugIn)
+            throw error;
+        else {
+            log(error);
+            System.exit(1);
+        }
+    }
+
+
+    // start the background download process using the jbroker broker process
+    // the method will first launch the broker process, if it is not already
+    // running
+    // it will then send the command necessary to start the background download
+    // process to the broker process
+    private static void startBackgroundDownloadWithBroker() {
+
+        if (!BackgroundDownloader.getBackgroundDownloadProperty()) {
+            // If getBackgroundDownloadProperty() returns false
+            // we're doing the downloads from this VM; we don't want to
+            // spawn another one
+            return;
+        }
+
+        // launch broker process if necessary
+        if (!launchBrokerProcess()) {
+            return;
+        }
+
+
+        String kernelDownloadURLProperty = getBaseDownloadURL();
+
+        String kernelDownloadURL;
+
+        // only set KERNEL_DOWNLOAD_URL_PROPERTY if we override
+        // the default download url
+        if (kernelDownloadURLProperty == null ||
+                kernelDownloadURLProperty.equals(DEFAULT_DOWNLOAD_URL)) {
+            kernelDownloadURL = " ";
+        } else {
+            kernelDownloadURL = kernelDownloadURLProperty;
+        }
+
+        startBackgroundDownloadWithBrokerImpl(kernelDownloadURLProperty);
+    }
+
+    private static void startBackgroundDownloads() {
+        if (!complete) {
+            if (BackgroundDownloader.getBackgroundMutex().acquire(0)) {
+                // we don't actually need to hold the mutex -- it was just a
+                // quick check to see if there is any point in even attempting
+                // to start the background downloader
+                BackgroundDownloader.getBackgroundMutex().release();
+                if (isWindowsVista()) {
+                    // use broker process to start background download
+                    // at high integrity
+                    startBackgroundDownloadWithBroker();
+                } else {
+                    BackgroundDownloader.startBackgroundDownloads();
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Increases the total download size displayed in the download progress
+     * dialog.
+     */
+    static native void addToTotalDownloadSize(int size);
+
+
+    /**
+     * Displays a progress dialog while downloading from the specified URL.
+     *
+     *@param url the URL string from which to download
+     *@param file the destination path
+     *@param name the user-visible name of the component we are downloading
+     */
+    static void downloadFromURL(String url, File file, String name,
+            boolean showProgress) {
+        // do not show download dialog if kernel.download.dialog is false
+        downloadFromURLImpl(url, file, name,
+                disableDownloadDialog ? false : showProgress);
+    }
+
+    private static native void downloadFromURLImpl(String url, File file,
+            String name, boolean showProgress);
+
+    // This is for testing purposes only - allows to specify URL
+    // to download kernel bundles from through the registry key.
+    static native String getUrlFromRegistry();
+
+    static native String getVisitorId0();
+
+    static native void postDownloadComplete();
+
+    static native void postDownloadError(int code);
+
+    // Returns the visitor ID set by the installer, will be sent to the server
+    // during bundle downloads for logging purposes.
+    static synchronized String getVisitorId() {
+        if (!visitorIdDetermined) {
+            visitorIdDetermined = true;
+            visitorId = getVisitorId0();
+        }
+        return visitorId;
+    }
+
+    // display an error message using a native dialog
+    public static native void displayError(int code, String arg);
+
+    // prompt user whether to retry download, or quit
+    // returns true if the user chose to retry
+    public static native boolean askUserToRetryDownloadOrQuit(int code);
+
+    // returns true if we are running Windows Vista; false otherwise
+    static native boolean isWindowsVista();
+
+    private static native void startBackgroundDownloadWithBrokerImpl(
+            String command);
+
+    private static int isJBrokerStarted() {
+        if (_isJBrokerStarted == -1) {
+            // initialize state of jbroker
+            _isJBrokerStarted = isJBrokerRunning() ? 1 : 0;
+        }
+        return _isJBrokerStarted;
+    }
+
+    // returns true if broker process (jbroker) is running; false otherwise
+    private static native boolean isJBrokerRunning();
+
+    // returns true if we are running in IE protected mode; false otherwise
+    private static native boolean isIEProtectedMode();
+
+    private static native boolean launchJBroker(String jbrokerPath);
+
+    static native void bundleInstallStart();
+
+    static native void bundleInstallComplete();
+
+    private static native boolean moveFileWithBrokerImpl(String fromPath,
+            String userHome);
+
+    private static native boolean moveDirWithBrokerImpl(String fromPath,
+            String userHome);
+
+    static boolean moveFileWithBroker(String fromPath) {
+        // launch jbroker if necessary
+        if (!launchBrokerProcess()) {
+            return false;
+        }
+
+        return moveFileWithBrokerImpl(fromPath, USER_HOME);
+    }
+
+    static boolean moveDirWithBroker(String fromPath) {
+        // launch jbroker if necessary
+        if (!launchBrokerProcess()) {
+            return false;
+        }
+
+        return moveDirWithBrokerImpl(fromPath, USER_HOME);
+    }
+
+    private static synchronized boolean launchBrokerProcess() {
+        // launch jbroker if necessary
+        if (isJBrokerStarted() == 0) {
+            // launch jbroker if needed
+            boolean ret = launchJBroker(JAVA_HOME);
+            // set state of jbroker
+            _isJBrokerStarted = ret ? 1 : 0;
+            return ret;
+        }
+        return true;
+    }
+
+    private static class StreamMonitor implements Runnable {
+        private InputStream istream;
+        public StreamMonitor(InputStream stream) {
+            istream = new BufferedInputStream(stream);
+            new Thread(this).start();
+        }
+        public void run() {
+            byte[] buffer = new byte[4096];
+            try {
+                int ret = istream.read(buffer);
+                while (ret != -1) {
+                    ret = istream.read(buffer);
+                }
+            } catch (IOException e) {
+                try {
+                    istream.close();
+                } catch (IOException e2) {
+                } // Should allow clean exit when process shuts down
+            }
+        }
+    }
+
+
+    /** Copy a file tree, excluding certain named files. */
+    private static void copyAll(File src, File dest, Set/*<String>*/ excludes)
+                            throws IOException {
+        if (!excludes.contains(src.getName())) {
+            if (src.isDirectory()) {
+                File[] children = src.listFiles();
+                if (children != null) {
+                    for (int i = 0; i < children.length; i++)
+                        copyAll(children[i],
+                                new File(dest, children[i].getName()),
+                                excludes);
+                }
+            }
+            else {
+                dest.getParentFile().mkdirs();
+                FileInputStream in = new FileInputStream(src);
+                FileOutputStream out = new FileOutputStream(dest);
+                send(in, out);
+                in.close();
+                out.close();
+            }
+        }
+    }
+
+
+    public static void dumpOutput(final Process p) {
+        Thread outputReader = new Thread("outputReader") {
+            public void run() {
+                try {
+                    InputStream in = p.getInputStream();
+                    DownloadManager.send(in, System.out);
+                } catch (IOException e) {
+                    log(e);
+                }
+            }
+        };
+        outputReader.start();
+        Thread errorReader = new Thread("errorReader") {
+            public void run() {
+                try {
+                    InputStream in = p.getErrorStream();
+                    DownloadManager.send(in, System.err);
+                } catch (IOException e) {
+                    log(e);
+                }
+            }
+        };
+        errorReader.start();
+    }
+
+
+    /**
+     * Creates the merged rt.jar and resources.jar files.
+     */
+    private static void createMergedJars() {
+        log("DownloadManager.createMergedJars");
+        File bundlePath;
+        if (isWindowsVista()) {
+            bundlePath = getLocalLowTempBundlePath();
+        } else {
+            bundlePath = getBundlePath();
+        }
+        File tmp = new File(bundlePath, "tmp");
+        // explicitly check the final location, not the (potentially) local-low
+        // location -- a local-low finished isn't good enough to call it done
+        if (new File(getBundlePath(), "tmp" + File.separator + "finished").exists())
+            return; // already done
+        log("DownloadManager.createMergedJars: running");
+        tmp.mkdirs();
+        boolean retry = false;
+        do {
+            try {
+                Bundle.getBundle("merged").install(false, false, true);
+                postDownloadComplete();
+                // done, write an empty "finished" file to flag completion
+                File finished = new File(tmp, "finished");
+                new FileOutputStream(finished).close();
+                if (isWindowsVista()) {
+                    if (!moveFileWithBroker(getKernelJREDir() +
+                            "-bundles\\tmp\\finished")) {
+                        throw new IOException("unable to create 'finished' file");
+                    }
+                }
+                log("DownloadManager.createMergedJars: created " + finished);
+                // next JRE startup will move these files into their final
+                // locations, as long as no other JREs are running
+
+                // clean up the local low bundle directory on vista
+                if (isWindowsVista()) {
+                    File tmpDir = getLocalLowTempBundlePath();
+                    File[] list = tmpDir.listFiles();
+                    if (list != null) {
+                        for (int i = 0; i < list.length; i++) {
+                            list[i].delete();
+                        }
+                    }
+                    tmpDir.delete();
+                    log("Finished cleanup, " + tmpDir + ".exists(): " + tmpDir.exists());
+                }
+            }
+            catch (IOException e) {
+                log(e);
+            }
+        }
+        while (retry);
+        log("DownloadManager.createMergedJars: finished");
+    }
+
+
+    private static void shutdown() {
+        try {
+            ExecutorService e = Bundle.getThreadPool();
+            e.shutdown();
+            e.awaitTermination(60 * 60 * 24, TimeUnit.SECONDS);
+        }
+        catch (InterruptedException e) {
+        }
+    }
+
+
+    // returns the registry key for kernel.debug
+    static native boolean getDebugKey();
+
+
+    // returns the final value for the kernel debug property
+    public static boolean getDebugProperty(){
+         /*
+          * Check registry key value
+          */
+         boolean debugEnabled = getDebugKey();
+
+         /*
+          * Check system property - it should override the registry
+          * key value.
+          */
+         if (System.getProperty(KERNEL_DEBUG_PROPERTY) != null) {
+             debugEnabled = Boolean.valueOf(
+                      System.getProperty(KERNEL_DEBUG_PROPERTY));
+         }
+         return debugEnabled;
+
+    }
+
+
+    /**
+     * Outputs to the error stream even when System.err has not yet been
+     * initialized.
+     */
+    static void println(String msg) {
+        if (System.err != null)
+            System.err.println(msg);
+        else {
+            try {
+                if (errorStream == null)
+                    errorStream = new FileOutputStream(FileDescriptor.err);
+                errorStream.write((msg +
+                        System.getProperty("line.separator")).getBytes("utf-8"));
+            }
+            catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+
+    static void log(String msg) {
+        if (debug) {
+            println(msg);
+            try {
+                if (logStream == null) {
+                    loadJKernelLibrary();
+                    File path = isWindowsVista() ? getLocalLowTempBundlePath() :
+                            getBundlePath();
+                    path = new File(path, "kernel." + getCurrentProcessId() + ".log");
+                    logStream = new FileOutputStream(path);
+                }
+                logStream.write((msg +
+                        System.getProperty("line.separator")).getBytes("utf-8"));
+                logStream.flush();
+            }
+            catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+
+    static void log(Throwable e) {
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        PrintStream p = new PrintStream(buffer);
+        e.printStackTrace(p);
+        p.close();
+        log(buffer.toString(0));
+    }
+
+
+    /** Dump the contents of a map to System.out. */
+    private static void printMap(Map/*<String, String>*/ map) {
+        int size = 0;
+        Set<Integer> identityHashes = new HashSet<Integer>();
+        Iterator/*<Map.Entry<String, String>>*/ i = map.entrySet().iterator();
+        while (i.hasNext()) {
+            Map.Entry/*<String, String>*/ e = (Map.Entry) i.next();
+            String key = (String) e.getKey();
+            String value = (String) e.getValue();
+            System.out.println(key + ": " + value);
+            Integer keyHash = Integer.valueOf(System.identityHashCode(key));
+            if (!identityHashes.contains(keyHash)) {
+                identityHashes.add(keyHash);
+                size += key.length();
+            }
+            Integer valueHash = Integer.valueOf(System.identityHashCode(value));
+            if (!identityHashes.contains(valueHash)) {
+                identityHashes.add(valueHash);
+                size += value.length();
+            }
+        }
+        System.out.println(size + " bytes");
+    }
+
+
+    /** Process the "-dumpmaps" command-line argument. */
+    private static void dumpMaps() throws IOException {
+        System.out.println("Resources:");
+        System.out.println("----------");
+        printMap(getResourceMap());
+        System.out.println();
+        System.out.println("Files:");
+        System.out.println("----------");
+        printMap(getFileMap());
+    }
+
+
+    /** Process the "-download" command-line argument. */
+    private static void processDownload(String bundleName) throws IOException {
+        if (bundleName.equals("all")) {
+            debug = true;
+            doBackgroundDownloads(true);
+            performCompletionIfNeeded();
+        }
+        else {
+            Bundle bundle = Bundle.getBundle(bundleName);
+            if (bundle == null) {
+                println("Unknown bundle: " + bundleName);
+                System.exit(1);
+            }
+            else
+                bundle.install();
+        }
+    }
+
+
+    static native int getCurrentProcessId();
+
+
+    public static void main(String[] arg) throws Exception {
+        AccessController.checkPermission(new AllPermission());
+
+        boolean valid = false;
+        if (arg.length == 2 && arg[0].equals("-install")) {
+            valid = true;
+            Bundle bundle = new Bundle() {
+                protected void updateState() {
+                    // the bundle path was provided on the command line, so we
+                    // just claim it has already been "downloaded" to the local
+                    // filesystem
+                    state = DOWNLOADED;
+                }
+            };
+
+            File jarPath;
+            int index = 0;
+            do {
+                index++;
+                jarPath = new File(getBundlePath(),
+                        CUSTOM_PREFIX + index + ".jar");
+            }
+            while (jarPath.exists());
+            bundle.setName(CUSTOM_PREFIX + index);
+            bundle.setLocalPath(new File(arg[1]));
+            bundle.setJarPath(jarPath);
+            bundle.setDeleteOnInstall(false);
+            bundle.install();
+        }
+        else if (arg.length == 2 && arg[0].equals("-download")) {
+            valid = true;
+            processDownload(arg[1]);
+        }
+        else if (arg.length == 1 && arg[0].equals("-dumpmaps")) {
+            valid = true;
+            dumpMaps();
+        }
+        else if (arg.length == 2 && arg[0].equals("-sha1")) {
+            valid = true;
+            System.out.println(BundleCheck.getInstance(new File(arg[1])));
+        }
+        else if (arg.length == 1 && arg[0].equals("-downloadtest")) {
+            valid = true;
+            File file = File.createTempFile("download", ".test");
+            for (;;) {
+                file.delete();
+                downloadFromURL(getBaseDownloadURL(), file, "URLS", true);
+                System.out.println("Downloaded " + file.length() + " bytes");
+            }
+        }
+        if (!valid) {
+            System.out.println("usage: DownloadManager -install <path>.zip |");
+            System.out.println("       DownloadManager -download " +
+                    "<bundle_name> |");
+            System.out.println("       DownloadManager -dumpmaps");
+            System.exit(1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/KernelError.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+/**
+ * Thrown to indicate that Java Kernel is unable to install a required bundle
+ * and the JRE is therefore not adhering to specifications.
+ */
+public class KernelError extends VirtualMachineError {
+    /**
+     * Constructs a <code>KernelError</code> with no detail message.
+     */
+    public KernelError() {
+        super();
+    }
+
+    /**
+     * Constructs a <code>KernelError</code> with the specified
+     * detail message.
+     *
+     * @param   s   the detail message.
+     */
+    public KernelError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/Mutex.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.jkernel;
+
+/**
+ * A mutex which works even between different processes.  Currently implemented
+ * only on Win32.
+ *
+ *@author Ethan Nicholas
+ */
+public class Mutex {
+    static {
+        try {
+            System.loadLibrary("jkernel");
+        }
+        catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+
+    private String uniqueId;
+    private long handle;
+
+    public static Mutex create(String uniqueId) {
+        return new Mutex(uniqueId);
+    }
+
+
+    private Mutex(String uniqueId) {
+        this.uniqueId = uniqueId;
+        this.handle = createNativeMutex(uniqueId);
+    }
+
+
+    private static native long createNativeMutex(String uniqueId);
+
+
+    public native void acquire();
+
+
+    public native boolean acquire(int timeout);
+
+
+    public native void release();
+
+
+    public native void destroyNativeMutex();
+
+
+    public void dispose() {
+        destroyNativeMutex();
+        handle = 0;
+    }
+
+
+    public void finalize() {
+        dispose();
+    }
+
+
+    public String toString() {
+        return "Mutex[" + uniqueId + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/StandaloneByteArrayAccess.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This is a pure subset of package-private class
+ * sun.security.provider.ByteArrayAccess. The subset consists of only the simple
+ * shift and boolean operations needed for the one current client of this
+ * class (sun.jkernel.StandaloneSHA) and omits optimization code and comments
+ * not relevant to the subset.  No semantic changes have been made.
+ * A few long lines were broken to conform to JDK coding style.
+ * Pete Soper, August, 2007.
+ */
+
+package sun.jkernel;
+
+/**
+ * Methods for converting between byte[] and int[]/long[].
+ *
+ * @since   1.6
+ * @version 1.1, 05/26/06
+ * @author  Andreas Sterbenz
+ */
+final class StandaloneByteArrayAccess {
+
+    private StandaloneByteArrayAccess() {
+        // empty
+    }
+
+    /**
+     * byte[] to int[] conversion, little endian byte order.
+     */
+    static void b2iLittle(byte[] in, int inOfs, int[] out, int outOfs,
+        int len) {
+        len += inOfs;
+        while (inOfs < len) {
+            out[outOfs++] = ((in[inOfs    ] & 0xff)      )
+                          | ((in[inOfs + 1] & 0xff) <<  8)
+                          | ((in[inOfs + 2] & 0xff) << 16)
+                          | ((in[inOfs + 3]       ) << 24);
+            inOfs += 4;
+        }
+    }
+
+    /**
+     * int[] to byte[] conversion, little endian byte order.
+     */
+    static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs,
+        int len) {
+        len += outOfs;
+        while (outOfs < len) {
+            int i = in[inOfs++];
+            out[outOfs++] = (byte)(i      );
+            out[outOfs++] = (byte)(i >>  8);
+            out[outOfs++] = (byte)(i >> 16);
+            out[outOfs++] = (byte)(i >> 24);
+        }
+    }
+
+    /**
+     * byte[] to int[] conversion, big endian byte order.
+     */
+    static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) {
+        len += inOfs;
+        while (inOfs < len) {
+            out[outOfs++] = ((in[inOfs + 3] & 0xff)      )
+                          | ((in[inOfs + 2] & 0xff) <<  8)
+                          | ((in[inOfs + 1] & 0xff) << 16)
+                          | ((in[inOfs    ]       ) << 24);
+            inOfs += 4;
+        }
+    }
+
+    /**
+     * int[] to byte[] conversion, big endian byte order.
+     */
+    static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) {
+        len += outOfs;
+        while (outOfs < len) {
+            int i = in[inOfs++];
+            out[outOfs++] = (byte)(i >> 24);
+            out[outOfs++] = (byte)(i >> 16);
+            out[outOfs++] = (byte)(i >>  8);
+            out[outOfs++] = (byte)(i      );
+        }
+    }
+
+    // Store one 32-bit value into out[outOfs..outOfs+3] in big endian order.
+    static void i2bBig4(int val, byte[] out, int outOfs) {
+        out[outOfs    ] = (byte)(val >> 24);
+        out[outOfs + 1] = (byte)(val >> 16);
+        out[outOfs + 2] = (byte)(val >>  8);
+        out[outOfs + 3] = (byte)(val      );
+    }
+
+    /**
+     * byte[] to long[] conversion, big endian byte order.
+     */
+    static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) {
+        len += inOfs;
+        while (inOfs < len) {
+            int i1 = ((in[inOfs + 3] & 0xff)      )
+                   | ((in[inOfs + 2] & 0xff) <<  8)
+                   | ((in[inOfs + 1] & 0xff) << 16)
+                   | ((in[inOfs    ]       ) << 24);
+            inOfs += 4;
+            int i2 = ((in[inOfs + 3] & 0xff)      )
+                   | ((in[inOfs + 2] & 0xff) <<  8)
+                   | ((in[inOfs + 1] & 0xff) << 16)
+                   | ((in[inOfs    ]       ) << 24);
+            out[outOfs++] = ((long)i1 << 32) | (i2 & 0xffffffffL);
+            inOfs += 4;
+        }
+    }
+
+    /**
+     * long[] to byte[] conversion
+     */
+    static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) {
+        len += outOfs;
+        while (outOfs < len) {
+            long i = in[inOfs++];
+            out[outOfs++] = (byte)(i >> 56);
+            out[outOfs++] = (byte)(i >> 48);
+            out[outOfs++] = (byte)(i >> 40);
+            out[outOfs++] = (byte)(i >> 32);
+            out[outOfs++] = (byte)(i >> 24);
+            out[outOfs++] = (byte)(i >> 16);
+            out[outOfs++] = (byte)(i >>  8);
+            out[outOfs++] = (byte)(i      );
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/StandaloneMessageDigest.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This is a combination and adaptation of subsets of
+ * <code>java.security.MessageDigest</code> and
+ * <code>sun.security.provider.DigestBase</code> to provide a class offering
+ * most of the same public methods of <code>MessageDigest</code> while not
+ * depending on the Java Security Framework.
+ * <p>
+ * One algorithm is currently supported: "SHA-1".
+ * <p>
+ * NOTE If <code>java.security.MessageDigest</code>,
+ * <code>sun.security.provider.DigestBase</code> or
+ * <code>sun.security.provider.SHA</code> are modified, review of those
+ * modifications should be done to determine any possible implications for this
+ * class and <code>StandaloneSHA</code>.
+ */
+
+package sun.jkernel;
+
+import java.security.DigestException;
+import java.security.ProviderException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * (Adapted from the <code>sun.security.provider.DigestBase</code> doc).
+ * This is a simple subset of the Common base message digest implementation
+ * for the Sun provider.
+ * It implements most of the JCA methods as suitable for a Java message
+ * digest
+ * implementation of an algorithm based on a compression function (as all
+ * commonly used algorithms are). The individual digest subclasses only need to
+ * implement the following methods:
+ *
+ *  . abstract void implCompress(byte[] b, int ofs);
+ *  . abstract void implDigest(byte[] out, int ofs);
+ *  . abstract void implReset();
+ * <p>
+ * No support for a clone() method is provided.
+ * <p>
+ * See the inline documentation for details.
+ *
+ * @since   1.5
+ * @version 1.3, 08/08/07
+ * @author  Andreas Sterbenz (MessageDigest)
+ * @author  Pete Soper (this derived class)
+ */
+public abstract class StandaloneMessageDigest {
+
+     public static final boolean debug = false;
+
+    /*
+     * (Copied/adapted from <code>java.security.MessageDigest</code>
+     *
+     * This is a subset/simplification <code>java.security.MessageDigest</code>
+     * that supports a fixed set of hashcode mechanisms (currently just
+     * SHA-1) while preserving the following MessageDigest methods:
+     *
+     * public MessageDigest getInstance(String algorithm)
+     * public final int getDigestLength()
+     * public void reset()
+     * public byte[] digest()
+     * public void update(byte[] input, int offset, int len)
+     * public final String getAlgorithm()
+     * <p>
+     * NOTE that the clone() method is not provided.
+     */
+
+    /**
+     * Prevent direct instantiation except via the factory method.
+     */
+
+    private StandaloneMessageDigest() {
+        // Keep javac happy.
+        digestLength = 0;
+        blockSize = 0;
+        algorithm = null;
+        buffer = null;
+    }
+
+    private String algorithm;
+
+    // The state of this digest
+    private static final int INITIAL = 0;
+    private static final int IN_PROGRESS = 1;
+    private int state = INITIAL;
+
+    /**
+     * Returns a StandaloneMessageDigest object that implements the specified
+     * digest algorithm.
+     *
+     * <p> This method returns a new StandaloneMessageDigest for a single
+     * algorithm provider.
+     *
+     * @param algorithm the name of the algorithm requested.
+     *
+     * @return a standalone Message Digest object that implements the specified algorithm.
+     *
+     * @exception NoSuchAlgorithmException if algorithm not supported
+     *
+     */
+    public static StandaloneMessageDigest getInstance(String algorithm)
+        throws NoSuchAlgorithmException {
+        if (! algorithm.equals("SHA-1")) {
+            throw new NoSuchAlgorithmException(algorithm + " not found");
+        } else {
+            return new StandaloneSHA();
+        }
+    }
+
+    /**
+     * Updates the digest using the specified array of bytes, starting
+     * at the specified offset.
+     *
+     * @param input the array of bytes.
+     *
+     * @param offset the offset to start from in the array of bytes.
+     *
+     * @param len the number of bytes to use, starting at
+     * <code>offset</code>.
+     */
+    public void update(byte[] input, int offset, int len) {
+        if (debug) {
+            System.out.println("StandaloneMessageDigest.update");
+            (new Exception()).printStackTrace();
+        }
+        if (input == null) {
+            throw new IllegalArgumentException("No input buffer given");
+        }
+        if (input.length - offset < len) {
+            throw new IllegalArgumentException("Input buffer too short");
+        }
+        // No need to check for negative offset: engineUpdate does this
+
+        engineUpdate(input, offset, len);
+        state = IN_PROGRESS;
+    }
+
+    /**
+     * Completes the hash computation by performing final operations
+     * such as padding. The digest is reset after this call is made.
+     *
+     * @return the array of bytes for the resulting hash value.
+     */
+    public byte[] digest() {
+        if (debug) {
+            System.out.println("StandaloneMessageDigest.digest");
+        }
+        /* Resetting is the responsibility of implementors. */
+        byte[] result = engineDigest();
+        state = INITIAL;
+        return result;
+    }
+
+    /**
+     * Compares two digests for equality. Does a simple byte compare.
+     *
+     * @param digesta one of the digests to compare.
+     *
+     * @param digestb the other digest to compare.
+     *
+     * @return true if the digests are equal, false otherwise.
+     */
+    public static boolean isEqual(byte digesta[], byte digestb[]) {
+        if (digesta.length != digestb.length)
+            return false;
+
+        for (int i = 0; i < digesta.length; i++) {
+            if (digesta[i] != digestb[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Resets the digest for further use.
+     */
+    public void reset() {
+        if (debug) {
+            System.out.println("StandaloneMessageDigest.reset");
+        }
+        engineReset();
+        state = INITIAL;
+    }
+
+    /**
+     * Returns a string that identifies the algorithm, independent of
+     * implementation details. The name should be a standard
+     * Java Security name (such as "SHA", "MD5", and so on).
+     * See Appendix A in the <a href=
+     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * for information about standard algorithm names.
+     *
+     * @return the name of the algorithm
+     */
+    public final String getAlgorithm() {
+        return this.algorithm;
+    }
+
+    /**
+     * Returns the length of the digest in bytes.
+     *
+     * @return the digest length in bytes.
+     *
+     * @since 1.2
+     */
+    public final int getDigestLength() {
+        return engineGetDigestLength();
+    }
+
+    //* End of copied/adapted <code>java.security.MessageDigest</code>
+
+    // Start of copied/adapted <code>sun.security.provider.DigestBase</code>
+
+    // one element byte array, temporary storage for update(byte)
+    private byte[] oneByte;
+
+    // length of the message digest in bytes
+    private final int digestLength;
+
+    // size of the input to the compression function in bytes
+    private final int blockSize;
+    // buffer to store partial blocks, blockSize bytes large
+    // Subclasses should not access this array directly except possibly in their
+    // implDigest() method. See MD5.java as an example.
+    final byte[] buffer;
+    // offset into buffer
+    private int bufOfs;
+
+    // number of bytes processed so far. subclasses should not modify
+    // this value.
+    // also used as a flag to indicate reset status
+    // -1: need to call engineReset() before next call to update()
+    //  0: is already reset
+    long bytesProcessed;
+
+    /**
+     * Main constructor.
+     */
+    StandaloneMessageDigest(String algorithm, int digestLength, int blockSize) {
+        // super();
+        this.algorithm = algorithm;
+        this.digestLength = digestLength;
+        this.blockSize = blockSize;
+        buffer = new byte[blockSize];
+    }
+
+    // return digest length. See JCA doc.
+    protected final int engineGetDigestLength() {
+        return digestLength;
+    }
+
+    // single byte update. See JCA doc.
+    protected final void engineUpdate(byte b) {
+        if (oneByte == null) {
+            oneByte = new byte[1];
+        }
+        oneByte[0] = b;
+        engineUpdate(oneByte, 0, 1);
+    }
+
+    // array update. See JCA doc.
+    protected final void engineUpdate(byte[] b, int ofs, int len) {
+        if (len == 0) {
+            return;
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > b.length - len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (bytesProcessed < 0) {
+            engineReset();
+        }
+        bytesProcessed += len;
+        // if buffer is not empty, we need to fill it before proceeding
+        if (bufOfs != 0) {
+            int n = Math.min(len, blockSize - bufOfs);
+            System.arraycopy(b, ofs, buffer, bufOfs, n);
+            bufOfs += n;
+            ofs += n;
+            len -= n;
+            if (bufOfs >= blockSize) {
+                // compress completed block now
+                implCompress(buffer, 0);
+                bufOfs = 0;
+            }
+        }
+        // compress complete blocks
+        while (len >= blockSize) {
+            implCompress(b, ofs);
+            len -= blockSize;
+            ofs += blockSize;
+        }
+        // copy remainder to buffer
+        if (len > 0) {
+            System.arraycopy(b, ofs, buffer, 0, len);
+            bufOfs = len;
+        }
+    }
+
+    // reset this object. See JCA doc.
+    protected final void engineReset() {
+        if (bytesProcessed == 0) {
+            // already reset, ignore
+            return;
+        }
+        implReset();
+        bufOfs = 0;
+        bytesProcessed = 0;
+    }
+
+    // return the digest. See JCA doc.
+    protected final byte[] engineDigest() throws ProviderException {
+        byte[] b = new byte[digestLength];
+        try {
+            engineDigest(b, 0, b.length);
+        } catch (DigestException e) {
+            throw (ProviderException)
+                new ProviderException("Internal error").initCause(e);
+        }
+        return b;
+    }
+
+    // return the digest in the specified array. See JCA doc.
+    protected final int engineDigest(byte[] out, int ofs, int len)
+            throws DigestException {
+        if (len < digestLength) {
+            throw new DigestException("Length must be at least "
+                + digestLength + " for " + algorithm + "digests");
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
+            throw new DigestException("Buffer too short to store digest");
+        }
+        if (bytesProcessed < 0) {
+            engineReset();
+        }
+        implDigest(out, ofs);
+        bytesProcessed = -1;
+        return digestLength;
+    }
+
+    /**
+     * Core compression function. Processes blockSize bytes at a time
+     * and updates the state of this object.
+     */
+    abstract void implCompress(byte[] b, int ofs);
+
+    /**
+     * Return the digest. Subclasses do not need to reset() themselves,
+     * StandaloneMessageDigest calls implReset() when necessary.
+     */
+    abstract void implDigest(byte[] out, int ofs);
+
+    /**
+     * Reset subclass specific state to their initial values. StandaloneMessageDigest
+     * calls this method when necessary.
+     */
+    abstract void implReset();
+
+    // padding used for the MD5, and SHA-* message digests
+    static final byte[] padding;
+
+    static {
+        // we need 128 byte padding for SHA-384/512
+        // and an additional 8 bytes for the high 8 bytes of the 16
+        // byte bit counter in SHA-384/512
+        padding = new byte[136];
+        padding[0] = (byte)0x80;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/jkernel/StandaloneSHA.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.jkernel;
+
+import static sun.jkernel.StandaloneByteArrayAccess.*;
+
+/**
+ * This is a slightly modified subset of the
+ * <code>sun.security.provider.SHA</code> class that
+ * is not dependent on the regular Java Security framework classes. It
+ * implements the Secure Hash Algorithm (SHA-1) developed by
+ * the National Institute of Standards and Technology along with the
+ * National Security Agency.  This is the updated version of SHA
+ * fip-180 as superseded by fip-180-1.
+ * <p>
+ * The <code>sun.security.provider.SHA.clonde()</code> method is not
+ * implemented and other, formerly public methods, are package private.
+ *
+ */
+final class StandaloneSHA extends StandaloneMessageDigest {
+
+    static final boolean debug = false;
+
+    // Buffer of int's and count of characters accumulated
+    // 64 bytes are included in each hash block so the low order
+    // bits of count are used to know how to pack the bytes into ints
+    // and to know when to compute the block and start the next one.
+    private final int[] W;
+
+    // state of this
+    private final int[] state;
+
+    /**
+     * Creates a new StandaloneSHA object.
+     */
+    StandaloneSHA() {
+        super("SHA-1", 20, 64);
+        state = new int[5];
+        W = new int[80];
+        implReset();
+    }
+
+    /**
+     * Resets the buffers and hash value to start a new hash.
+     */
+    void implReset() {
+        if (debug) {
+            System.out.print("StandaloneSHA.implR: " );
+        }
+        state[0] = 0x67452301;
+        state[1] = 0xefcdab89;
+        state[2] = 0x98badcfe;
+        state[3] = 0x10325476;
+        state[4] = 0xc3d2e1f0;
+    }
+
+    /**
+     * Computes the final hash and copies the 20 bytes to the output array.
+     */
+    void implDigest(byte[] out, int ofs) {
+        if (debug) {
+            System.out.print("StandaloneSHA.implD: " );
+        }
+        long bitsProcessed = bytesProcessed << 3;
+
+        int index = (int)bytesProcessed & 0x3f;
+        int padLen = (index < 56) ? (56 - index) : (120 - index);
+
+        engineUpdate(padding, 0, padLen);
+
+        // System.out.println("Inserting: " + bitsProcessed);
+        StandaloneByteArrayAccess.i2bBig4((int)(bitsProcessed >>> 32), buffer, 56);
+        StandaloneByteArrayAccess.i2bBig4((int)bitsProcessed, buffer, 60);
+        implCompress(buffer, 0);
+
+        StandaloneByteArrayAccess.i2bBig(state, 0, out, ofs, 20);
+    }
+
+    // Constants for each round
+    private final static int round1_kt = 0x5a827999;
+    private final static int round2_kt = 0x6ed9eba1;
+    private final static int round3_kt = 0x8f1bbcdc;
+    private final static int round4_kt = 0xca62c1d6;
+
+    /**
+     * Compute a the hash for the current block.
+     *
+     * This is in the same vein as Peter Gutmann's algorithm listed in
+     * the back of Applied Cryptography, Compact implementation of
+     * "old" NIST Secure Hash Algorithm.
+     */
+    void implCompress(byte[] buf, int ofs) {
+
+        if (debug) {
+            System.out.print("StandaloneSHA.implC: " );
+            for (int i=ofs; i<buf.length; i++) {
+                System.out.format("%02X",buf[i]);
+            }
+            System.out.println();
+        }
+
+        StandaloneByteArrayAccess.b2iBig(buf, ofs, W, 0, 64);
+
+        // The first 16 ints have the byte stream, compute the rest of
+        // the buffer
+        for (int t = 16; t <= 79; t++) {
+            int temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
+            W[t] = (temp << 1) | (temp >>> 31);
+        }
+
+        int a = state[0];
+        int b = state[1];
+        int c = state[2];
+        int d = state[3];
+        int e = state[4];
+
+        // Round 1
+        for (int i = 0; i < 20; i++) {
+            int temp = ((a<<5) | (a>>>(32-5))) +
+                ((b&c)|((~b)&d))+ e + W[i] + round1_kt;
+            e = d;
+            d = c;
+            c = ((b<<30) | (b>>>(32-30)));
+            b = a;
+            a = temp;
+        }
+
+        // Round 2
+        for (int i = 20; i < 40; i++) {
+            int temp = ((a<<5) | (a>>>(32-5))) +
+                (b ^ c ^ d) + e + W[i] + round2_kt;
+            e = d;
+            d = c;
+            c = ((b<<30) | (b>>>(32-30)));
+            b = a;
+            a = temp;
+        }
+
+        // Round 3
+        for (int i = 40; i < 60; i++) {
+            int temp = ((a<<5) | (a>>>(32-5))) +
+                ((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt;
+            e = d;
+            d = c;
+            c = ((b<<30) | (b>>>(32-30)));
+            b = a;
+            a = temp;
+        }
+
+        // Round 4
+        for (int i = 60; i < 80; i++) {
+            int temp = ((a<<5) | (a>>>(32-5))) +
+                (b ^ c ^ d) + e + W[i] + round4_kt;
+            e = d;
+            d = c;
+            c = ((b<<30) | (b>>>(32-30)));
+            b = a;
+            a = temp;
+        }
+        state[0] += a;
+        state[1] += b;
+        state[2] += c;
+        state[3] += d;
+        state[4] += e;
+    }
+
+}
--- a/src/share/classes/sun/management/OperatingSystemImpl.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/management/OperatingSystemImpl.java	Tue Jul 21 13:02:23 2009 -0700
@@ -78,4 +78,3 @@
     }
 
 }
-
--- a/src/share/classes/sun/management/ThreadImpl.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/management/ThreadImpl.java	Tue Jul 21 13:02:23 2009 -0700
@@ -419,4 +419,3 @@
     }
 
 }
-
--- a/src/share/classes/sun/misc/Launcher.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/misc/Launcher.java	Tue Jul 21 13:02:23 2009 -0700
@@ -38,6 +38,7 @@
 import java.util.Set;
 import java.util.Vector;
 import java.security.AccessController;
+import java.security.AllPermission;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.security.AccessControlContext;
@@ -49,7 +50,8 @@
 import sun.security.action.GetPropertyAction;
 import sun.security.util.SecurityConstants;
 import sun.net.www.ParseUtil;
-
+import sun.jkernel.Bundle;
+import sun.jkernel.DownloadManager;
 
 /**
  * This class is used by the system to launch the main application.
@@ -116,6 +118,18 @@
         return loader;
     }
 
+    public static void addURLToAppClassLoader(URL u) {
+        AccessController.checkPermission(new AllPermission());
+        ClassLoader loader = Launcher.getLauncher().getClassLoader();
+        ((Launcher.AppClassLoader) loader).addAppURL(u);
+    }
+
+    public static void addURLToExtClassLoader(URL u) {
+        AccessController.checkPermission(new AllPermission());
+        ClassLoader loader = Launcher.getLauncher().getClassLoader();
+        ((Launcher.ExtClassLoader) loader.getParent()).addExtURL(u);
+    }
+
     /*
      * The class loader used for loading installed extensions.
      */
@@ -233,6 +247,16 @@
             return null;
         }
 
+        protected Class findClass(String name) throws ClassNotFoundException {
+            if (VM.isBootedKernelVM()) {
+                // Check for download before we look for it.  If
+                // DownloadManager ends up downloading it, it will add it to
+                // our search path before we proceed to the findClass().
+                DownloadManager.getBootClassPathEntryForClass(name);
+            }
+            return super.findClass(name);
+        }
+
         private static AccessControlContext getContext(File[] dirs)
             throws IOException
         {
@@ -297,6 +321,9 @@
         public Class loadClass(String name, boolean resolve)
             throws ClassNotFoundException
         {
+            if (VM.isBootedKernelVM()) {
+                DownloadManager.getBootClassPathEntryForClass(name);
+            }
             int i = name.lastIndexOf('.');
             if (i != -1) {
                 SecurityManager sm = System.getSecurityManager();
@@ -353,39 +380,66 @@
 
             return acc;
         }
+
+        void addAppURL(URL url) {
+            super.addURL(url);
+        }
     }
 
-    public static URLClassPath getBootstrapClassPath() {
-        String prop = AccessController.doPrivileged(
-            new GetPropertyAction("sun.boot.class.path"));
-        URL[] urls;
-        if (prop != null) {
-            final String path = prop;
-            urls = AccessController.doPrivileged(
-                new PrivilegedAction<URL[]>() {
-                    public URL[] run() {
-                        File[] classPath = getClassPath(path);
-                        int len = classPath.length;
-                        Set<File> seenDirs = new HashSet<File>();
-                        for (int i = 0; i < len; i++) {
-                            File curEntry = classPath[i];
-                            // Negative test used to properly handle
-                            // nonexistent jars on boot class path
-                            if (!curEntry.isDirectory()) {
-                                curEntry = curEntry.getParentFile();
+    private static URLClassPath bootstrapClassPath;
+
+    public static synchronized URLClassPath getBootstrapClassPath() {
+        if (bootstrapClassPath == null) {
+            String prop = AccessController.doPrivileged(
+                new GetPropertyAction("sun.boot.class.path"));
+            URL[] urls;
+            if (prop != null) {
+                final String path = prop;
+                urls = AccessController.doPrivileged(
+                    new PrivilegedAction<URL[]>() {
+                        public URL[] run() {
+                            File[] classPath = getClassPath(path);
+                            int len = classPath.length;
+                            Set<File> seenDirs = new HashSet<File>();
+                            for (int i = 0; i < len; i++) {
+                                File curEntry = classPath[i];
+                                // Negative test used to properly handle
+                                // nonexistent jars on boot class path
+                                if (!curEntry.isDirectory()) {
+                                    curEntry = curEntry.getParentFile();
+                                }
+                                if (curEntry != null && seenDirs.add(curEntry)) {
+                                    MetaIndex.registerDirectory(curEntry);
+                                }
                             }
-                            if (curEntry != null && seenDirs.add(curEntry)) {
-                                MetaIndex.registerDirectory(curEntry);
-                            }
+                            return pathToURLs(classPath);
                         }
-                        return pathToURLs(classPath);
                     }
-                }
-            );
-        } else {
-            urls = new URL[0];
+                );
+            } else {
+                urls = new URL[0];
+            }
+
+            bootstrapClassPath = new URLClassPath(urls, factory);
+            if (VM.isBootedKernelVM()) {
+                final File[] additionalBootStrapPaths =
+                    DownloadManager.getAdditionalBootStrapPaths();
+                AccessController.doPrivileged(new PrivilegedAction() {
+                    public Object run() {
+                        for (int i=0; i<additionalBootStrapPaths.length; i++) {
+                            bootstrapClassPath.addURL(
+                                getFileURL(additionalBootStrapPaths[i]));
+                        }
+                        return null;
+                    }
+                });
+            }
         }
-        return new URLClassPath(urls, factory);
+        return bootstrapClassPath;
+    }
+
+    public static synchronized void flushBootstrapClassPath() {
+        bootstrapClassPath = null;
     }
 
     private static URL[] pathToURLs(File[] path) {
--- a/src/share/classes/sun/misc/PerformanceLogger.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/misc/PerformanceLogger.java	Tue Jul 21 13:02:23 2009 -0700
@@ -81,6 +81,7 @@
     private static Vector<TimeData> times;
     private static String logFileName = null;
     private static Writer logWriter = null;
+    private static long baseTime;
 
     static {
         String perfLoggingProp =
@@ -188,6 +189,16 @@
     }
 
     /**
+     * Sets the base time, output can then
+     * be displayed as offsets from the base time;.
+     */
+    public static void setBaseTime(long time) {
+        if (loggingEnabled()) {
+            baseTime = time;
+        }
+    }
+
+    /**
      * Sets the start time.
      * This version of the method is
      * given the time to log, instead of expecting this method to
@@ -281,7 +292,8 @@
                         TimeData td = times.get(i);
                         if (td != null) {
                             writer.write(i + " " + td.getMessage() + ": " +
-                                         td.getTime() + "\n");
+                                         (td.getTime() - baseTime) + "\n");
+
                         }
                     }
                 }
--- a/src/share/classes/sun/misc/VM.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/misc/VM.java	Tue Jul 21 13:02:23 2009 -0700
@@ -346,6 +346,11 @@
     private native static void getThreadStateValues(int[][] vmThreadStateValues,
                                                     String[][] vmThreadStateNames);
 
+    private static boolean kernelVM;
+    public static boolean isBootedKernelVM() {
+        return booted && kernelVM;
+    }
+
     static {
         initialize();
     }
--- a/src/share/classes/sun/security/provider/certpath/CertPathHelper.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/security/provider/certpath/CertPathHelper.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2006 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
@@ -25,9 +25,11 @@
 
 package sun.security.provider.certpath;
 
+import java.util.Date;
 import java.util.Set;
 
 import java.security.cert.X509CertSelector;
+import java.security.cert.X509CRLSelector;
 
 import sun.security.x509.GeneralNameInterface;
 
@@ -55,8 +57,14 @@
     protected abstract void implSetPathToNames(X509CertSelector sel,
             Set<GeneralNameInterface> names);
 
+    protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
+
     static void setPathToNames(X509CertSelector sel,
             Set<GeneralNameInterface> names) {
         instance.implSetPathToNames(sel, names);
     }
+
+    static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
+        instance.implSetDateAndTime(sel, date, skew);
+    }
 }
--- a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,10 @@
     private static final boolean[] ALL_REASONS =
         {true, true, true, true, true, true, true, true, true};
 
+    // Maximum clock skew in milliseconds (15 minutes) allowed when checking
+    // validity of CRLs
+    private static final long MAX_CLOCK_SKEW = 900000;
+
     /**
      * Creates a <code>CrlRevocationChecker</code>.
      *
@@ -281,7 +285,7 @@
         try {
             X509CRLSelector sel = new X509CRLSelector();
             sel.setCertificateChecking(currCert);
-            sel.setDateAndTime(mCurrentTime);
+            CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW);
 
             for (CertStore mStore : mStores) {
                 for (java.security.cert.CRL crl : mStore.getCRLs(sel)) {
--- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Tue Jul 21 13:02:23 2009 -0700
@@ -149,9 +149,9 @@
 
     private SingleResponse singleResponse;
 
-    // Maximum clock skew in milliseconds (10 minutes) allowed when checking
+    // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of OCSP responses
-    private static final long MAX_CLOCK_SKEW = 600000;
+    private static final long MAX_CLOCK_SKEW = 900000;
 
     // an array of all of the CRLReasons (used in SingleResponse)
     private static CRLReason[] values = CRLReason.values();
--- a/src/share/classes/sun/swing/AccessibleMethod.java	Wed Jul 15 10:46:42 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-package sun.swing;
-
-import java.security.*;
-import java.lang.reflect.*;
-
-/**
- * A utility for accessing and invoking methods, via reflection,
- * that would otherwise be unaccessible.
- *
- * @author Shannon Hickey
- */
-public class AccessibleMethod {
-
-    private final Method method;
-
-    /**
-     * Construct an instance for the given params.
-     *
-     * @param klass the class to which the method belongs
-     * @param methodName the name of the method
-     * @param paramTypes the paramater type array
-     * @throws NullPointerException if <code>klass</code>
-     *         or <code>name</code> is <code>null</code>
-     * @throws NoSuchMethodException if the method can't be found
-     */
-    public AccessibleMethod(Class klass,
-                            String methodName,
-                            Class ... paramTypes) throws NoSuchMethodException {
-        try {
-            method = AccessController.doPrivileged(
-                new AccessMethodAction(klass, methodName, paramTypes));
-        } catch (PrivilegedActionException e) {
-            throw (NoSuchMethodException)e.getCause();
-        }
-    }
-
-    /**
-     * Invoke the method that this object represents.
-     * Has the same behavior and throws the same exceptions as
-     * <code>java.lang.reflect.Method.invoke</code> with one
-     * exception: This method does not throw
-     * <code>IllegalAccessException</code> since the target
-     * method has already been made accessible.
-     *
-     * @param obj the object the underlying method is invoked from
-     * @param args the arguments used for the method call
-     * @return the result of dispatching the method represented by
-     *         this object on <code>obj</code> with parameters
-     *         <code>args</code>
-     * @see java.lang.reflect.Method#invoke
-     */
-    public Object invoke(Object obj, Object ... args)
-            throws IllegalArgumentException, InvocationTargetException {
-
-        try {
-            return method.invoke(obj, args);
-        } catch (IllegalAccessException e) {
-            // should never happen since we've made it accessible
-            throw new AssertionError("accessible method inaccessible");
-        }
-    }
-
-    /**
-     * Invoke the method that this object represents, with the
-     * expectation that the method being called throws no
-     * checked exceptions.
-     * <p>
-     * Simply calls <code>this.invoke(obj, args)</code>
-     * but catches any <code>InvocationTargetException</code>
-     * and returns the cause wrapped in a runtime exception.
-     *
-     * @param obj the object the underlying method is invoked from
-     * @param args the arguments used for the method call
-     * @return the result of dispatching the method represented by
-     *         this object on <code>obj</code> with parameters
-     *         <code>args</code>
-     * @see #invoke
-     */
-    public Object invokeNoChecked(Object obj, Object ... args) {
-        try {
-            return invoke(obj, args);
-        } catch (InvocationTargetException ex) {
-            if (ex.getCause() instanceof RuntimeException) {
-                throw (RuntimeException)ex.getCause();
-            } else {
-                throw new RuntimeException(ex.getCause());
-            }
-        }
-    }
-
-    /** The action used to fetch the method and make it accessible */
-    private static class AccessMethodAction implements PrivilegedExceptionAction<Method> {
-        private final Class<?> klass;
-        private final String methodName;
-        private final Class[] paramTypes;
-
-        public AccessMethodAction(Class klass,
-                                  String methodName,
-                                  Class ... paramTypes) {
-
-            this.klass = klass;
-            this.methodName = methodName;
-            this.paramTypes = paramTypes;
-        }
-
-        public Method run() throws NoSuchMethodException {
-            Method method = klass.getDeclaredMethod(methodName, paramTypes);
-            method.setAccessible(true);
-            return method;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/swing/SwingAccessor.java	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.swing;
+
+import sun.misc.Unsafe;
+
+import java.awt.Point;
+
+import javax.swing.text.JTextComponent;
+import javax.swing.TransferHandler;
+
+/**
+ * The SwingAccessor utility class.
+ * The main purpose of this class is to enable accessing
+ * private and package-private fields of classes from
+ * different classes/packages. See sun.misc.SharedSecretes
+ * for another example.
+ */
+public final class SwingAccessor {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /**
+     * We don't need any objects of this class.
+     * It's rather a collection of static methods
+     * and interfaces.
+     */
+    private SwingAccessor() {
+    }
+
+    /**
+     * An accessor for the JTextComponent class.
+     * Note that we intentionally introduce the JTextComponentAccessor,
+     * and not the JComponentAccessor because the needed methods
+     * aren't override methods.
+     */
+    public interface JTextComponentAccessor {
+
+        /**
+         * Calculates a custom drop location for the text component,
+         * representing where a drop at the given point should insert data.
+         */
+        TransferHandler.DropLocation dropLocationForPoint(JTextComponent textComp, Point p);
+
+        /**
+         * Called to set or clear the drop location during a DnD operation.
+         */
+        Object setDropLocation(JTextComponent textComp, TransferHandler.DropLocation location,
+                               Object state, boolean forDrop);
+    }
+
+    /**
+     * The javax.swing.text.JTextComponent class accessor object.
+     */
+    private static JTextComponentAccessor jtextComponentAccessor;
+
+    /**
+     * Set an accessor object for the javax.swing.text.JTextComponent class.
+     */
+    public static void setJTextComponentAccessor(JTextComponentAccessor jtca) {
+         jtextComponentAccessor = jtca;
+    }
+
+    /**
+     * Retrieve the accessor object for the javax.swing.text.JTextComponent class.
+     */
+    public static JTextComponentAccessor getJTextComponentAccessor() {
+        if (jtextComponentAccessor == null) {
+            unsafe.ensureClassInitialized(JTextComponent.class);
+        }
+
+        return jtextComponentAccessor;
+    }
+}
--- a/src/share/classes/sun/text/normalizer/NormalizerBase.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/classes/sun/text/normalizer/NormalizerBase.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1598,15 +1598,34 @@
      * @param options   the optional features to be enabled.
      */
     public static String normalize(String str, Normalizer.Form form, int options) {
+        int len = str.length();
+        boolean asciiOnly = true;
+        if (len < 80) {
+            for (int i = 0; i < len; i++) {
+                if (str.charAt(i) > 127) {
+                    asciiOnly = false;
+                    break;
+                }
+            }
+        } else {
+            char[] a = str.toCharArray();
+            for (int i = 0; i < len; i++) {
+                if (a[i] > 127) {
+                    asciiOnly = false;
+                    break;
+                }
+            }
+        }
+
         switch (form) {
         case NFC :
-            return NFC.normalize(str, options);
+            return asciiOnly ? str : NFC.normalize(str, options);
         case NFD :
-            return NFD.normalize(str, options);
+            return asciiOnly ? str : NFD.normalize(str, options);
         case NFKC :
-            return NFKC.normalize(str, options);
+            return asciiOnly ? str : NFKC.normalize(str, options);
         case NFKD :
-            return NFKD.normalize(str, options);
+            return asciiOnly ? str : NFKD.normalize(str, options);
         }
 
         throw new IllegalArgumentException("Unexpected normalization form: " +
--- a/src/share/demo/jfc/Font2DTest/RangeMenu.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/demo/jfc/Font2DTest/RangeMenu.java	Tue Jul 21 13:02:23 2009 -0700
@@ -53,7 +53,7 @@
 public final class RangeMenu extends JComboBox implements ActionListener {
 
     /// Painfully extracted from java.lang.Character.UnicodeBlock.  Arrrgh!
-    /// Unicode 3.0 data.
+    /// Unicode 5.1.0 data.
 
     private final int[][] UNICODE_RANGES = {
         { 0x000000, 0x00007f }, /// BASIC_LATIN
@@ -63,14 +63,16 @@
         { 0x000250, 0x0002af }, /// IPA_EXTENSIONS
         { 0x0002b0, 0x0002ff }, /// SPACING_MODIFIER_LETTERS
         { 0x000300, 0x00036f }, /// COMBINING_DIACRITICAL_MARKS
-        { 0x000370, 0x0003ff }, /// GREEK
+        { 0x000370, 0x0003ff }, /// GREEK_AND_COPTIC
         { 0x000400, 0x0004ff }, /// CYRILLIC
         { 0x000500, 0x00052f }, /// CYRILLIC_SUPPLEMENTARY
         { 0x000530, 0x00058f }, /// ARMENIAN
         { 0x000590, 0x0005ff }, /// HEBREW
         { 0x000600, 0x0006ff }, /// ARABIC
         { 0x000700, 0x00074f }, /// SYRIAC
+        { 0x000750, 0x00077f }, /// ARABIC_SUPPLEMENT
         { 0x000780, 0x0007bf }, /// THAANA
+        { 0x0007c0, 0x0007ff }, /// NKO
         { 0x000900, 0x00097f }, /// DEVANAGARI
         { 0x000980, 0x0009ff }, /// BENGALI
         { 0x000a00, 0x000a7f }, /// GURMUKHI
@@ -88,6 +90,7 @@
         { 0x0010a0, 0x0010ff }, /// GEORGIAN
         { 0x001100, 0x0011ff }, /// HANGUL_JAMO
         { 0x001200, 0x00137f }, /// ETHIOPIC
+        { 0x001380, 0x00139f }, /// ETHIOPIC_SUPPLEMENT
         { 0x0013a0, 0x0013ff }, /// CHEROKEE
         { 0x001400, 0x00167f }, /// UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
         { 0x001680, 0x00169f }, /// OGHAM
@@ -100,8 +103,16 @@
         { 0x001800, 0x0018af }, /// MONGOLIAN
         { 0x001900, 0x00194f }, /// LIMBU
         { 0x001950, 0x00197f }, /// TAI_LE
+        { 0x001980, 0x0019df }, /// NEW_TAI_LE
         { 0x0019e0, 0x0019ff }, /// KHMER_SYMBOLS
+        { 0x001a00, 0x001a1f }, /// BUGINESE
+        { 0x001b00, 0x001b7f }, /// BALINESE
+        { 0x001b80, 0x001bbf }, /// SUNDANESE
+        { 0x001c00, 0x001c4f }, /// LEPCHA
+        { 0x001c50, 0x001c7f }, /// OL_CHIKI
         { 0x001d00, 0x001d7f }, /// PHONETIC_EXTENSIONS
+        { 0x001d80, 0x001dbf }, /// PHONEITC EXTENSIONS SUPPLEMENT
+        { 0x001dc0, 0x001dff }, /// COMBINING_DIACRITICAL_MAKRS_SUPPLEMENT
         { 0x001e00, 0x001eff }, /// LATIN_EXTENDED_ADDITIONAL
         { 0x001f00, 0x001fff }, /// GREEK_EXTENDED
         { 0x002000, 0x00206f }, /// GENERAL_PUNCTUATION
@@ -128,6 +139,14 @@
         { 0x002980, 0x0029ff }, /// MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B
         { 0x002a00, 0x002aff }, /// SUPPLEMENTAL_MATHEMATICAL_OPERATORS
         { 0x002b00, 0x002bff }, /// MISCELLANEOUS_SYMBOLS_AND_ARROWS
+        { 0x002c00, 0x002c5f }, /// GLAGOLITIC
+        { 0x002c60, 0x002c7f }, /// LATIN_EXTENDED-C
+        { 0x002c80, 0x002cff }, /// COPTIC
+        { 0x002d00, 0x002d2f }, /// GEORGIAN_SUPPLEMENT
+        { 0x002d30, 0x002d7f }, /// TIFINAGH
+        { 0x002d80, 0x002ddf }, /// ETHIOPIC_EXTENDED
+        { 0x002de0, 0x002dff }, /// CYRILLIC_EXTENDED-A
+        { 0x002e00, 0x002e7f }, /// SUPPLEMENTAL_PUNCTUATION
         { 0x002e80, 0x002eff }, /// CJK_RADICALS_SUPPLEMENT
         { 0x002f00, 0x002fdf }, /// KANGXI_RADICALS
         { 0x002ff0, 0x002fff }, /// IDEOGRAPHIC_DESCRIPTION_CHARACTERS
@@ -138,6 +157,7 @@
         { 0x003130, 0x00318f }, /// HANGUL_COMPATIBILITY_JAMO
         { 0x003190, 0x00319f }, /// KANBUN
         { 0x0031a0, 0x0031bf }, /// BOPOMOFO_EXTENDED
+        { 0x0031c0, 0x0031ef }, /// CJK_STROKES
         { 0x0031f0, 0x0031ff }, /// KATAKANA_PHONETIC_EXTENSIONS
         { 0x003200, 0x0032ff }, /// ENCLOSED_CJK_LETTERS_AND_MONTHS
         { 0x003300, 0x0033ff }, /// CJK_COMPATIBILITY
@@ -146,13 +166,26 @@
         { 0x004e00, 0x009fff }, /// CJK_UNIFIED_IDEOGRAPHS
         { 0x00a000, 0x00a48f }, /// YI_SYLLABLES
         { 0x00a490, 0x00a4cf }, /// YI_RADICALS
+        { 0x00a500, 0x00a63f }, /// YAI
+        { 0x00a640, 0x00a69f }, /// CYRILLIC_EXTENDED-B
+        { 0x00a700, 0x00a71f }, /// MODIFIER_TONE_LETTERS
+        { 0x00a720, 0x00a7ff }, /// LATIN_EXTENDED-D
+        { 0x00a800, 0x00a82f }, /// SYLOTI_NAGRI
+        { 0x00a840, 0x00a87f }, /// PHAGS-PA
+        { 0x00a880, 0x00a8df }, /// SAURASHTRA
+        { 0x00a900, 0x00a92f }, /// KAYAH_LI
+        { 0x00a930, 0x00a95f }, /// REJANG
+        { 0x00aa00, 0x00aa5f }, /// CHAM
         { 0x00ac00, 0x00d7af }, /// HANGUL_SYLLABLES
-        { 0x00d800, 0x00dfff }, /// SURROGATES_AREA
+        { 0x00d800, 0x00db7f }, /// HIGH_SURROGATES_AREA
+        { 0x00db80, 0x00dbff }, /// HIGH_PRIVATE_USE_SURROGATES_AREA
+        { 0x00dc00, 0x00dfff }, /// LOW_SURROGATES_AREA
         { 0x00e000, 0x00f8ff }, /// PRIVATE_USE_AREA
         { 0x00f900, 0x00faff }, /// CJK_COMPATIBILITY_IDEOGRAPHS
         { 0x00fb00, 0x00fb4f }, /// ALPHABETIC_PRESENTATION_FORMS
         { 0x00fb50, 0x00fdff }, /// ARABIC_PRESENTATION_FORMS_A
         { 0x00fe00, 0x00fe0f }, /// VARIATION_SELECTORS
+        { 0x00fe10, 0x00fe1f }, /// VERTICAL_FORMS
         { 0x00fe20, 0x00fe2f }, /// COMBINING_HALF_MARKS
         { 0x00fe30, 0x00fe4f }, /// CJK_COMPATIBILITY_FORMS
         { 0x00fe50, 0x00fe6f }, /// SMALL_FORM_VARIANTS
@@ -162,17 +195,32 @@
         { 0x010000, 0x01007f }, /// LINEAR_B_SYLLABARY
         { 0x010080, 0x0100ff }, /// LINEAR_B_IDEOGRAMS
         { 0x010100, 0x01013f }, /// AEGEAN_NUMBERS
+        { 0x010140, 0x01018f }, /// ANCIENT_GREEK_NUMBERS
+        { 0x010190, 0x0101cf }, /// ANCIENT_SYMBOLS
+        { 0x0101d0, 0x0101ff }, /// PHAISTOS_DISC
+        { 0x010280, 0x01029f }, /// LYCIAN
+        { 0x0102a0, 0x0102df }, /// CARIAN
         { 0x010300, 0x01032f }, /// OLD_ITALIC
         { 0x010330, 0x01034f }, /// GOTHIC
         { 0x010380, 0x01039f }, /// UGARITIC
+        { 0x0103a0, 0x0103df }, /// OLD_PERSIAN
         { 0x010400, 0x01044f }, /// DESERET
         { 0x010450, 0x01047f }, /// SHAVIAN
         { 0x010480, 0x0104af }, /// OSMANYA
         { 0x010800, 0x01083f }, /// CYPRIOT_SYLLABARY
+        { 0x010900, 0x01091f }, /// PHOENICIAN
+        { 0x010920, 0x01093f }, /// LYDIAN
+        { 0x010a00, 0x010a5f }, /// KHAROSHTHI
+        { 0x012000, 0x0123ff }, /// CUNEIFORM
+        { 0x012400, 0x01247f }, /// CUNEIFORM_NUMBERS_AND_PUNCTUATION
         { 0x01d000, 0x01d0ff }, /// BYZANTINE_MUSICAL_SYMBOLS
         { 0x01d100, 0x01d1ff }, /// MUSICAL_SYMBOLS
+        { 0x01d200, 0x01d24f }, /// ANCIENT_GREEK_MUSICAL_NOTATION
         { 0x01d300, 0x01d35f }, /// TAI_XUAN_JING_SYMBOLS
+        { 0x01d360, 0x01d37f }, /// COUNTING_ROD_NUMERALS
         { 0x01d400, 0x01d7ff }, /// MATHEMATICAL_ALPHANUMERIC_SYMBOLS
+        { 0x01f000, 0x01f02f }, /// MAHJONG_TILES
+        { 0x01f030, 0x01f09f }, /// DOMINO_TILES
         { 0x020000, 0x02a6df }, /// CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
         { 0x02f800, 0x02fa1f }, /// CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT
         { 0x0e0000, 0x0e007f }, /// TAGS
@@ -190,14 +238,16 @@
         "IPA Extensions",
         "Spacing Modifier Letters",
         "Combining Diacritical Marks",
-        "Greek",
+        "Greek and Coptic",
         "Cyrillic",
         "Cyrillic Supplement",
         "Armenian",
         "Hebrew",
         "Arabic",
         "Syriac",
+        "Arabic Supplement",
         "Thaana",
+        "NKo",
         "Devanagari",
         "Bengali",
         "Gurmukhi",
@@ -215,6 +265,7 @@
         "Georgian",
         "Hangul Jamo",
         "Ethiopic",
+        "Ethiopic Supplement",
         "Cherokee",
         "Unified Canadian Aboriginal Syllabics",
         "Ogham",
@@ -227,14 +278,22 @@
         "Mongolian",
         "Limbu",
         "Tai Le",
+        "New Tai Lue",
         "Khmer Symbols",
+        "Buginese",
+        "Balinese",
+        "Sundanese",
+        "Lepcha",
+        "Ol Chiki",
         "Phonetic Extensions",
+        "Phonetic Extensions Supplement",
+        "Combining Diacritical Marks Supplement",
         "Latin Extended Additional",
         "Greek Extended",
         "General Punctuation",
         "Superscripts and Subscripts",
         "Currency Symbols",
-        "Combining Marks for Symbols",
+        "Combining Diacritical Marks for Symbols",
         "Letterlike Symbols",
         "Number Forms",
         "Arrows",
@@ -255,6 +314,14 @@
         "Miscellaneous Mathematical Symbols-B",
         "Supplemental Mathematical Operators",
         "Miscellaneous Symbols and Arrows",
+        "Glagolitic",
+        "Latin Extended-C",
+        "Coptic",
+        "Georgian Supplement",
+        "Tifinagh",
+        "Ethiopic Extended",
+        "Cyrillic Extended-A",
+        "Supplemental Punctuation",
         "CJK Radicals Supplement",
         "Kangxi Radicals",
         "Ideographic Description Characters",
@@ -265,6 +332,7 @@
         "Hangul Compatibility Jamo",
         "Kanbun",
         "Bopomofo Extended",
+        "CJK Strokes",
         "Katakana Phonetic Extensions",
         "Enclosed CJK Letters and Months",
         "CJK Compatibility",
@@ -273,13 +341,26 @@
         "CJK Unified Ideographs",
         "Yi Syllables",
         "Yi Radicals",
+        "Vai",
+        "Cyrillic Extended-B",
+        "Modifier Tone Letters",
+        "Latin Extended-D",
+        "Syloti Nagri",
+        "Phags-pa",
+        "Saurashtra",
+        "Kayah Li",
+        "Rejang",
+        "Cham",
         "Hangul Syllables",
-        "Surrogates Area", // High Surrogates, High Private Use Surrogates, Low Surrogates
+        "High Surrogates",
+        "High Private Use Surrogates",
+        "Low Surrogates",
         "Private Use Area",
         "CJK Compatibility Ideographs",
         "Alphabetic Presentation Forms",
         "Arabic Presentation Forms-A",
         "Variation Selectors",
+        "Vertical Forms",
         "Combining Half Marks",
         "CJK Compatibility Forms",
         "Small Form Variants",
@@ -289,17 +370,32 @@
         "Linear B Syllabary",
         "Linear B Ideograms",
         "Aegean Numbers",
+        "Ancient Greek Numbers",
+        "Ancient Symbols",
+        "Phaistos Disc",
+        "Lycian",
+        "Carian",
         "Old Italic",
         "Gothic",
         "Ugaritic",
+        "Old Persian",
         "Deseret",
         "Shavian",
         "Osmanya",
         "Cypriot Syllabary",
+        "Phoenician",
+        "Lydian",
+        "Kharoshthi",
+        "Cuneiform",
+        "Cuneiform Numbers and Punctuation",
         "Byzantine Musical Symbols",
         "Musical Symbols",
+        "Ancient Greek Musical Notation",
         "Tai Xuan Jing Symbols",
+        "Counting Rod Numerals",
         "Mathematical Alphanumeric Symbols",
+        "Mahjong Tiles",
+        "Domino Tiles",
         "CJK Unified Ideographs Extension B",
         "CJK Compatibility Ideographs Supplement",
         "Tags",
--- a/src/share/native/common/jni_util.c	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/native/common/jni_util.c	Tue Jul 21 13:02:23 2009 -0700
@@ -607,14 +607,6 @@
     return result;
 }
 
-enum {
-    NO_ENCODING_YET = 0,        /* "sun.jnu.encoding" not yet set */
-    NO_FAST_ENCODING,           /* Platform encoding is not fast */
-    FAST_8859_1,                /* ISO-8859-1 */
-    FAST_CP1252,                /* MS-DOS Cp1252 */
-    FAST_646_US                 /* US-ASCII : ISO646-US */
-};
-
 static int fastEncoding = NO_ENCODING_YET;
 static jstring jnuEncoding = NULL;
 
@@ -622,10 +614,14 @@
 static jmethodID String_init_ID;        /* String(byte[], enc) */
 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
 
+int getFastEncoding() {
+    return fastEncoding;
+}
+
 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
  */
-static void
+void
 initializeEncoding(JNIEnv *env)
 {
     jstring propname = 0;
@@ -719,44 +715,47 @@
 JNU_NewStringPlatform(JNIEnv *env, const char *str)
 {
     jstring result;
-    jbyteArray hab = 0;
-    int len;
+    result = nativeNewStringPlatform(env, str);
+    if (result == NULL) {
+        jbyteArray hab = 0;
+        int len;
 
-    if (fastEncoding == NO_ENCODING_YET)
-        initializeEncoding(env);
+        if (fastEncoding == NO_ENCODING_YET)
+            initializeEncoding(env);
 
-    if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
-        return newString8859_1(env, str);
-    if (fastEncoding == FAST_646_US)
-        return newString646_US(env, str);
-    if (fastEncoding == FAST_CP1252)
-        return newStringCp1252(env, str);
+        if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
+            return newString8859_1(env, str);
+        if (fastEncoding == FAST_646_US)
+            return newString646_US(env, str);
+        if (fastEncoding == FAST_CP1252)
+            return newStringCp1252(env, str);
 
-    if ((*env)->EnsureLocalCapacity(env, 2) < 0)
-        return 0;
+        if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+            return NULL;
 
-    len = (int)strlen(str);
-    hab = (*env)->NewByteArray(env, len);
-    if (hab != 0) {
-        (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
-        if (jnuEncodingSupported(env)) {
-            result = (*env)->NewObject(env, JNU_ClassString(env),
-                                       String_init_ID, hab, jnuEncoding);
-        } else {
-            /*If the encoding specified in sun.jnu.encoding is not endorsed
-              by "Charset.isSupported" we have to fall back to use String(byte[])
-              explicitly here without specifying the encoding name, in which the
-              StringCoding class will pickup the iso-8859-1 as the fallback
-              converter for us.
-             */
-            jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
-                                 "<init>", "([B)V");
-            result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
+        len = (int)strlen(str);
+        hab = (*env)->NewByteArray(env, len);
+        if (hab != 0) {
+            (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
+            if (jnuEncodingSupported(env)) {
+                result = (*env)->NewObject(env, JNU_ClassString(env),
+                                           String_init_ID, hab, jnuEncoding);
+            } else {
+                /*If the encoding specified in sun.jnu.encoding is not endorsed
+                  by "Charset.isSupported" we have to fall back to use String(byte[])
+                  explicitly here without specifying the encoding name, in which the
+                  StringCoding class will pickup the iso-8859-1 as the fallback
+                  converter for us.
+                 */
+                jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+                                                    "<init>", "([B)V");
+                result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
+            }
+            (*env)->DeleteLocalRef(env, hab);
+            return result;
         }
-        (*env)->DeleteLocalRef(env, hab);
-        return result;
     }
-    return 0;
+    return NULL;
 }
 
 JNIEXPORT const char *
@@ -768,46 +767,49 @@
 JNIEXPORT const char * JNICALL
 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 {
-    jbyteArray hab = 0;
-    char *result = 0;
+    char *result = nativeGetStringPlatformChars(env, jstr, isCopy);
+    if (result == NULL) {
 
-    if (isCopy)
-        *isCopy = JNI_TRUE;
+        jbyteArray hab = 0;
 
-    if (fastEncoding == NO_ENCODING_YET)
-        initializeEncoding(env);
+        if (isCopy)
+            *isCopy = JNI_TRUE;
 
-    if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
-        return getString8859_1Chars(env, jstr);
-    if (fastEncoding == FAST_646_US)
-        return getString646_USChars(env, jstr);
-    if (fastEncoding == FAST_CP1252)
-        return getStringCp1252Chars(env, jstr);
+        if (fastEncoding == NO_ENCODING_YET)
+            initializeEncoding(env);
 
-    if ((*env)->EnsureLocalCapacity(env, 2) < 0)
-        return 0;
+        if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
+            return getString8859_1Chars(env, jstr);
+        if (fastEncoding == FAST_646_US)
+            return getString646_USChars(env, jstr);
+        if (fastEncoding == FAST_CP1252)
+            return getStringCp1252Chars(env, jstr);
 
-    if (jnuEncodingSupported(env)) {
-        hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
-    } else {
-        jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
-                                            "getBytes", "()[B");
-        hab = (*env)->CallObjectMethod(env, jstr, mid);
+        if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+            return 0;
+
+        if (jnuEncodingSupported(env)) {
+            hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
+        } else {
+            jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+                                                "getBytes", "()[B");
+            hab = (*env)->CallObjectMethod(env, jstr, mid);
+        }
+
+        if (!(*env)->ExceptionCheck(env)) {
+            jint len = (*env)->GetArrayLength(env, hab);
+            result = MALLOC_MIN4(len);
+            if (result == 0) {
+                JNU_ThrowOutOfMemoryError(env, 0);
+                (*env)->DeleteLocalRef(env, hab);
+                return 0;
+            }
+            (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
+            result[len] = 0; /* NULL-terminate */
+        }
+
+        (*env)->DeleteLocalRef(env, hab);
     }
-
-    if (!(*env)->ExceptionCheck(env)) {
-        jint len = (*env)->GetArrayLength(env, hab);
-        result = MALLOC_MIN4(len);
-        if (result == 0) {
-            JNU_ThrowOutOfMemoryError(env, 0);
-            (*env)->DeleteLocalRef(env, hab);
-            return 0;
-        }
-        (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
-        result[len] = 0; /* NULL-terminate */
-    }
-
-    (*env)->DeleteLocalRef(env, hab);
     return result;
 }
 
--- a/src/share/native/common/jni_util.h	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/native/common/jni_util.h	Tue Jul 21 13:02:23 2009 -0700
@@ -320,6 +320,26 @@
 #define JNU_SetLongFieldFromPtr(env,obj,id,val) \
     (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val))
 
+/*
+ * Internal use only.
+ */
+enum {
+    NO_ENCODING_YET = 0,        /* "sun.jnu.encoding" not yet set */
+    NO_FAST_ENCODING,           /* Platform encoding is not fast */
+    FAST_8859_1,                /* ISO-8859-1 */
+    FAST_CP1252,                /* MS-DOS Cp1252 */
+    FAST_646_US                 /* US-ASCII : ISO646-US */
+};
+
+jstring nativeNewStringPlatform(JNIEnv *env, const char *str);
+
+char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+int getFastEncoding();
+
+void initializeEncoding();
+
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
--- a/src/share/native/sun/misc/VM.c	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/share/native/sun/misc/VM.c	Tue Jul 21 13:02:23 2009 -0700
@@ -109,11 +109,39 @@
     get_thread_state_info(env, JAVA_THREAD_STATE_TERMINATED, values, names);
 }
 
+typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t);
+
 JNIEXPORT void JNICALL
 Java_sun_misc_VM_initialize(JNIEnv *env, jclass cls) {
     char errmsg[128];
+    GetJvmVersionInfo_fp func_p;
 
     if (!JDK_InitJvmHandle()) {
         JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup");
+        return;
+    }
+
+    func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo");
+     if (func_p != NULL) {
+        char errmsg[100];
+        jfieldID fid;
+        jvm_version_info info;
+
+        memset(&info, 0, sizeof(info));
+
+        /* obtain the JVM version info */
+        (*func_p)(env, &info, sizeof(info));
+
+        if (info.is_kernel_jvm == 1) {
+            /* set the static field VM.kernelVM to true for kernel VM */
+            fid = (*env)->GetStaticFieldID(env, cls, "kernelVM", "Z");
+            if (fid != 0) {
+                (*env)->SetStaticBooleanField(env, cls, fid, info.is_kernel_jvm);
+            } else {
+                sprintf(errmsg, "Static kernelVM boolean field not found");
+                JNU_ThrowInternalError(env, errmsg);
+            }
+        }
     }
 }
+
--- a/src/solaris/classes/sun/awt/X11/XKeysym.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/solaris/classes/sun/awt/X11/XKeysym.java	Tue Jul 21 13:02:23 2009 -0700
@@ -145,7 +145,7 @@
     {
         // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
         // Otherwise, it is [1].
-        int ndx = XToolkit.isXsunServer() &&
+        int ndx = XToolkit.isXsunKPBehavior() &&
                   ! XToolkit.isXKBenabled() ? 2 : 1;
         // Even if XKB is enabled, we have another problem: some symbol tables (e.g. cz) force
         // a regular comma instead of KP_comma for a decimal separator. Result is,
@@ -193,7 +193,7 @@
     private static long getKeypadKeysym( XKeyEvent ev ) {
         int ndx = 0;
         long keysym = XConstants.NoSymbol;
-        if( XToolkit.isXsunServer() &&
+        if( XToolkit.isXsunKPBehavior() &&
             ! XToolkit.isXKBenabled() ) {
             if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on
                 ndx = 3;
--- a/src/solaris/classes/sun/awt/X11/XToolkit.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/solaris/classes/sun/awt/X11/XToolkit.java	Tue Jul 21 13:02:23 2009 -0700
@@ -1177,6 +1177,7 @@
         awtLock();
         try {
             XlibWrapper.XBell(getDisplay(), 0);
+            XlibWrapper.XFlush(getDisplay());
         } finally {
             awtUnlock();
         }
@@ -1435,9 +1436,14 @@
         return timeStamp;
     }
     protected void initializeDesktopProperties() {
-        desktopProperties.put("DnD.Autoscroll.initialDelay",     Integer.valueOf(50));
-        desktopProperties.put("DnD.Autoscroll.interval",         Integer.valueOf(50));
-        desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5));
+        desktopProperties.put("DnD.Autoscroll.initialDelay",
+                              Integer.valueOf(50));
+        desktopProperties.put("DnD.Autoscroll.interval",
+                              Integer.valueOf(50));
+        desktopProperties.put("DnD.Autoscroll.cursorHysteresis",
+                              Integer.valueOf(5));
+        desktopProperties.put("Shell.shellFolderManager",
+                              "sun.awt.shell.ShellFolderManager");
         // Don't want to call getMultiClickTime() if we are headless
         if (!GraphicsEnvironment.isHeadless()) {
             desktopProperties.put("awt.multiClickInterval",
@@ -2124,39 +2130,33 @@
      */
     private static int backingStoreType;
 
-    static boolean awt_ServerInquired = false;
-    static boolean awt_IsXsunServer    = false;
+    static final int XSUN_KP_BEHAVIOR = 1;
+    static final int XORG_KP_BEHAVIOR = 2;
+
+    static int     awt_IsXsunKPBehavior = 0;
     static boolean awt_UseXKB         = false;
     static boolean awt_UseXKB_Calls   = false;
     static int     awt_XKBBaseEventCode = 0;
     static int     awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations
                                               // to XkbTranslateKeyCode
     static long    awt_XKBDescPtr     = 0;
+
     /**
-       Try to understand if it is Xsun server.
-       By now (2005) Sun is vendor of Xsun and Xorg servers; we only return true if Xsun is running.
-    */
-    static boolean isXsunServer() {
+     * Check for Xsun convention regarding numpad keys.
+     * Xsun and some other servers (i.e. derived from Xsun)
+     * under certain conditions process numpad keys unlike Xorg.
+     */
+    static boolean isXsunKPBehavior() {
         awtLock();
         try {
-            if( awt_ServerInquired ) {
-                return awt_IsXsunServer;
+            if( awt_IsXsunKPBehavior == 0 ) {
+                if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) {
+                    awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR;
+                }else{
+                    awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR;
+                }
             }
-            if( ! XlibWrapper.ServerVendor(getDisplay()).startsWith("Sun Microsystems") ) {
-                awt_ServerInquired = true;
-                awt_IsXsunServer = false;
-                return false;
-            }
-            // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86.
-            // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun.
-            if( XlibWrapper.VendorRelease(getDisplay()) > 10000 ) {
-                awt_ServerInquired = true;
-                awt_IsXsunServer = false;
-                return false;
-            }
-            awt_ServerInquired = true;
-            awt_IsXsunServer = true;
-            return true;
+            return awt_IsXsunKPBehavior == XSUN_KP_BEHAVIOR ? true : false;
         } finally {
             awtUnlock();
         }
--- a/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Tue Jul 21 13:02:23 2009 -0700
@@ -352,6 +352,7 @@
     static native int XIconifyWindow(long display, long window, long screenNumber);
     static native String ServerVendor(long display);
     static native int VendorRelease(long display);
+    static native boolean IsXsunKPBehavior(long display);
 
     static native void XBell(long display, int percent);
 
--- a/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Tue Jul 21 13:02:23 2009 -0700
@@ -183,7 +183,7 @@
 tojava     {
 tojava         // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
 tojava         // Otherwise, it is [1].
-tojava         int ndx = XToolkit.isXsunServer() &&
+tojava         int ndx = XToolkit.isXsunKPBehavior() &&
 tojava                   ! XToolkit.isXKBenabled() ? 2 : 1;
 tojava         // Even if XKB is enabled, we have another problem: some symbol tables (e.g. cz) force
 tojava         // a regular comma instead of KP_comma for a decimal separator. Result is,
@@ -231,7 +231,7 @@
 tojava     private static long getKeypadKeysym( XKeyEvent ev ) {
 tojava         int ndx = 0;
 tojava         long keysym = XConstants.NoSymbol;
-tojava         if( XToolkit.isXsunServer() &&
+tojava         if( XToolkit.isXsunKPBehavior() &&
 tojava             ! XToolkit.isXKBenabled() ) {
 tojava             if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on
 tojava                 ndx = 3;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/native/common/jni_util_md.c	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+
+jstring nativeNewStringPlatform(JNIEnv *env, const char *str) {
+    return NULL;
+}
+
+char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) {
+    return NULL;
+}
--- a/src/solaris/native/sun/xawt/XlibWrapper.c	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/solaris/native/sun/xawt/XlibWrapper.c	Tue Jul 21 13:02:23 2009 -0700
@@ -1181,6 +1181,38 @@
     AWT_CHECK_HAVE_LOCK();
     return VendorRelease((Display*)jlong_to_ptr(display));
 }
+/*
+ * Class:     sun_awt_X11_XlibWrapper
+ * Method:    IsXsunKPBehavior
+ * Signature: (J)Z;
+ */
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior
+(JNIEnv *env, jclass clazz, jlong display)
+{
+    // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
+    // Otherwise, it is [1] or sometimes [0].
+    // This sniffer first tries to determine what is a keycode for XK_KP_7
+    // using XKeysymToKeycode;
+    // second, in which place in the keysymarray is XK_KP_7
+    // using XKeycodeToKeysym.
+    int kc7;
+    AWT_CHECK_HAVE_LOCK();
+    kc7 = XKeysymToKeycode((Display*)jlong_to_ptr(display), XK_KP_7);
+    if( !kc7 ) {
+        // keycode is not defined. Why, it's a reduced keyboard perhaps:
+        // report arbitrarily false.
+        return JNI_FALSE;
+    } else {
+        long ks2 = XKeycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2);
+        if( ks2 == XK_KP_7 ) {
+            //XXX If some Xorg server would put XK_KP_7 in keysymarray[2] as well,
+            //XXX for yet unknown to me reason, the sniffer would lie.
+            return JNI_TRUE;
+        }else{
+            return JNI_FALSE;
+        }
+    }
+}
 
 JavaVM* jvm = NULL;
 static int ToolkitErrorHandler(Display * dpy, XErrorEvent * event) {
--- a/src/windows/bin/java_md.c	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/bin/java_md.c	Tue Jul 21 13:02:23 2009 -0700
@@ -49,6 +49,7 @@
 static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
                            char *jvmpath, jint jvmpathsize);
 static jboolean GetJREPath(char *path, jint pathsize);
+static void EnsureJreInstallation(const char *jrepath);
 
 static jboolean _isjavaw = JNI_FALSE;
 
@@ -108,6 +109,9 @@
         exit(1);
     }
 
+    /* Do this before we read jvm.cfg */
+    EnsureJreInstallation(jrepath);
+
     /* Find out where the JRE is that we will be using. */
     if (!GetJREPath(jrepath, so_jrepath)) {
         JLI_ReportErrorMessage(JRE_ERROR1);
@@ -130,6 +134,103 @@
 
 }
 
+
+static jboolean
+LoadMSVCRT()
+{
+    // Only do this once
+    static int loaded = 0;
+    char crtpath[MAXPATHLEN];
+
+    if (!loaded) {
+        /*
+         * The Microsoft C Runtime Library needs to be loaded first.  A copy is
+         * assumed to be present in the "JRE path" directory.  If it is not found
+         * there (or "JRE path" fails to resolve), skip the explicit load and let
+         * nature take its course, which is likely to be a failure to execute.
+         */
+#ifdef _MSC_VER
+#if _MSC_VER < 1400
+#define CRT_DLL "msvcr71.dll"
+#endif
+#ifdef CRT_DLL
+        if (GetJREPath(crtpath, MAXPATHLEN)) {
+            (void)JLI_StrCat(crtpath, "\\bin\\" CRT_DLL);   /* Add crt dll */
+            JLI_TraceLauncher("CRT path is %s\n", crtpath);
+            if (_access(crtpath, 0) == 0) {
+                if (LoadLibrary(crtpath) == 0) {
+                    JLI_ReportErrorMessage(DLL_ERROR4, crtpath);
+                    return JNI_FALSE;
+                }
+            }
+        }
+#endif /* CRT_DLL */
+#endif /* _MSC_VER */
+        loaded = 1;
+    }
+    return JNI_TRUE;
+}
+
+/*
+ * The preJVMStart is a function in the jkernel.dll, which
+ * performs the final step of synthesizing back the decomposed
+ * modules  (partial install) to the full JRE. Any tool which
+ * uses the  JRE must peform this step to ensure the complete synthesis.
+ * The EnsureJreInstallation function calls preJVMStart based on
+ * the conditions outlined below, noting that the operation
+ * will fail silently if any of conditions are not met.
+ * NOTE: this call must be made before jvm.dll is loaded, or jvm.cfg
+ * is read, since jvm.cfg will be modified by the preJVMStart.
+ * 1. Are we on a supported platform.
+ * 2. Find the location of the JRE or the Kernel JRE.
+ * 3. check existence of JREHOME/lib/bundles
+ * 4. check jkernel.dll and invoke the entry-point
+ */
+typedef VOID (WINAPI *PREJVMSTART)();
+
+static void
+EnsureJreInstallation(const char* jrepath)
+{
+    HINSTANCE handle;
+    char tmpbuf[MAXPATHLEN];
+    PREJVMSTART PreJVMStart;
+    struct stat s;
+
+    /* 32 bit windows only please */
+    if (strcmp(GetArch(), "i386") != 0 ) {
+        return;
+    }
+    /* Does our bundle directory exist ? */
+    strcpy(tmpbuf, jrepath);
+    strcat(tmpbuf, "\\lib\\bundles");
+    if (stat(tmpbuf, &s) != 0) {
+        return;
+    }
+    /* Does our jkernel dll exist ? */
+    strcpy(tmpbuf, jrepath);
+    strcat(tmpbuf, "\\bin\\jkernel.dll");
+    if (stat(tmpbuf, &s) != 0) {
+        return;
+    }
+    /* The Microsoft C Runtime Library needs to be loaded first. */
+    if (!LoadMSVCRT()) {
+        return;
+    }
+    /* Load the jkernel.dll */
+    if ((handle = LoadLibrary(tmpbuf)) == 0) {
+        return;
+    }
+    /* Get the function address */
+    PreJVMStart = (PREJVMSTART)GetProcAddress(handle, "preJVMStart");
+    if (PreJVMStart == NULL) {
+        FreeLibrary(handle);
+        return;
+    }
+    PreJVMStart();
+    FreeLibrary(handle);
+    return;
+}
+
 /*
  * Find path to JRE based on .exe's location or registry settings.
  */
@@ -196,7 +297,6 @@
 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
 {
     HINSTANCE handle;
-    char crtpath[MAXPATHLEN];
 
     JLI_TraceLauncher("JVM path is %s\n", jvmpath);
 
@@ -206,26 +306,8 @@
      * there (or "JRE path" fails to resolve), skip the explicit load and let
      * nature take its course, which is likely to be a failure to execute.
      *
-     * (NOTE: the above statement is only true for Visual Studio 2003 and
-     *  msvcr71.dll.)
      */
-#ifdef _MSC_VER
-#if _MSC_VER < 1400
-#define CRT_DLL "msvcr71.dll"
-#endif
-#ifdef CRT_DLL
-    if (GetJREPath(crtpath, MAXPATHLEN)) {
-        (void)JLI_StrCat(crtpath, "\\bin\\" CRT_DLL);   /* Add crt dll */
-        JLI_TraceLauncher("CRT path is %s\n", crtpath);
-        if (_access(crtpath, 0) == 0) {
-            if (LoadLibrary(crtpath) == 0) {
-                JLI_ReportErrorMessage(DLL_ERROR4, crtpath);
-                return JNI_FALSE;
-            }
-        }
-    }
-#endif /* CRT_DLL */
-#endif /* _MSC_VER */
+    LoadMSVCRT();
 
     /* Load the Java VM DLL */
     if ((handle = LoadLibrary(jvmpath)) == 0) {
--- a/src/windows/classes/sun/awt/windows/WComponentPeer.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java	Tue Jul 21 13:02:23 2009 -0700
@@ -417,6 +417,15 @@
         replaceSurfaceData(this.numBackBuffers, this.backBufferCaps);
     }
 
+    public void createScreenSurface(boolean isResize)
+    {
+        Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration();
+        ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
+
+        surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize);
+    }
+
+
     /**
      * Multi-buffer version of replaceSurfaceData.  This version is called
      * by createBuffers(), which needs to acquire the same locks in the same
@@ -434,13 +443,10 @@
                     return;
                 }
                 numBackBuffers = newNumBackBuffers;
-                Win32GraphicsConfig gc =
-                        (Win32GraphicsConfig)getGraphicsConfiguration();
                 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
                 oldData = surfaceData;
                 mgr.dropScreenSurface(oldData);
-                surfaceData =
-                    mgr.createScreenSurface(gc, this, numBackBuffers, true);
+                createScreenSurface(true);
                 if (oldData != null) {
                     oldData.invalidate();
                 }
@@ -449,6 +455,8 @@
                 if (numBackBuffers > 0) {
                     // set the caps first, they're used when creating the bb
                     backBufferCaps = caps;
+                    Win32GraphicsConfig gc =
+                        (Win32GraphicsConfig)getGraphicsConfiguration();
                     backBuffer = gc.createBackBuffer(this);
                 } else if (backBuffer != null) {
                     backBufferCaps = null;
@@ -711,11 +719,8 @@
         create(parentPeer);
         // fix for 5088782: check if window object is created successfully
         checkCreation();
-        this.winGraphicsConfig =
-            (Win32GraphicsConfig)getGraphicsConfiguration();
-        ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
-        this.surfaceData = mgr.createScreenSurface(winGraphicsConfig, this,
-                                                   numBackBuffers, false);
+
+        createScreenSurface(false);
         initialize();
         start();  // Initialize enable/disable state, turn on callbacks
     }
--- a/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Tue Jul 21 13:02:23 2009 -0700
@@ -211,9 +211,10 @@
      */
     public void notifyModalBlocked(Dialog blocker, boolean blocked) {
         try {
-            notifyModalBlockedImpl((WEmbeddedFramePeer)ComponentAccessor.getPeer(this),
-                                   (WWindowPeer)ComponentAccessor.getPeer(blocker),
-                                   blocked);
+            ComponentPeer thisPeer = (ComponentPeer)WToolkit.targetToPeer(this);
+            ComponentPeer blockerPeer = (ComponentPeer)WToolkit.targetToPeer(blocker);
+            notifyModalBlockedImpl((WEmbeddedFramePeer)thisPeer,
+                                   (WWindowPeer)blockerPeer, blocked);
         } catch (Exception z) {
             z.printStackTrace(System.err);
         }
--- a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java	Tue Jul 21 13:02:23 2009 -0700
@@ -237,4 +237,11 @@
     public void setOpacity(float opacity) {}
     public void setOpaque(boolean isOpaque) {}
     public void updateWindow(java.awt.image.BufferedImage backBuffer) {}
+
+    // the file/print dialogs are native dialogs and
+    // the native system does their own rendering
+    @Override
+    public void createScreenSurface(boolean isResize) {}
+    @Override
+    public void replaceSurfaceData() {}
 }
--- a/src/windows/classes/sun/awt/windows/WPopupMenuPeer.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/awt/windows/WPopupMenuPeer.java	Tue Jul 21 13:02:23 2009 -0700
@@ -29,33 +29,25 @@
 import java.lang.reflect.Field;
 
 import sun.awt.SunToolkit;
+import sun.awt.AWTAccessor;
 
 public class WPopupMenuPeer extends WMenuPeer implements PopupMenuPeer {
     // We can't use target.getParent() for TrayIcon popup
     // because this method should return null for the TrayIcon
     // popup regardless of that whether it has parent or not.
-    private static Field f_parent;
-    private static Field f_isTrayIconPopup;
-
-    static {
-        f_parent = SunToolkit.getField(MenuComponent.class, "parent");
-        f_isTrayIconPopup = SunToolkit.getField(PopupMenu.class, "isTrayIconPopup");
-    }
 
     public WPopupMenuPeer(PopupMenu target) {
         this.target = target;
         MenuContainer parent = null;
-        boolean isTrayIconPopup = false;
-        try {
-            isTrayIconPopup = ((Boolean)f_isTrayIconPopup.get(target)).booleanValue();
-            if (isTrayIconPopup) {
-                parent = (MenuContainer)f_parent.get(target);
-            } else {
-                parent = target.getParent();
-            }
-        } catch (IllegalAccessException iae) {
-            iae.printStackTrace();
-            return;
+
+        // We can't use target.getParent() for TrayIcon popup
+        // because this method should return null for the TrayIcon
+        // popup regardless of that whether it has parent or not.
+        boolean isTrayIconPopup = AWTAccessor.getPopupMenuAccessor().isTrayIconPopup(target);
+        if (isTrayIconPopup) {
+            parent = AWTAccessor.getMenuComponentAccessor().getParent(target);
+        } else {
+            parent = target.getParent();
         }
 
         if (parent instanceof Component) {
--- a/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Tue Jul 21 13:02:23 2009 -0700
@@ -150,4 +150,11 @@
     public void setOpacity(float opacity) {}
     public void setOpaque(boolean isOpaque) {}
     public void updateWindow(java.awt.image.BufferedImage backBuffer) {}
+
+    // the file/print dialogs are native dialogs and
+    // the native system does their own rendering
+    @Override
+    public void createScreenSurface(boolean isResize) {}
+    @Override
+    public void replaceSurfaceData() {}
 }
--- a/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java	Wed Jul 15 10:46:42 2009 -0700
+++ b/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java	Tue Jul 21 13:02:23 2009 -0700
@@ -38,8 +38,6 @@
 import sun.awt.Win32GraphicsConfig;
 import sun.awt.Win32GraphicsDevice;
 import sun.awt.windows.WComponentPeer;
-import sun.awt.windows.WFileDialogPeer;
-import sun.awt.windows.WPrintDialogPeer;
 import sun.java2d.ScreenUpdateManager;
 import sun.java2d.SunGraphics2D;
 import sun.java2d.SurfaceData;
@@ -264,17 +262,7 @@
         this.graphicsConfig =
             (Win32GraphicsConfig) peer.getGraphicsConfiguration();
         this.solidloops = graphicsConfig.getSolidLoops(sType);
-        if (peer instanceof WFileDialogPeer ||
-            peer instanceof WPrintDialogPeer )
-        {
-            // REMIND: Awful hack.  The right fix for this problem
-            // would be for these type of Peers to not even use a
-            // GDIWindowSurfaceData object since they never do any
-            // rendering.  Or they could actually implement the
-            // functionality needed in initOps.  But this seems
-            // to work for now.  See bug 4391928 for more info.
-            return;
-        }
+
         Win32GraphicsDevice gd =
             (Win32GraphicsDevice)graphicsConfig.getDevice();
         initOps(peer, depth, rMask, gMask, bMask, gd.getScreen());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/windows/native/common/jni_util_md.c	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2004 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <locale.h>
+
+#include "jni.h"
+#include "jni_util.h"
+
+static void getParent(const TCHAR *path, TCHAR *dest) {
+    char* lastSlash = max(strrchr(path, '\\'), strrchr(path, '/'));
+    if (lastSlash == NULL) {
+        *dest = 0;
+        return;
+    }
+    if (path != dest)
+        strcpy(dest, path);
+    *lastSlash = 0;
+}
+
+BOOL useNativeConverter(JNIEnv *env) {
+    static BOOL initialized;
+    static BOOL useNative;
+    if (!initialized) {
+        HMODULE jvm = GetModuleHandle("jvm");
+        useNative = FALSE;
+        if (jvm != NULL) {
+            TCHAR *jvmPath = NULL;
+            int bufferSize = MAX_PATH;
+            while (jvmPath == NULL) {
+                DWORD result;
+                jvmPath = malloc(bufferSize);
+                if (jvmPath == NULL)
+                    return FALSE;
+                result = GetModuleFileName(jvm, jvmPath, bufferSize);
+                if (result == 0)
+                    return FALSE;
+                if (result == bufferSize) { // didn't fit
+                    bufferSize += MAX_PATH; // increase buffer size, try again
+                    free(jvmPath);
+                    jvmPath = NULL;
+                }
+            }
+
+            getParent(jvmPath, jvmPath);
+            useNative = (!strcmp("kernel", jvmPath + strlen(jvmPath) -
+                    strlen("kernel"))); // true if jvm.dll lives in "kernel"
+            if (useNative)
+                setlocale(LC_ALL, "");
+            free(jvmPath);
+        }
+        initialized = TRUE;
+    }
+    return useNative;
+}
+
+jstring nativeNewStringPlatform(JNIEnv *env, const char *str) {
+    static String_char_constructor = NULL;
+    if (useNativeConverter(env)) {
+        // use native Unicode conversion so Kernel isn't required during
+        // System.initProperties
+        jcharArray chars = 0;
+        wchar_t *utf16;
+        int len;
+        jstring result = NULL;
+
+        if (getFastEncoding() == NO_ENCODING_YET)
+            initializeEncoding(env);
+
+        len = mbstowcs(NULL, str, strlen(str));
+        if (len == -1)
+            return NULL;
+        utf16 = calloc(len + 1, 2);
+        if (mbstowcs(utf16, str, len) == -1)
+            return NULL;
+        chars = (*env)->NewCharArray(env, len);
+        if (chars == NULL)
+            return NULL;
+        (*env)->SetCharArrayRegion(env, chars, 0, len, utf16);
+        if (String_char_constructor == NULL)
+            String_char_constructor = (*env)->GetMethodID(env,
+                    JNU_ClassString(env), "<init>", "([C)V");
+        result = (*env)->NewObject(env, JNU_ClassString(env),
+                String_char_constructor, chars);
+        free(utf16);
+        return result;
+    }
+    else
+        return NULL;
+}
+
+
+char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) {
+    if (useNativeConverter(env)) {
+        // use native Unicode conversion so Kernel isn't required during
+        // System.initProperties
+        char *result = NULL;
+        size_t len;
+        const jchar* utf16 = (*env)->GetStringChars(env, jstr, NULL);
+        len = wcstombs(NULL, utf16, (*env)->GetStringLength(env, jstr) * 4) + 1;
+        if (len == -1)
+            return NULL;
+        result = (char*) malloc(len);
+        if (result != NULL) {
+            if (wcstombs(result, utf16, len) == -1)
+                return NULL;
+            (*env)->ReleaseStringChars(env, jstr, utf16);
+            if (isCopy)
+                *isCopy = JNI_TRUE;
+        }
+        return result;
+    }
+    else
+        return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/windows/native/sun/jkernel/DownloadDialog.cpp	Tue Jul 21 13:02:23 2009 -0700
@@ -0,0 +1,891 @@
+/*
+ * Copyright 2008 - 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define STRICT
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#define _ATL_APARTMENT_THREADED
+
+#include <atlbase.h>
+//You may derive a class from CComModule and use it if you want to override
+//something, but do not change the name of _Module
+extern CComModule _Module;
+#include <atlcom.h>
+#include <atlwin.h>
+
+#include <atlhost.h>
+#include <commdlg.h>
+#include <commctrl.h>
+#include <windowsx.h>
+#include <urlmon.h>
+#include <wininet.h>
+#include <shellapi.h>
+#include <time.h>
+#include <math.h>
+#include <stdio.h>
+#include <jni.h>
+
+#include "DownloadDialog.h"
+
+#define UPDATE_INTERVAL 500
+#define INITIAL_DELAY 2000
+#define POST_DELAY 1000
+
+/////////////////////////////////////////////////////////////////////////////
+// CDownloadDialog
+
+typedef BOOL (WINAPI * InitCommonControlsType)();
+
+CDownloadDialog::CDownloadDialog()
+{
+    m_numDownloadThreadsRunning = 0;
+
+    m_destroyWindowTimerStarted = FALSE;
+    m_pszFileName = NULL;
+    m_jvm = NULL;
+
+    m_ulProgress = 0;
+    m_ulProgressMax = 0;
+    m_iProgressFactor = 0;
+    m_iMaxProgressFactor = 1;
+
+
+    m_hCancelEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_hDownloadThreadExitEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_hDialogInitializedEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+
+    // Load up commctrl.dll
+    // Loading dll dynamically we can use latest available version
+    // (i.e. latest native components and extended API)
+    HMODULE hModComCtl32 = ::LoadLibrary(TEXT("comctl32.dll"));
+    if (hModComCtl32 != NULL) {
+        /* Initialize controls to ensure proper appearance */
+        InitCommonControlsType fn_InitCommonControls = (InitCommonControlsType)
+            ::GetProcAddress(hModComCtl32, "InitCommonControls");
+        fn_InitCommonControls();
+
+        /* MessageBox replacement introduced in Vista */
+        taskDialogFn = (TaskDialogIndirectFn)
+            ::GetProcAddress(hModComCtl32, "TaskDialogIndirect");
+    }
+}
+
+
+CDownloadDialog::~CDownloadDialog()
+{
+    ::CloseHandle(m_hCancelEvent);
+    ::CloseHandle(m_hDownloadThreadExitEvent);
+    ::CloseHandle(m_hDialogInitializedEvent);
+}
+
+void CDownloadDialog::addToTotalContentLength(DWORD contentLength) {
+     __try
+    {
+        m_csDownload.Lock();
+        if (m_ulProgressMax == 0) {
+            // first download this session, initialize start time
+            time(&m_startTime);
+        }
+
+        m_ulProgressMax = m_ulProgressMax + contentLength;
+        logProgress();
+    }
+    __finally
+    {
+        m_csDownload.Unlock();
+    }
+}
+
+
+
+void CDownloadDialog::initDialogText(LPCTSTR downloadURL, LPCTSTR bundleName) {
+
+    // reset status text
+    HWND hStatusWnd = GetDlgItem(IDC_TIME_REMAINING);
+    ::SetWindowText(hStatusWnd, "");
+
+    // reset progress bar
+    HWND hProgressWnd = GetDlgItem(IDC_DOWNLOAD_PROGRESS);
+
+    ::PostMessage(hProgressWnd, PBM_SETPOS, (WPARAM) 0, NULL);
+
+    m_hMastheadFont = NULL;
+    m_hDialogFont = NULL;
+    m_hSixPointFont = NULL;
+
+    m_hMemDC = NULL;
+
+    TCHAR szDownloadText[BUFFER_SIZE];
+
+    HWND hWndDownloadText = GetDlgItem(IDC_DOWNLOAD_TEXT);
+    ::LoadString(_Module.GetModuleInstance(), IDS_DOWNLOAD_TEXT, szDownloadText, BUFFER_SIZE);
+    ::SetWindowText(hWndDownloadText, szDownloadText);
+
+    TCHAR szMasthead[BUFFER_SIZE];
+
+    HWND hWndMastheadText = GetDlgItem(IDC_MASTHEAD_TEXT);
+    ::LoadString(_Module.GetModuleInstance(), IDS_DOWNLOAD, szMasthead, BUFFER_SIZE);
+    ::SetWindowText(hWndMastheadText, szMasthead);
+
+
+}
+
+BOOL CDownloadDialog::isDownloading() {
+    return m_numDownloadThreadsRunning > 0;
+}
+
+
+void CDownloadDialog::bundleInstallStart() {
+    __try
+    {
+        m_csNumDownloadThreads.Lock();
+        m_numDownloadThreadsRunning++;
+        // another download request has came in, kill the destroyWindowTimer
+        KillTimer(destroyWindowTimerID);
+        m_destroyWindowTimerStarted = FALSE;
+    }
+    __finally
+    {
+        m_csNumDownloadThreads.Unlock();
+    }
+}
+
+void CDownloadDialog::bundleInstallComplete() {
+    __try
+    {
+        m_csNumDownloadThreads.Lock();
+        m_numDownloadThreadsRunning = max(m_numDownloadThreadsRunning - 1, 0);
+        if (m_numDownloadThreadsRunning == 0) {
+            m_ulProgress = m_ulProgressMax;
+            logProgress();
+        }
+        // Signal main thread
+        ::SetEvent(m_hDownloadThreadExitEvent);
+    }
+    __finally
+    {
+        m_csNumDownloadThreads.Unlock();
+    }
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnInitDialog
+//=--------------------------------------------------------------------------=
+// Message handler for WM_INITDIALOG
+//
+// Parameters:
+//      uMsg        Windows Message
+//      wParam      WPARAM
+//      lParam      LPARAM
+//      bHandled    FALSE if not handled
+//
+// Output:
+//      LRESULT
+//
+// Notes:
+//
+LRESULT CDownloadDialog::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+     __try
+    {
+        m_csDownload.Lock();
+    }
+    __finally
+    {
+        m_csDownload.Unlock();
+    }
+    // Set timer
+    SetTimer(iTimerID, UPDATE_INTERVAL);
+
+    m_hMastheadFont = NULL;
+    m_hDialogFont = NULL;
+    m_hSixPointFont = NULL;
+    m_feedbackOnCancel = TRUE;
+
+    m_hMemDC = NULL;
+
+    TCHAR szDownloadText[BUFFER_SIZE];
+
+    HWND hWndDownloadText = GetDlgItem(IDC_DOWNLOAD_TEXT);
+    ::LoadString(_Module.GetModuleInstance(), IDS_DOWNLOAD_TEXT, szDownloadText, BUFFER_SIZE);
+    ::SetWindowText(hWndDownloadText, szDownloadText);
+
+    TCHAR szMasthead[BUFFER_SIZE];
+
+    HWND hWndMastheadText = GetDlgItem(IDC_MASTHEAD_TEXT);
+    ::LoadString(_Module.GetModuleInstance(), IDS_DOWNLOAD, szMasthead, BUFFER_SIZE);
+    ::SetWindowText(hWndMastheadText, szMasthead);
+
+    HICON javaCupIcon = ::LoadIcon(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_JAVA));
+    SetIcon(javaCupIcon, FALSE);
+
+    ::SetEvent(m_hDialogInitializedEvent);
+
+    return 0;  // do not set initial focus to cancel button
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnOK
+//=--------------------------------------------------------------------------=
+// Message handler for WM_COMMAND with IDOK
+//
+// Parameters:
+//      wNotifyCode Notify Code
+//      wID         ID of control
+//      hWndCtl     HWND of control
+//      bHandled    FALSE if not handled
+//
+// Output:
+//      LRESULT
+//
+// Notes:
+//
+LRESULT CDownloadDialog::OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+    // do nothing for now
+    return 0;
+}
+
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnCancel
+//=--------------------------------------------------------------------------=
+// Message handler for WM_COMMAND with IDCANCEL
+//
+// Parameters:
+//      wNotifyCode Notify Code
+//      wID         ID of control
+//      hWndCtl     HWND of control
+//      bHandled    FALSE if not handled
+//
+// Output:
+//      LRESULT
+//
+// Notes:
+//
+LRESULT CDownloadDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+    // Disable window first to avoid any keyboard input
+    EnableWindow(FALSE);
+
+    if (m_feedbackOnCancel) {
+      int r = SafeMessageBox(IDS_DOWNLOAD_CANCEL_MESSAGE,
+                       IDS_DOWNLOAD_CANCEL_INSTRUCTION,
+                       IDS_DOWNLOAD_CANCEL_CAPTION,
+                       DIALOG_WARNING_CANCELOK,
+                       NULL, NULL);
+      if (!::IsWindow(hWndCtl)) {
+         /* It is possible that download was finished and download
+            window hidden by the time user close this message box.
+            If such case we should simply return. */
+         return 0;
+      }
+      if (r == IDCANCEL) {
+        EnableWindow(TRUE);
+        return 0;
+      }
+    }
+
+    __try
+    {
+        m_csDownload.Lock();
+        // if we are downloading, signal download thread to stop downloading
+        if (m_numDownloadThreadsRunning > 0) {
+            SetEvent(m_hCancelEvent);
+        }
+    }
+    __finally
+    {
+        m_csDownload.Unlock();
+    }
+
+    // Kill timer
+    KillTimer(iTimerID);
+    KillTimer(destroyWindowTimerID);
+
+    FreeGDIResources();
+
+    // Destroy dialog
+    EndDialog(wID);
+
+    return 0;
+}
+
+void CDownloadDialog::destroyDialog() {
+    m_feedbackOnCancel = FALSE;
+    ::PostMessage(m_hWnd, WM_COMMAND, IDCANCEL, NULL);
+}
+
+
+void CDownloadDialog::delayedDoModal() {
+     __try
+    {
+         __try
+        {
+            m_csMessageBox.Lock();
+            m_dialogUp = true;
+            Sleep(INITIAL_DELAY);
+        }
+        __finally
+        {
+            m_csMessageBox.Unlock();
+        }
+
+        if (isDownloading())
+            DoModal();
+    }
+    __finally
+    {
+        m_dialogUp = false;
+    }
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::SafeMessageBox
+//=--------------------------------------------------------------------------=
+// Helper method that uses best availble API to show native error/information
+// dialog. In particular, it uses TaskDialog if availble (Vista specific)
+// and MessageBox otherwise.
+//
+// It also ensures that the message box is always displayed on top of
+// the progress dialog instead of underneath
+//
+
+//helper structures to define XP vs Vista style differences
+static TASKDIALOG_COMMON_BUTTON_FLAGS vistaDialogButtons[] = {
+    TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON,
+    TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON
+};
+static PCWSTR vistaIcons[] = {
+    TD_ERROR_ICON,
+    TD_WARNING_ICON
+};
+
+static UINT xpStyle[] = {
+    MB_ICONERROR | MB_RETRYCANCEL,
+    MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2
+};
+
+int CDownloadDialog::SafeMessageBox(UINT details, UINT mainInstruction, UINT caption, DialogType type, LPCWSTR instructionArg, LPCWSTR detailsArg) {
+    WCHAR textCaption[BUFFER_SIZE+1];
+    WCHAR textDetails[BUFFER_SIZE+1];
+    WCHAR textInstruction[BUFFER_SIZE+1];
+    WCHAR tmpBuffer[BUFFER_SIZE+1];
+
+    /* make sure buffers are terminated */
+    textCaption[BUFFER_SIZE] = textDetails[BUFFER_SIZE] = 0;
+    textInstruction[BUFFER_SIZE] = tmpBuffer[BUFFER_SIZE] = 0;
+
+    if (detailsArg != NULL) {
+        ::LoadStringW(_Module.GetResourceInstance(),
+                 details,
+                 tmpBuffer,
+                 BUFFER_SIZE);
+        _snwprintf(textDetails, BUFFER_SIZE, tmpBuffer, detailsArg);
+    } else {
+        ::LoadStringW(_Module.GetResourceInstance(),
+                 details,
+                 textDetails,
+                 BUFFER_SIZE);
+    }
+
+    if (instructionArg != NULL) {
+        ::LoadStringW(_Module.GetResourceInstance(),
+                 mainInstruction,
+                 tmpBuffer,
+                 BUFFER_SIZE);
+        _snwprintf(textInstruction, BUFFER_SIZE, tmpBuffer, instructionArg);
+     } else {
+        ::LoadStringW(_Module.GetResourceInstance(),
+                 mainInstruction,
+                 textInstruction,
+                 BUFFER_SIZE);
+     }
+
+    ::LoadStringW(_Module.GetResourceInstance(),
+                 caption,
+                 textCaption,
+                 BUFFER_SIZE);
+
+    __try
+    {
+        m_csMessageBox.Lock();
+        if (m_dialogUp) {
+            waitUntilInitialized();
+        }
+        /* If TaskDialog availble - use it! */
+        if (taskDialogFn != NULL) {
+              TASKDIALOGCONFIG tc = { 0 };
+              int nButton;
+
+              tc.cbSize = sizeof(tc);
+              tc.hwndParent = ::IsWindow(m_hWnd) ? m_hWnd : NULL;
+              tc.dwCommonButtons = vistaDialogButtons[type];
+              tc.pszWindowTitle = textCaption;
+              tc.pszMainInstruction = textInstruction;
+              tc.pszContent = textDetails;
+              tc.pszMainIcon = vistaIcons[type];
+              /* workaround: we need to make sure Cancel is default
+                             for this type of Dialog */
+              if (type == DIALOG_WARNING_CANCELOK) {
+                  tc.nDefaultButton = IDCANCEL;
+              }
+
+              taskDialogFn(&tc, &nButton, NULL, NULL);
+              return nButton;
+        } else { /* default: use MessageBox */
+            /* Note that MessageBox API expects content as single string
+               and therefore we need to concatenate instruction
+               and details as 2 paragraphs.
+
+               The only exception is empty instruction. */
+            if (wcslen(textInstruction) > 0) {
+                wcsncat(textInstruction, L"\n\n",
+                        BUFFER_SIZE - wcslen(textInstruction));
+            }
+            wcsncat(textInstruction, textDetails,
+                    BUFFER_SIZE - wcslen(textInstruction));
+
+            return ::MessageBoxW(::IsWindow(m_hWnd) ? m_hWnd : NULL,
+                textInstruction, textCaption, xpStyle[type]);
+        }
+    }
+    __finally
+    {
+        m_csMessageBox.Unlock();
+    }
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnTimer
+//=--------------------------------------------------------------------------=
+// Message handler for WM_TIMER
+//
+// Parameters:
+//      uMsg        Windows Message
+//      wParam      WPARAM
+//      lParam      LPARAM
+//      bHandled    FALSE if not handled
+//
+// Output:
+//      LRESULT
+//
+// Notes:
+//
+LRESULT CDownloadDialog::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    if (destroyWindowTimerID == (int)wParam) {
+        KillTimer(destroyWindowTimerID);
+        m_destroyWindowTimerStarted = FALSE;
+        m_ulProgressMax = max(0, m_ulProgressMax - m_ulProgress);
+        logProgress();
+        m_ulProgress = 0;
+        logProgress();
+        m_feedbackOnCancel = FALSE;
+        ::PostMessage(m_hWnd, WM_COMMAND, IDCANCEL, NULL);
+    }
+
+    if (iTimerID == (int)wParam)
+    {
+
+        __try
+        {
+            m_csDownload.Lock();
+
+            HWND hStatusWnd = GetDlgItem(IDC_TIME_REMAINING);
+            HWND hProgressWnd = GetDlgItem(IDC_DOWNLOAD_PROGRESS);
+
+            if (m_ulProgress && m_ulProgressMax)
+            {
+                ::PostMessage(hProgressWnd, PBM_SETPOS,
+                     (WPARAM) (m_ulProgress * 100
+                        / m_ulProgressMax), NULL);
+
+                time_t currentTime;
+                time(&currentTime);
+
+                double elapsed_time = difftime(currentTime, m_startTime);
+                double remain_time = (elapsed_time / m_ulProgress) *
+                                      (m_ulProgressMax - m_ulProgress);
+                int hr = 0, min = 0;
+
+                if (remain_time > 60 * 60)
+                {
+                    hr = int(remain_time / (60 * 60));
+                    remain_time = remain_time - hr * 60 * 60;
+                }
+
+                if (remain_time > 60)
+                {
+                    min = int(remain_time / 60);
+                    remain_time = remain_time - min * 60;
+                }
+
+                TCHAR szBuffer[BUFFER_SIZE];
+                TCHAR szTimeBuffer[BUFFER_SIZE];
+
+                if (hr > 0)
+                {
+                    if (hr > 1)
+                        LoadString(_Module.GetResourceInstance(), IDS_HOURSMINUTESECOND,
+                                   szTimeBuffer, BUFFER_SIZE);
+                    else
+                        LoadString(_Module.GetResourceInstance(), IDS_HOURMINUTESECOND,
+                                   szTimeBuffer, BUFFER_SIZE);
+
+                    sprintf(szBuffer, szTimeBuffer, hr, min, remain_time);
+                }
+                else
+                {
+                    if (min > 0)
+                    {
+                        LoadString(_Module.GetResourceInstance(), IDS_MINUTESECOND,
+                                   szTimeBuffer, BUFFER_SIZE);
+                        sprintf(szBuffer, szTimeBuffer, min, remain_time);
+
+                    }
+                    else
+                    {
+                        LoadString(_Module.GetResourceInstance(), IDS_SECOND,
+                                   szTimeBuffer, BUFFER_SIZE);
+                        sprintf(szBuffer, szTimeBuffer, remain_time);
+
+                    }
+                }
+
+                if (m_ulProgress == m_ulProgressMax) {
+                    // download is done, unpacking bundle now, and waiting
+                    // for another download to take place
+                    ::LoadString(_Module.GetResourceInstance(),
+                            IDS_DOWNLOAD_UNPACKING, szBuffer, BUFFER_SIZE);
+                    __try
+                    {
+                        m_csNumDownloadThreads.Lock();
+                        // both download and unpacking is done, start
+                        // timer to destroy the progress window in 500ms
+                        if (!m_destroyWindowTimerStarted &&
+                               m_numDownloadThreadsRunning == 0) {
+                            SetTimer(destroyWindowTimerID, POST_DELAY);
+