aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorherrick <none@none>2009-07-01 10:18:58 -0400
committerherrick <none@none>2009-07-01 10:18:58 -0400
commit92639748cc5f99420936b8e98e22b4a4a8476b5f (patch)
treee42159a4b5f5d3e1ff046a7bc25d01f22f670120
parentebf7d6a2a5da4d57208cb69486acc9845eee9a62 (diff)
parent53921e2f54b084f101dd93e693408bfedeaf6030 (diff)
Merge
-rw-r--r--make/com/sun/java/pack/Makefile16
-rw-r--r--make/common/Defs-windows.gmk55
-rw-r--r--make/common/Library.gmk8
-rw-r--r--make/common/Program.gmk8
-rw-r--r--make/common/Release.gmk5
-rw-r--r--make/common/shared/Compiler-msvc.gmk8
-rw-r--r--make/common/shared/Defs-utils.gmk2
-rw-r--r--make/common/shared/Defs-windows.gmk10
-rw-r--r--make/common/shared/Defs.gmk1
-rw-r--r--make/common/shared/Sanity.gmk53
-rw-r--r--make/java/java/FILES_c.gmk1
-rw-r--r--make/java/redist/Makefile21
-rw-r--r--make/jpda/tty/Makefile6
-rw-r--r--make/sun/Makefile2
-rw-r--r--make/sun/applet/Makefile6
-rw-r--r--make/sun/jar/Makefile7
-rw-r--r--make/sun/javazic/tzdata_jdk/jdk11_full_backward4
-rw-r--r--make/sun/jconsole/Makefile7
-rw-r--r--make/sun/jkernel/FILES_c_windows.gmk42
-rw-r--r--make/sun/jkernel/FILES_java.gmk41
-rw-r--r--make/sun/jkernel/Makefile90
-rw-r--r--make/sun/native2ascii/Makefile7
-rw-r--r--make/sun/rmi/rmic/Makefile7
-rw-r--r--make/sun/serialver/Makefile8
-rw-r--r--src/share/classes/java/awt/color/ICC_Profile.java14
-rw-r--r--src/share/classes/java/lang/ClassLoader.java40
-rw-r--r--src/share/classes/java/lang/System.java18
-rw-r--r--src/share/classes/java/util/zip/ZipEntry.java16
-rw-r--r--src/share/classes/sun/applet/AppletClassLoader.java116
-rw-r--r--src/share/classes/sun/applet/AppletPanel.java4
-rw-r--r--src/share/classes/sun/jkernel/BackgroundDownloader.java209
-rw-r--r--src/share/classes/sun/jkernel/Bundle.java922
-rw-r--r--src/share/classes/sun/jkernel/BundleCheck.java330
-rw-r--r--src/share/classes/sun/jkernel/ByteArrayToFromHexDigits.java138
-rw-r--r--src/share/classes/sun/jkernel/DigestOutputStream.java255
-rw-r--r--src/share/classes/sun/jkernel/DownloadManager.java1676
-rw-r--r--src/share/classes/sun/jkernel/KernelError.java48
-rw-r--r--src/share/classes/sun/jkernel/Mutex.java86
-rw-r--r--src/share/classes/sun/jkernel/StandaloneByteArrayAccess.java155
-rw-r--r--src/share/classes/sun/jkernel/StandaloneMessageDigest.java395
-rw-r--r--src/share/classes/sun/jkernel/StandaloneSHA.java190
-rw-r--r--src/share/classes/sun/management/OperatingSystemImpl.java1
-rw-r--r--src/share/classes/sun/management/ThreadImpl.java1
-rw-r--r--src/share/classes/sun/misc/Launcher.java110
-rw-r--r--src/share/classes/sun/misc/PerformanceLogger.java14
-rw-r--r--src/share/classes/sun/misc/VM.java5
-rw-r--r--src/share/native/common/jni_util.c156
-rw-r--r--src/share/native/common/jni_util.h20
-rw-r--r--src/share/native/sun/misc/VM.c28
-rw-r--r--src/solaris/native/common/jni_util_md.c35
-rw-r--r--src/windows/bin/java_md.c122
-rw-r--r--src/windows/native/common/jni_util_md.c139
-rw-r--r--src/windows/native/sun/jkernel/DownloadDialog.cpp891
-rw-r--r--src/windows/native/sun/jkernel/DownloadDialog.h329
-rw-r--r--src/windows/native/sun/jkernel/DownloadHelper.cpp652
-rw-r--r--src/windows/native/sun/jkernel/DownloadHelper.h80
-rw-r--r--src/windows/native/sun/jkernel/graphics/bullet.bmpbin0 -> 68 bytes
-rw-r--r--src/windows/native/sun/jkernel/graphics/cautionshield32.bmpbin0 -> 2080 bytes
-rw-r--r--src/windows/native/sun/jkernel/graphics/java-icon.icobin0 -> 29926 bytes
-rw-r--r--src/windows/native/sun/jkernel/graphics/masthead.bmpbin0 -> 33336 bytes
-rw-r--r--src/windows/native/sun/jkernel/graphics/warningmasthead.bmpbin0 -> 2704 bytes
-rw-r--r--src/windows/native/sun/jkernel/kernel.cpp1621
-rw-r--r--src/windows/native/sun/jkernel/kernel.def28
-rw-r--r--src/windows/native/sun/jkernel/kernel.h25
-rw-r--r--src/windows/native/sun/jkernel/kernel.rc198
-rw-r--r--src/windows/native/sun/jkernel/kernel_de.rc121
-rw-r--r--src/windows/native/sun/jkernel/kernel_en.rc122
-rw-r--r--src/windows/native/sun/jkernel/kernel_es.rc121
-rw-r--r--src/windows/native/sun/jkernel/kernel_fr.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_it.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_ja.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_ko.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_sv.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_zh.rc120
-rw-r--r--src/windows/native/sun/jkernel/kernel_zh_TW.rc120
-rw-r--r--src/windows/native/sun/jkernel/resource.h105
-rw-r--r--src/windows/native/sun/jkernel/stdafx.cpp37
-rw-r--r--src/windows/native/sun/jkernel/stdafx.h53
-rw-r--r--src/windows/native/sun/jkernel/version.rc73
-rw-r--r--src/windows/native/sun/windows/awt.rc24
-rw-r--r--src/windows/resource/unpack200_proto.exe.manifest19
-rw-r--r--src/windows/resource/version.rc24
-rw-r--r--test/java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java2
-rw-r--r--test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java1
-rw-r--r--test/java/awt/font/Rotate/TranslatedOutlineTest.java1
-rw-r--r--test/java/awt/font/Threads/FontThread.java2
-rw-r--r--test/java/security/AccessControlContext/FailureDebugOption.java1
-rw-r--r--test/javax/swing/JPopupMenu/6691503/bug6691503.java2
-rw-r--r--test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java1
-rw-r--r--test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java1
-rw-r--r--test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java1
91 files changed, 10781 insertions, 252 deletions
diff --git a/make/com/sun/java/pack/Makefile b/make/com/sun/java/pack/Makefile
index afb84d365..a47948367 100644
--- a/make/com/sun/java/pack/Makefile
+++ b/make/com/sun/java/pack/Makefile
@@ -91,10 +91,10 @@ ifeq ($(PLATFORM), windows)
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 @@ unpacker:
$(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
diff --git a/make/common/Defs-windows.gmk b/make/common/Defs-windows.gmk
index 00b8ea71e..4112fd1eb 100644
--- a/make/common/Defs-windows.gmk
+++ b/make/common/Defs-windows.gmk
@@ -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_NAME = \
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
diff --git a/make/common/Library.gmk b/make/common/Library.gmk
index 0093c8e3a..22b9bc4f3 100644
--- a/make/common/Library.gmk
+++ b/make/common/Library.gmk
@@ -207,10 +207,10 @@ ifndef LOCAL_RESOURCE_FILE
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
diff --git a/make/common/Program.gmk b/make/common/Program.gmk
index 22aa7f9db..067ffa39b 100644
--- a/make/common/Program.gmk
+++ b/make/common/Program.gmk
@@ -123,10 +123,10 @@ $(ACTUAL_PROGRAM):: classes $(JVMCFG) $(INIT)
#
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)
diff --git a/make/common/Release.gmk b/make/common/Release.gmk
index 23a11c2b0..ad80b2c09 100644
--- a/make/common/Release.gmk
+++ b/make/common/Release.gmk
@@ -795,6 +795,11 @@ ifeq ($(PLATFORM), windows)
$(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))
diff --git a/make/common/shared/Compiler-msvc.gmk b/make/common/shared/Compiler-msvc.gmk
index ade430ad9..4ba8f1da6 100644
--- a/make/common/shared/Compiler-msvc.gmk
+++ b/make/common/shared/Compiler-msvc.gmk
@@ -35,8 +35,8 @@ ifeq ($(PLATFORM), windows)
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 @@ ifeq ($(PLATFORM), windows)
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 @@ ifeq ($(PLATFORM), windows)
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 @@ ifeq ($(PLATFORM), windows)
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
diff --git a/make/common/shared/Defs-utils.gmk b/make/common/shared/Defs-utils.gmk
index dacb40800..92a547805 100644
--- a/make/common/shared/Defs-utils.gmk
+++ b/make/common/shared/Defs-utils.gmk
@@ -72,6 +72,7 @@ ADB = $(UTILS_COMMAND_PATH)adb
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 @@ ifeq ($(PLATFORM),windows)
endif
# Re-define some utilities
LEX =# override GNU Make intrinsic: no lex on windows
+ SHA1SUM = $(UNIXCOMMAND_PATH)openssl sha1
endif
# Linux specific
diff --git a/make/common/shared/Defs-windows.gmk b/make/common/shared/Defs-windows.gmk
index 789fd3ad7..93f1a631c 100644
--- a/make/common/shared/Defs-windows.gmk
+++ b/make/common/shared/Defs-windows.gmk
@@ -520,7 +520,7 @@ ifdef ALT_INSTALL_MSSDK
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 @@ JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
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 @@ else
endif
HOTSPOT_LIB_PATH:=$(call AltCheckSpaces,HOTSPOT_LIB_PATH)
HOTSPOT_LIB_PATH:=$(call AltCheckValue,HOTSPOT_LIB_PATH)
-
diff --git a/make/common/shared/Defs.gmk b/make/common/shared/Defs.gmk
index 6477a075c..7a87da960 100644
--- a/make/common/shared/Defs.gmk
+++ b/make/common/shared/Defs.gmk
@@ -292,6 +292,7 @@ endif
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.
diff --git a/make/common/shared/Sanity.gmk b/make/common/shared/Sanity.gmk
index 2a5235031..b26097826 100644
--- a/make/common/shared/Sanity.gmk
+++ b/make/common/shared/Sanity.gmk
@@ -1568,10 +1568,50 @@ ifeq ($(ARCH_DATA_MODEL), 32)
"" >> $(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 @@ ifeq ($(PLATFORM), windows)
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.
diff --git a/make/java/java/FILES_c.gmk b/make/java/java/FILES_c.gmk
index b31c12313..ae4a46a45 100644
--- a/make/java/java/FILES_c.gmk
+++ b/make/java/java/FILES_c.gmk
@@ -64,6 +64,7 @@ FILES_c = \
jio.c \
logging.c \
jni_util.c \
+ jni_util_md.c \
jdk_util.c \
jdk_util_md.c \
check_version.c \
diff --git a/make/java/redist/Makefile b/make/java/redist/Makefile
index 9ab884dd2..59e1b11c7 100644
--- a/make/java/redist/Makefile
+++ b/make/java/redist/Makefile
@@ -119,10 +119,15 @@ IMPORT_LIST += \
$(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 @@ $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMMAP_NAME):
@$(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 @@ $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMPDB_NAME):
@$(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 @@ endif # PLATFORM
$(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)/$(SERVER_LOCATION)/Xusage.txt : $(HOTSPOT_SERVER_PATH)/Xusage.tx
$(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:
diff --git a/make/jpda/tty/Makefile b/make/jpda/tty/Makefile
index 650376313..4468bddbe 100644
--- a/make/jpda/tty/Makefile
+++ b/make/jpda/tty/Makefile
@@ -33,6 +33,12 @@ PRODUCT = jpda
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.
#
diff --git a/make/sun/Makefile b/make/sun/Makefile
index e5d62b68a..2e22bd803 100644
--- a/make/sun/Makefile
+++ b/make/sun/Makefile
@@ -59,7 +59,7 @@ else
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) \
diff --git a/make/sun/applet/Makefile b/make/sun/applet/Makefile
index a9a51f636..415db17dd 100644
--- a/make/sun/applet/Makefile
+++ b/make/sun/applet/Makefile
@@ -32,6 +32,12 @@ PACKAGE = sun.applet
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.
#
diff --git a/make/sun/jar/Makefile b/make/sun/jar/Makefile
index 39171873f..b90d73890 100644
--- a/make/sun/jar/Makefile
+++ b/make/sun/jar/Makefile
@@ -32,6 +32,13 @@ PACKAGE = sun.tools
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
#
diff --git a/make/sun/javazic/tzdata_jdk/jdk11_full_backward b/make/sun/javazic/tzdata_jdk/jdk11_full_backward
index 8999a9528..754d6d1ec 100644
--- a/make/sun/javazic/tzdata_jdk/jdk11_full_backward
+++ b/make/sun/javazic/tzdata_jdk/jdk11_full_backward
@@ -54,9 +54,9 @@ Link America/Los_Angeles PST
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.
diff --git a/make/sun/jconsole/Makefile b/make/sun/jconsole/Makefile
index ff27063ba..68ff7c504 100644
--- a/make/sun/jconsole/Makefile
+++ b/make/sun/jconsole/Makefile
@@ -32,6 +32,13 @@ PACKAGE = sun.tools.jconsole
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
diff --git a/make/sun/jkernel/FILES_c_windows.gmk b/make/sun/jkernel/FILES_c_windows.gmk
new file mode 100644
index 000000000..204776585
--- /dev/null
+++ b/make/sun/jkernel/FILES_c_windows.gmk
@@ -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 \
diff --git a/make/sun/jkernel/FILES_java.gmk b/make/sun/jkernel/FILES_java.gmk
new file mode 100644
index 000000000..0f2819e89
--- /dev/null
+++ b/make/sun/jkernel/FILES_java.gmk
@@ -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
diff --git a/make/sun/jkernel/Makefile b/make/sun/jkernel/Makefile
new file mode 100644
index 000000000..047efeae5
--- /dev/null
+++ b/make/sun/jkernel/Makefile
@@ -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
diff --git a/make/sun/native2ascii/Makefile b/make/sun/native2ascii/Makefile
index bab087848..766e90fc5 100644
--- a/make/sun/native2ascii/Makefile
+++ b/make/sun/native2ascii/Makefile
@@ -33,6 +33,13 @@ PRODUCT = sun
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
#
diff --git a/make/sun/rmi/rmic/Makefile b/make/sun/rmi/rmic/Makefile
index 8d9f435e6..a09a170f8 100644
--- a/make/sun/rmi/rmic/Makefile
+++ b/make/sun/rmi/rmic/Makefile
@@ -33,6 +33,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
#
include FILES.gmk
diff --git a/make/sun/serialver/Makefile b/make/sun/serialver/Makefile
index e848154af..0906d3e3e 100644
--- a/make/sun/serialver/Makefile
+++ b/make/sun/serialver/Makefile
@@ -33,6 +33,14 @@ 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
#
AUTO_FILES_JAVA_DIRS = sun/tools/serialver
diff --git a/src/share/classes/java/awt/color/ICC_Profile.java b/src/share/classes/java/awt/color/ICC_Profile.java
index ef685f435..d3c0613f0 100644
--- a/src/share/classes/java/awt/color/ICC_Profile.java
+++ b/src/share/classes/java/awt/color/ICC_Profile.java
@@ -1844,10 +1844,18 @@ public class ICC_Profile implements Serializable {
}
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()) {
diff --git a/src/share/classes/java/lang/ClassLoader.java b/src/share/classes/java/lang/ClassLoader.java
index cc0987a58..d25100958 100644
--- a/src/share/classes/java/lang/ClassLoader.java
+++ b/src/share/classes/java/lang/ClassLoader.java
@@ -58,6 +58,7 @@ import sun.misc.URLClassPath;
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 @@ public abstract class ClassLoader {
* 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 @@ public abstract class ClassLoader {
// 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 @@ public abstract class ClassLoader {
// 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) {
diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java
index 00478bc9e..fbe6fd1ff 100644
--- a/src/share/classes/java/lang/System.java
+++ b/src/share/classes/java/lang/System.java
@@ -1106,12 +1106,22 @@ public final class System {
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 @@ public final class System {
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 @@ public final class System {
// 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) {
diff --git a/src/share/classes/java/util/zip/ZipEntry.java b/src/share/classes/java/util/zip/ZipEntry.java
index 96e3b4d82..cba69b0c1 100644
--- a/src/share/classes/java/util/zip/ZipEntry.java
+++ b/src/share/classes/java/util/zip/ZipEntry.java
@@ -109,7 +109,15 @@ class ZipEntry implements ZipConstants, Cloneable {
* @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 @@ class ZipEntry implements ZipConstants, Cloneable {
* 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;
}
diff --git a/src/share/classes/sun/applet/AppletClassLoader.java b/src/share/classes/sun/applet/AppletClassLoader.java
index 155686c2d..3489256ae 100644
--- a/src/share/classes/sun/applet/AppletClassLoader.java
+++ b/src/share/classes/sun/applet/AppletClassLoader.java
@@ -69,6 +69,7 @@ public class AppletClassLoader extends URLClassLoader {
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 @@ public class AppletClassLoader extends URLClassLoader {
acc = AccessController.getContext();
}
+ public void disableRecursiveDirectoryRead() {
+ allowRecursiveDirectoryRead = false;
+ }
+
+
/**
* Set the codebase lookup flag.
*/
@@ -188,7 +194,21 @@ public class AppletClassLoader extends URLClassLoader {
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 @@ public class AppletClassLoader extends URLClassLoader {
}
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;
- }
- if (bperm instanceof FilePermission) {
- String bpath = bperm.getName();
- if (bpath.endsWith(File.separator)) {
- bpath += "-";
+ try {
+ bperm = base.openConnection().getPermission();
+ } catch (java.io.IOException ioe) {
+ bperm = null;
}
- 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 += "-";
+ 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));
}
- perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION));
- }
+ }
}
return perms;
}
@@ -702,7 +719,7 @@ public class AppletClassLoader extends URLClassLoader {
* 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 @@ public class AppletClassLoader extends URLClassLoader {
--usageCount;
} else {
synchronized(threadGroupSynchronizer) {
- // Store app context in temp variable
- tempAppContext = appContext;
- usageCount = 0;
- appContext = null;
- threadGroup = null;
+ tempAppContext = resetAppContext();
}
}
}
@@ -758,6 +771,29 @@ public class AppletClassLoader extends URLClassLoader {
}
}
+ /*
+ * 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();
diff --git a/src/share/classes/sun/applet/AppletPanel.java b/src/share/classes/sun/applet/AppletPanel.java
index 911324e15..5e126c211 100644
--- a/src/share/classes/sun/applet/AppletPanel.java
+++ b/src/share/classes/sun/applet/AppletPanel.java
@@ -80,7 +80,7 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
/**
* The classloader for the applet.
*/
- AppletClassLoader loader;
+ protected AppletClassLoader loader;
/* applet event ids */
public final static int APPLET_DISPOSE = 0;
@@ -116,7 +116,7 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
/**
* The thread for the applet.
*/
- Thread handler;
+ protected Thread handler;
/**
diff --git a/src/share/classes/sun/jkernel/BackgroundDownloader.java b/src/share/classes/sun/jkernel/BackgroundDownloader.java
new file mode 100644
index 000000000..9b3e2ba18
--- /dev/null
+++ b/src/share/classes/sun/jkernel/BackgroundDownloader.java
@@ -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();
+ }
+}
diff --git a/src/share/classes/sun/jkernel/Bundle.java b/src/share/classes/sun/jkernel/Bundle.java
new file mode 100644
index 000000000..13c130dad
--- /dev/null
+++ b/src/share/classes/sun/jkernel/Bundle.java
@@ -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 + "]";
+ }
+}
diff --git a/src/share/classes/sun/jkernel/BundleCheck.java b/src/share/classes/sun/jkernel/BundleCheck.java
new file mode 100644
index 000000000..3ce7173ad
--- /dev/null
+++ b/src/share/classes/sun/jkernel/BundleCheck.java
@@ -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
+}
diff --git a/src/share/classes/sun/jkernel/ByteArrayToFromHexDigits.java b/src/share/classes/sun/jkernel/ByteArrayToFromHexDigits.java
new file mode 100644
index 000000000..7d7cf23c9
--- /dev/null
+++ b/src/share/classes/sun/jkernel/ByteArrayToFromHexDigits.java
@@ -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;
+ }
+}
diff --git a/src/share/classes/sun/jkernel/DigestOutputStream.java b/src/share/classes/sun/jkernel/DigestOutputStream.java
new file mode 100644
index 000000000..67ec4b327
--- /dev/null
+++ b/src/share/classes/sun/jkernel/DigestOutputStream.java
@@ -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);
+// }
+
+}
diff --git a/src/share/classes/sun/jkernel/DownloadManager.java b/src/share/classes/sun/jkernel/DownloadManager.java
new file mode 100644
index 000000000..e945380eb
--- /dev/null
+++ b/src/share/classes/sun/jkernel/DownloadManager.java
@@ -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);
+ }
+ }
+}
diff --git a/src/share/classes/sun/jkernel/KernelError.java b/src/share/classes/sun/jkernel/KernelError.java
new file mode 100644
index 000000000..7517f81ff
--- /dev/null
+++ b/src/share/classes/sun/jkernel/KernelError.java
@@ -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);
+ }
+}
diff --git a/src/share/classes/sun/jkernel/Mutex.java b/src/share/classes/sun/jkernel/Mutex.java
new file mode 100644
index 000000000..da00a72fc
--- /dev/null
+++ b/src/share/classes/sun/jkernel/Mutex.java
@@ -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 + "]";
+ }
+}
diff --git a/src/share/classes/sun/jkernel/StandaloneByteArrayAccess.java b/src/share/classes/sun/jkernel/StandaloneByteArrayAccess.java
new file mode 100644
index 000000000..6b3f66401
--- /dev/null
+++ b/src/share/classes/sun/jkernel/StandaloneByteArrayAccess.java
@@ -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 );
+ }
+ }
+
+}
diff --git a/src/share/classes/sun/jkernel/StandaloneMessageDigest.java b/src/share/classes/sun/jkernel/StandaloneMessageDigest.java
new file mode 100644
index 000000000..1c9bd4e5f
--- /dev/null
+++ b/src/share/classes/sun/jkernel/StandaloneMessageDigest.java
@@ -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;
+ }
+
+}
diff --git a/src/share/classes/sun/jkernel/StandaloneSHA.java b/src/share/classes/sun/jkernel/StandaloneSHA.java
new file mode 100644
index 000000000..267b015e1
--- /dev/null
+++ b/src/share/classes/sun/jkernel/StandaloneSHA.java
@@ -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;
+ }
+
+}
diff --git a/src/share/classes/sun/management/OperatingSystemImpl.java b/src/share/classes/sun/management/OperatingSystemImpl.java
index 9ab8b5695..18f28e09b 100644
--- a/src/share/classes/sun/management/OperatingSystemImpl.java
+++ b/src/share/classes/sun/management/OperatingSystemImpl.java
@@ -78,4 +78,3 @@ public class OperatingSystemImpl implements OperatingSystemMXBean {
}
}
-
diff --git a/src/share/classes/sun/management/ThreadImpl.java b/src/share/classes/sun/management/ThreadImpl.java
index 565966e9d..6604c72b7 100644
--- a/src/share/classes/sun/management/ThreadImpl.java
+++ b/src/share/classes/sun/management/ThreadImpl.java
@@ -419,4 +419,3 @@ class ThreadImpl implements ThreadMXBean {
}
}
-
diff --git a/src/share/classes/sun/misc/Launcher.java b/src/share/classes/sun/misc/Launcher.java
index 030d3e571..2793f14f0 100644
--- a/src/share/classes/sun/misc/Launcher.java
+++ b/src/share/classes/sun/misc/Launcher.java
@@ -38,6 +38,7 @@ import java.util.StringTokenizer;
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 java.security.CodeSource;
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 @@ public class Launcher {
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 @@ public class Launcher {
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 Launcher {
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 @@ public class Launcher {
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();
- }
- if (curEntry != null && seenDirs.add(curEntry)) {
- MetaIndex.registerDirectory(curEntry);
+ 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);
+ }
}
+ 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) {
diff --git a/src/share/classes/sun/misc/PerformanceLogger.java b/src/share/classes/sun/misc/PerformanceLogger.java
index 2f9cf3360..87b4122ed 100644
--- a/src/share/classes/sun/misc/PerformanceLogger.java
+++ b/src/share/classes/sun/misc/PerformanceLogger.java
@@ -81,6 +81,7 @@ public class PerformanceLogger {
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 @@ public class PerformanceLogger {
}
/**
+ * 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 @@ public class PerformanceLogger {
TimeData td = times.get(i);
if (td != null) {
writer.write(i + " " + td.getMessage() + ": " +
- td.getTime() + "\n");
+ (td.getTime() - baseTime) + "\n");
+
}
}
}
diff --git a/src/share/classes/sun/misc/VM.java b/src/share/classes/sun/misc/VM.java
index c0090de38..cc7f97f1c 100644
--- a/src/share/classes/sun/misc/VM.java
+++ b/src/share/classes/sun/misc/VM.java
@@ -346,6 +346,11 @@ public class VM {
private native static void getThreadStateValues(int[][] vmThreadStateValues,
String[][] vmThreadStateNames);
+ private static boolean kernelVM;
+ public static boolean isBootedKernelVM() {
+ return booted && kernelVM;
+ }
+
static {
initialize();
}
diff --git a/src/share/native/common/jni_util.c b/src/share/native/common/jni_util.c
index 12cd087cc..1afb59f38 100644
--- a/src/share/native/common/jni_util.c
+++ b/src/share/native/common/jni_util.c
@@ -607,14 +607,6 @@ getStringCp1252Chars(JNIEnv *env, jstring jstr)
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 jstring jnuEncoding = NULL;
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 @@ JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str)
{
jstring result;
- jbyteArray hab = 0;
- int len;
-
- 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 ((*env)->EnsureLocalCapacity(env, 2) < 0)
- return 0;
-
- 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);
+ result = nativeNewStringPlatform(env, str);
+ if (result == NULL) {
+ jbyteArray hab = 0;
+ int len;
+
+ 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 ((*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);
+ }
+ (*env)->DeleteLocalRef(env, hab);
+ return result;
}
- (*env)->DeleteLocalRef(env, hab);
- return result;
}
- return 0;
+ return NULL;
}
JNIEXPORT const char *
@@ -768,46 +767,49 @@ GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
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 (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 ((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 (!(*env)->ExceptionCheck(env)) {
- jint len = (*env)->GetArrayLength(env, hab);
- result = MALLOC_MIN4(len);
- if (result == 0) {
- JNU_ThrowOutOfMemoryError(env, 0);
- (*env)->DeleteLocalRef(env, hab);
+ 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)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
- result[len] = 0; /* NULL-terminate */
- }
- (*env)->DeleteLocalRef(env, hab);
+ (*env)->DeleteLocalRef(env, hab);
+ }
return result;
}
diff --git a/src/share/native/common/jni_util.h b/src/share/native/common/jni_util.h
index 294152641..a1ae06ad4 100644
--- a/src/share/native/common/jni_util.h
+++ b/src/share/native/common/jni_util.h
@@ -320,6 +320,26 @@ JNU_GetEnv(JavaVM *vm, jint version);
#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 */
diff --git a/src/share/native/sun/misc/VM.c b/src/share/native/sun/misc/VM.c
index dc8c7011e..6dcc8d68f 100644
--- a/src/share/native/sun/misc/VM.c
+++ b/src/share/native/sun/misc/VM.c
@@ -109,11 +109,39 @@ Java_sun_misc_VM_getThreadStateValues(JNIEnv *env, jclass cls,
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);
+ }
+ }
}
}
+
diff --git a/src/solaris/native/common/jni_util_md.c b/src/solaris/native/common/jni_util_md.c
new file mode 100644
index 000000000..e0061026d
--- /dev/null
+++ b/src/solaris/native/common/jni_util_md.c
@@ -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;
+}
diff --git a/src/windows/bin/java_md.c b/src/windows/bin/java_md.c
index c468258b7..df5e6988c 100644
--- a/src/windows/bin/java_md.c
+++ b/src/windows/bin/java_md.c
@@ -49,6 +49,7 @@ static jboolean GetPublicJREHome(char *path, jint pathsize);
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 @@ CreateExecutionEnvironment(int *_argc,
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 @@ CreateExecutionEnvironment(int *_argc,
}
+
+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 @@ jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
{
HINSTANCE handle;
- char crtpath[MAXPATHLEN];
JLI_TraceLauncher("JVM path is %s\n", jvmpath);
@@ -206,26 +306,8 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
* 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) {
diff --git a/src/windows/native/common/jni_util_md.c b/src/windows/native/common/jni_util_md.c
new file mode 100644
index 000000000..b57e4ee8c
--- /dev/null
+++ b/src/windows/native/common/jni_util_md.c
@@ -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;
+}
diff --git a/src/windows/native/sun/jkernel/DownloadDialog.cpp b/src/windows/native/sun/jkernel/DownloadDialog.cpp
new file mode 100644
index 000000000..d56a51687
--- /dev/null
+++ b/src/windows/native/sun/jkernel/DownloadDialog.cpp
@@ -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);
+ m_destroyWindowTimerStarted = TRUE;
+ }
+ }
+ __finally
+ {
+ m_csNumDownloadThreads.Unlock();
+ }
+ }
+
+ // Update status message
+ ::SetWindowText(hStatusWnd, szBuffer);
+ }
+ }
+ __finally
+ {
+ m_csDownload.Unlock();
+ }
+ }
+
+ return 0;
+}
+
+// Message handler for WM_ONCTLCOLORSTATIC.
+// this message is sent each time a static control is drawn.
+// we get the Control ID and then set background color and font
+// as appropriate for that control.
+LRESULT CDownloadDialog::OnCtlColorStatic(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ HDC hdc = (HDC) wParam;
+ HWND hwnd = (HWND) lParam;
+
+ int DlgCtrlID = ::GetDlgCtrlID(hwnd);
+
+ if (DlgCtrlID == IDC_DOWNLOAD_TEXT )
+ {
+ if (m_hDialogFont == NULL)
+ {
+ m_hDialogFont = CreateDialogFont(hdc, TEXT("MS Shell Dlg"), 8);
+ }
+
+ ::SelectObject(hdc, m_hDialogFont);
+ return 0;
+ }
+ else if (DlgCtrlID == IDC_TIME_REMAINING)
+ {
+ if (m_hSixPointFont == NULL)
+ {
+ m_hSixPointFont = CreateDialogFont(hdc, TEXT("MS Shell Dlg"), 8);
+ }
+
+ ::SelectObject(hdc, m_hSixPointFont);
+ return 0;
+ }
+ else if (DlgCtrlID == IDC_MASTHEAD_TEXT)
+ {
+ if (m_hMastheadFont == NULL)
+ {
+ m_hMastheadFont = CreateDialogFont(hdc, TEXT("MS Shell Dlg"), 12, 1);
+ }
+
+ ::SelectObject(hdc, m_hMastheadFont);
+ return (LRESULT) GetStockObject(WHITE_BRUSH);
+ }
+ else if (DlgCtrlID == IDC_DOWNLOAD_MASTHEAD)
+ {
+ if (m_hMemDC == NULL)
+ {
+ m_hBitmap = LoadBitmap(_Module.GetModuleInstance(),
+ MAKEINTRESOURCE(IDI_MASTHEAD));
+ GetObject(m_hBitmap, sizeof(BITMAP), &m_bmMasthead);
+ m_hMemDC = CreateCompatibleDC(NULL);
+ SelectObject(m_hMemDC, m_hBitmap);
+ }
+
+ RECT rect;
+ ::GetClientRect(hwnd, &rect);
+
+ StretchBlt(hdc, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top),
+ m_hMemDC, 0, 0, m_bmMasthead.bmWidth, m_bmMasthead.bmHeight, SRCCOPY);
+
+ return (LRESULT) GetStockObject(NULL_BRUSH);
+ }
+
+
+ return 0;
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnStartBinding
+//=--------------------------------------------------------------------------=
+// Called when download is started
+//
+// Parameters:
+//
+// Output:
+// HRESULT
+//
+// Notes:
+//
+STDMETHODIMP CDownloadDialog::OnStartBinding()
+{
+ __try
+ {
+ m_csDownload.Lock();
+ time(&m_startTime);
+ }
+ __finally
+ {
+ m_csDownload.Unlock();
+ }
+
+ return S_OK;
+}
+
+
+//=--------------------------------------------------------------------------=
+// CDownloadDialog::OnProgress
+//=--------------------------------------------------------------------------=
+// Called when download is in progress
+//
+// Parameters: ULONG ulProgress
+//
+// Output:
+// HRESULT
+//
+// Notes:
+//
+STDMETHODIMP CDownloadDialog::OnProgress(ULONG ulProgress)
+{
+ __try
+ {
+ m_csDownload.Lock();
+ m_ulProgress = m_ulProgress + ulProgress;
+ logProgress();
+
+ }
+ __finally
+ {
+ m_csDownload.Unlock();
+ }
+
+ return S_OK;
+}
+
+void CDownloadDialog::decrementProgressMax(ULONG contentLength, ULONG readSoFar) {
+ __try
+ {
+ m_csDownload.Lock();
+ m_ulProgressMax = m_ulProgressMax - contentLength;
+ m_ulProgress = m_ulProgress - readSoFar;
+ logProgress();
+ }
+ __finally
+ {
+ m_csDownload.Unlock();
+ }
+
+}
+
+void CDownloadDialog::waitUntilInitialized() {
+ // wait until download progress dialog is initialized and ready to show
+ WaitForSingleObject(m_hDialogInitializedEvent, INFINITE);
+ ResetEvent(m_hDialogInitializedEvent);
+
+}
+
+// Check if download has been cancelled
+BOOL CDownloadDialog::isDownloadCancelled() {
+ if (WAIT_OBJECT_0 == WaitForSingleObject(m_hCancelEvent, 0)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+// Create the fonts we need for the download and
+// install UE
+HFONT CDownloadDialog::CreateDialogFont(HDC hdc, LPCTSTR lpszFaceName, int ptSize, int isBold)
+{
+ POINT pt;
+ FLOAT cxDPI, cyDPI;
+ HFONT hFont;
+ LOGFONT lf;
+
+ int iDeciPtWidth = 0;
+ int iDeciPtHeight = 10 * ptSize;
+
+ int iSavedDC = SaveDC(hdc);
+
+ SetGraphicsMode (hdc, GM_ADVANCED);
+ ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
+ SetViewportOrgEx (hdc, 0,0, NULL);
+ SetWindowOrgEx (hdc, 0,0, NULL);
+
+ cxDPI = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSX);
+ cyDPI = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSY);
+
+ pt.x = (int) (iDeciPtWidth * cxDPI / 72);
+ pt.y = (int) (iDeciPtHeight * cyDPI / 72);
+
+ DPtoLP(hdc, &pt, 1);
+
+ lf.lfHeight = - (int) (fabs ((double) pt.y) / 10.0 + 0.5);
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = (isBold > 0) ? FW_BOLD : 0;
+ lf.lfItalic = 0;
+ lf.lfUnderline = 0;
+ lf.lfStrikeOut = 0;
+ lf.lfCharSet = 0;
+ lf.lfOutPrecision = 0;
+ lf.lfClipPrecision = 0;
+ lf.lfQuality = 0;
+ lf.lfPitchAndFamily = 0;
+
+ TCHAR szLocaleData[BUFFER_SIZE];
+ GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SENGCOUNTRY,
+ szLocaleData, BUFFER_SIZE);
+
+ if (strncmp(szLocaleData, "Japan", 5) == 0) {
+ // need special font for _ja locale
+ strcpy (lf.lfFaceName, TEXT("MS UI Gothic"));
+ } else {
+ strcpy (lf.lfFaceName, lpszFaceName);
+ }
+
+ hFont = CreateFontIndirect(&lf);
+
+ RestoreDC (hdc, iSavedDC);
+ return hFont;
+}
+
+void CDownloadDialog::FreeGDIResources ()
+{
+ ::DeleteObject(m_hMastheadFont);
+ m_hMastheadFont = NULL;
+
+ ::DeleteObject(m_hDialogFont);
+ m_hDialogFont = NULL;
+
+ ::DeleteObject(m_hSixPointFont);
+ m_hSixPointFont = NULL;
+
+ ::DeleteObject(m_hBitmap);
+ m_hBitmap = NULL;
+
+ ::DeleteDC(m_hMemDC);
+ m_hMemDC = NULL;
+}
+
+
+JNIEnv* CDownloadDialog::getJNIEnv() {
+ if (m_jvm == NULL)
+ return NULL;
+ JNIEnv *env;
+ m_jvm->AttachCurrentThread((void**) &env, NULL);
+ return env;
+}
+
+
+void CDownloadDialog::log(char *msg) {
+ JNIEnv *env = getJNIEnv();
+ if (env != NULL) {
+ jclass dm = env->FindClass("sun/jkernel/DownloadManager");
+ if (dm == NULL) {
+ printf("Cound not find class sun.jkernel.DownloadManager\n");
+ return;
+ }
+ jmethodID log = env->GetStaticMethodID(dm, "log", "(Ljava/lang/String;)V");
+ if (log == NULL) {
+ printf("Could not find method sun.jkernel.DownloadManager.log(String)\n");
+ return;
+ }
+ jstring string = env->NewStringUTF(msg);
+ if (string == NULL) {
+ printf("Error creating log string\n");
+ return;
+ }
+ env->CallStaticVoidMethod(dm, log, string);
+ }
+}
+
+
+void CDownloadDialog::logProgress() {
+ char msg[256];
+ sprintf(msg, "Progress: %d / %d", m_ulProgress, m_ulProgressMax);
+ log(msg);
+}
diff --git a/src/windows/native/sun/jkernel/DownloadDialog.h b/src/windows/native/sun/jkernel/DownloadDialog.h
new file mode 100644
index 000000000..30ed9bd75
--- /dev/null
+++ b/src/windows/native/sun/jkernel/DownloadDialog.h
@@ -0,0 +1,329 @@
+/*
+ * 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.
+ */
+
+//
+// DownloadDialog.h : Declaration of the CDownloadDialog
+//
+
+#ifndef __DOWNLOADDIALOG_H_
+#define __DOWNLOADDIALOG_H_
+
+#include "resource.h" // main symbols
+#include <time.h>
+#include "jni.h"
+
+#ifndef BUFFER_SIZE
+#define BUFFER_SIZE 2048
+#endif
+
+#define iTimerID 1000
+#define destroyWindowTimerID 2000
+
+#define E_JDHELPER_TIMEOUT 12002
+#define E_JDHELPER_NAME_NOT_RESOLVED 12007
+#define E_JDHELPER_CANNOT_CONNECT 12029
+
+/* Following lines were copied from the new version of commctrl.h
+ These definitions are not available in default version of
+ this header file in VS 2003 but they are needed to use
+ new Vista task dialog API.
+*/
+#ifndef TD_ERROR_ICON
+
+/* These modifiers have sense with new VS only,
+ reset them to get code to compile */
+#define __in
+#define __in_opt
+#define __out_opt
+
+#ifdef _WIN32
+#include <pshpack1.h>
+#endif
+
+
+typedef HRESULT (CALLBACK *PFTASKDIALOGCALLBACK)(HWND hwnd, __in UINT msg, __in WPARAM wParam, __in LPARAM lParam, __in LONG_PTR lpRefData);
+
+enum _TASKDIALOG_FLAGS
+{
+ TDF_ENABLE_HYPERLINKS = 0x0001,
+ TDF_USE_HICON_MAIN = 0x0002,
+ TDF_USE_HICON_FOOTER = 0x0004,
+ TDF_ALLOW_DIALOG_CANCELLATION = 0x0008,
+ TDF_USE_COMMAND_LINKS = 0x0010,
+ TDF_USE_COMMAND_LINKS_NO_ICON = 0x0020,
+ TDF_EXPAND_FOOTER_AREA = 0x0040,
+ TDF_EXPANDED_BY_DEFAULT = 0x0080,
+ TDF_VERIFICATION_FLAG_CHECKED = 0x0100,
+ TDF_SHOW_PROGRESS_BAR = 0x0200,
+ TDF_SHOW_MARQUEE_PROGRESS_BAR = 0x0400,
+ TDF_CALLBACK_TIMER = 0x0800,
+ TDF_POSITION_RELATIVE_TO_WINDOW = 0x1000,
+ TDF_RTL_LAYOUT = 0x2000,
+ TDF_NO_DEFAULT_RADIO_BUTTON = 0x4000,
+ TDF_CAN_BE_MINIMIZED = 0x8000
+};
+typedef int TASKDIALOG_FLAGS; // Note: _TASKDIALOG_FLAGS is an int
+
+typedef enum _TASKDIALOG_MESSAGES
+{
+ TDM_NAVIGATE_PAGE = WM_USER+101,
+ TDM_CLICK_BUTTON = WM_USER+102, // wParam = Button ID
+ TDM_SET_MARQUEE_PROGRESS_BAR = WM_USER+103, // wParam = 0 (nonMarque) wParam != 0 (Marquee)
+ TDM_SET_PROGRESS_BAR_STATE = WM_USER+104, // wParam = new progress state
+ TDM_SET_PROGRESS_BAR_RANGE = WM_USER+105, // lParam = MAKELPARAM(nMinRange, nMaxRange)
+ TDM_SET_PROGRESS_BAR_POS = WM_USER+106, // wParam = new position
+ TDM_SET_PROGRESS_BAR_MARQUEE = WM_USER+107, // wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints)
+ TDM_SET_ELEMENT_TEXT = WM_USER+108, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
+ TDM_CLICK_RADIO_BUTTON = WM_USER+110, // wParam = Radio Button ID
+ TDM_ENABLE_BUTTON = WM_USER+111, // lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID
+ TDM_ENABLE_RADIO_BUTTON = WM_USER+112, // lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID
+ TDM_CLICK_VERIFICATION = WM_USER+113, // wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus)
+ TDM_UPDATE_ELEMENT_TEXT = WM_USER+114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
+ TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = WM_USER+115, // wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required)
+ TDM_UPDATE_ICON = WM_USER+116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise)
+} TASKDIALOG_MESSAGES;
+
+typedef enum _TASKDIALOG_NOTIFICATIONS
+{
+ TDN_CREATED = 0,
+ TDN_NAVIGATED = 1,
+ TDN_BUTTON_CLICKED = 2, // wParam = Button ID
+ TDN_HYPERLINK_CLICKED = 3, // lParam = (LPCWSTR)pszHREF
+ TDN_TIMER = 4, // wParam = Milliseconds since dialog created or timer reset
+ TDN_DESTROYED = 5,
+ TDN_RADIO_BUTTON_CLICKED = 6, // wParam = Radio Button ID
+ TDN_DIALOG_CONSTRUCTED = 7,
+ TDN_VERIFICATION_CLICKED = 8, // wParam = 1 if checkbox checked, 0 if not, lParam is unused and always 0
+ TDN_HELP = 9,
+ TDN_EXPANDO_BUTTON_CLICKED = 10 // wParam = 0 (dialog is now collapsed), wParam != 0 (dialog is now expanded)
+} TASKDIALOG_NOTIFICATIONS;
+
+typedef struct _TASKDIALOG_BUTTON
+{
+ int nButtonID;
+ PCWSTR pszButtonText;
+} TASKDIALOG_BUTTON;
+
+typedef enum _TASKDIALOG_ELEMENTS
+{
+ TDE_CONTENT,
+ TDE_EXPANDED_INFORMATION,
+ TDE_FOOTER,
+ TDE_MAIN_INSTRUCTION
+} TASKDIALOG_ELEMENTS;
+
+typedef enum _TASKDIALOG_ICON_ELEMENTS
+{
+ TDIE_ICON_MAIN,
+ TDIE_ICON_FOOTER
+} TASKDIALOG_ICON_ELEMENTS;
+
+#define TD_WARNING_ICON MAKEINTRESOURCEW(-1)
+#define TD_ERROR_ICON MAKEINTRESOURCEW(-2)
+#define TD_INFORMATION_ICON MAKEINTRESOURCEW(-3)
+#define TD_SHIELD_ICON MAKEINTRESOURCEW(-4)
+
+
+enum _TASKDIALOG_COMMON_BUTTON_FLAGS
+{
+ TDCBF_OK_BUTTON = 0x0001, // selected control return value IDOK
+ TDCBF_YES_BUTTON = 0x0002, // selected control return value IDYES
+ TDCBF_NO_BUTTON = 0x0004, // selected control return value IDNO
+ TDCBF_CANCEL_BUTTON = 0x0008, // selected control return value IDCANCEL
+ TDCBF_RETRY_BUTTON = 0x0010, // selected control return value IDRETRY
+ TDCBF_CLOSE_BUTTON = 0x0020 // selected control return value IDCLOSE
+};
+typedef int TASKDIALOG_COMMON_BUTTON_FLAGS; // Note: _TASKDIALOG_COMMON_BUTTON_FLAGS is an int
+
+typedef struct _TASKDIALOGCONFIG
+{
+ UINT cbSize;
+ HWND hwndParent;
+ HINSTANCE hInstance; // used for MAKEINTRESOURCE() strings
+ TASKDIALOG_FLAGS dwFlags; // TASKDIALOG_FLAGS (TDF_XXX) flags
+ TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons; // TASKDIALOG_COMMON_BUTTON (TDCBF_XXX) flags
+ PCWSTR pszWindowTitle; // string or MAKEINTRESOURCE()
+ union
+ {
+ HICON hMainIcon;
+ PCWSTR pszMainIcon;
+ };
+ PCWSTR pszMainInstruction;
+ PCWSTR pszContent;
+ UINT cButtons;
+ const TASKDIALOG_BUTTON *pButtons;
+ int nDefaultButton;
+ UINT cRadioButtons;
+ const TASKDIALOG_BUTTON *pRadioButtons;
+ int nDefaultRadioButton;
+ PCWSTR pszVerificationText;
+ PCWSTR pszExpandedInformation;
+ PCWSTR pszExpandedControlText;
+ PCWSTR pszCollapsedControlText;
+ union
+ {
+ HICON hFooterIcon;
+ PCWSTR pszFooterIcon;
+ };
+ PCWSTR pszFooter;
+ PFTASKDIALOGCALLBACK pfCallback;
+ LONG_PTR lpCallbackData;
+ UINT cxWidth; // width of the Task Dialog's client area in DLU's. If 0, Task Dialog will calculate the ideal width.
+} TASKDIALOGCONFIG;
+
+WINCOMMCTRLAPI HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, __out_opt int *pnButton, __out_opt int *pnRadioButton, __out_opt BOOL *pfVerificationFlagChecked);
+WINCOMMCTRLAPI HRESULT WINAPI TaskDialog(__in_opt HWND hwndParent, __in_opt HINSTANCE hInstance, __in_opt PCWSTR pszWindowTitle, __in_opt PCWSTR pszMainInstruction, __in_opt PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, __in_opt PCWSTR pszIcon, __out_opt int *pnButton);
+
+#ifdef _WIN32
+#include <poppack.h>
+#endif
+
+#endif /* end of copy from commctrl.h */
+
+typedef HRESULT (WINAPI *TaskDialogIndirectFn) (const TASKDIALOGCONFIG *pTaskConfig, __out_opt int *pnButton, __out_opt int *pnRadioButton, __out_opt BOOL *pfVerificationFlagChecked);
+
+typedef enum {
+ DIALOG_ERROR_RETRYCANCEL = 0,
+ DIALOG_WARNING_CANCELOK
+} DialogType;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CDownloadDialog
+class CDownloadDialog :
+ public CAxDialogImpl<CDownloadDialog>
+{
+public:
+ CDownloadDialog();
+ ~CDownloadDialog();
+
+ enum { IDD = IDD_DOWNLOAD_DIALOG };
+
+BEGIN_MSG_MAP(CDownloadDialog)
+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+ MESSAGE_HANDLER(WM_TIMER, OnTimer)
+ MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColorStatic)
+ COMMAND_ID_HANDLER(IDOK, OnOK)
+ COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+END_MSG_MAP()
+
+ LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnCtlColorStatic(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+ STDMETHODIMP OnStartBinding();
+
+ STDMETHODIMP OnProgress(ULONG ulProgress);
+
+ void initDialogText(LPCTSTR pszDownloadURL, LPCTSTR pszBundleName);
+
+ BOOL isDownloading();
+ BOOL isDownloadCancelled();
+
+ void addToTotalContentLength(DWORD contentLength);
+
+ void decrementProgressMax(ULONG contentLength, ULONG readSoFar);
+
+ void bundleInstallStart();
+ void bundleInstallComplete();
+
+ void waitUntilInitialized();
+
+ void log(char *msg);
+ void logProgress();
+
+ void setFile(LPCTSTR pszFileName)
+ {
+ m_pszFileName = pszFileName;
+ }
+
+ void setURL(LPCTSTR pszURL)
+ {
+ m_pszURL = pszURL;
+ }
+
+ void setNameText(LPTSTR pszNameText)
+ {
+ m_pszNameText = pszNameText;
+ }
+
+
+ JNIEnv* getJNIEnv();
+
+
+ void setJavaVM(JavaVM *jvm)
+ {
+ m_jvm = jvm;
+ }
+
+
+ HRESULT DownloadConfiguration(LPTSTR pszConfigURL, LPTSTR pszConfigFile);
+
+ void delayedDoModal();
+
+ int SafeMessageBox(UINT details, UINT mainInstruction, UINT caption,
+ DialogType type, LPCWSTR instructionArg = NULL,
+ LPCWSTR detailsArg = NULL);
+
+ void destroyDialog();
+
+ private:
+
+ HFONT CreateDialogFont (HDC hdc, LPCTSTR lpszFaceName, int ptSize, int isBold = 0);
+ void FreeGDIResources ();
+
+ BOOL m_feedbackOnCancel;
+ TaskDialogIndirectFn taskDialogFn;
+ LPCTSTR m_pszFileName;
+ LPCTSTR m_pszURL;
+ time_t m_startTime;
+ ULONG m_ulProgress;
+ ULONG m_ulProgressMax;
+ int m_iProgressFactor;
+ int m_iMaxProgressFactor;
+ int m_numDownloadThreadsRunning;
+ BOOL m_destroyWindowTimerStarted;
+ volatile BOOL m_dialogUp;
+ CComAutoCriticalSection m_csDownload;
+ CComAutoCriticalSection m_csNumDownloadThreads;
+ HANDLE m_hCancelEvent;
+ HANDLE m_hDownloadThreadExitEvent;
+ HANDLE m_hDialogInitializedEvent;
+ HFONT m_hMastheadFont;
+ HFONT m_hDialogFont;
+ HFONT m_hSixPointFont;
+ LPTSTR m_pszNameText;
+ BITMAP m_bmMasthead;
+ HBITMAP m_hBitmap;
+ HDC m_hMemDC;
+ TCHAR m_szUrlPath[BUFFER_SIZE];
+ TCHAR m_szHostName[BUFFER_SIZE];
+ JavaVM* m_jvm;
+ CComAutoCriticalSection m_csMessageBox;
+};
+
+#endif //__DOWNLOADDIALOG_H_
diff --git a/src/windows/native/sun/jkernel/DownloadHelper.cpp b/src/windows/native/sun/jkernel/DownloadHelper.cpp
new file mode 100644
index 000000000..ee5e5f00a
--- /dev/null
+++ b/src/windows/native/sun/jkernel/DownloadHelper.cpp
@@ -0,0 +1,652 @@
+/*
+ * 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 "resource.h" // main symbols
+#include "DownloadHelper.h"
+
+DownloadHelper::DownloadHelper() {
+
+ m_showProgressDialog = TRUE;
+ m_pszURL = NULL;
+ m_pszFileName = NULL;
+ m_pszNameText = NULL;
+}
+
+DownloadHelper::~DownloadHelper() {
+
+}
+
+HRESULT DownloadHelper::doDownload() {
+ return DownloadFile(m_pszURL, m_pszFileName, FALSE, m_showProgressDialog);
+}
+
+HRESULT DownloadHelper::DownloadFile(const TCHAR* szURL,
+ const TCHAR* szLocalFile, BOOL bResumable, BOOL bUIFeedback) {
+ HINTERNET hOpen = NULL;
+ HINTERNET hConnect = NULL;
+ HINTERNET hRequest = NULL;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD dwDownloadError = 0;
+ DWORD nContentLength = 0;
+
+ /* Some of error messages use drive letter.
+ Result is something like "(C:)".
+ NB: Parentheses are added here because in some other places
+ we same message but can not provide disk label info */
+ TCHAR drivePath[5];
+ /* assuming szLocalFile is not NULL */
+ _sntprintf(drivePath, 5, "(%c:)", szLocalFile[0]);
+ WCHAR* wName = CT2CW(drivePath);
+
+ __try {
+ m_csDownload.Lock();
+
+ time(&m_startTime);
+
+ }
+ __finally {
+ m_csDownload.Unlock();
+ }
+
+ __try {
+ // block potential security hole
+ if (strstr(szURL, TEXT("file://")) != NULL) {
+ dwDownloadError = 1;
+ __leave;
+ }
+
+ HWND hProgressInfo = NULL;
+ TCHAR szStatus[BUFFER_SIZE];
+
+ if (bUIFeedback) {
+ // init download dialg text
+ m_dlg->initDialogText(m_pszURL, m_pszNameText);
+ }
+
+ // Open Internet Call
+ hOpen = ::InternetOpen("deployHelper", INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL, NULL, NULL);
+
+ if (hOpen == NULL) {
+ dwDownloadError = 1;
+ __leave;
+ }
+
+ // URL components
+ URL_COMPONENTS url_components;
+ ::ZeroMemory(&url_components, sizeof(URL_COMPONENTS));
+
+ TCHAR szHostName[BUFFER_SIZE], szUrlPath[BUFFER_SIZE],
+ szExtraInfo[BUFFER_SIZE];
+ url_components.dwStructSize = sizeof(URL_COMPONENTS);
+ url_components.lpszHostName = szHostName;
+ url_components.dwHostNameLength = BUFFER_SIZE;
+ url_components.nPort = NULL;
+ url_components.lpszUrlPath = szUrlPath;
+ url_components.dwUrlPathLength = BUFFER_SIZE;
+ url_components.lpszExtraInfo = szExtraInfo;
+ url_components.dwExtraInfoLength = BUFFER_SIZE;
+
+ // Crack the URL into pieces
+ ::InternetCrackUrl(szURL, lstrlen(szURL), NULL, &url_components);
+
+ // Open Internet Connection
+ hConnect = ::InternetConnect(hOpen, url_components.lpszHostName,
+ url_components.nPort, "", "", INTERNET_SERVICE_HTTP, NULL,
+ NULL);
+
+ if (hConnect == NULL) {
+ dwDownloadError = 1;
+ __leave;
+ }
+
+ // Determine the relative URL path by combining
+ // Path and ExtraInfo
+ char szURL[4096];
+
+ if (url_components.dwUrlPathLength != 0)
+ lstrcpy(szURL, url_components.lpszUrlPath);
+ else
+ lstrcpy(szURL, "/");
+
+ if (url_components.dwExtraInfoLength != 0)
+ lstrcat(szURL, url_components.lpszExtraInfo);
+
+ BOOL bRetryHttpRequest = FALSE;
+ int numberOfRetry = 0;
+ long secondsToWait = 60;
+
+ do {
+ bRetryHttpRequest = FALSE;
+
+ // Make a HTTP GET request
+ hRequest = ::HttpOpenRequest(hConnect, "GET", szURL, "HTTP/1.1",
+ "", NULL,
+ INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_DONT_CACHE,
+ 0);
+
+ if (hRequest == NULL) {
+ dwDownloadError = 1;
+ __leave;
+ }
+
+ // Create or open existing destination file
+ hFile = ::CreateFile(szLocalFile, GENERIC_WRITE, 0, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ if (bUIFeedback) {
+ if (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_DISK_WRITE_ERROR,
+ IDS_DISK_WRITE_ERROR_CAPTION,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ wName)) {
+ bRetryHttpRequest = TRUE;
+ continue;
+ }
+ }
+ dwDownloadError = 1;
+ __leave;
+ }
+ DWORD fileSize = GetFileSize(hFile, NULL);
+
+ // Check if resumable download is enabled
+ if (bResumable == FALSE) {
+ // Start from scratch
+ fileSize = 0;
+ }
+
+ FILETIME tWrite;
+ BOOL rangereq = FALSE;
+ if ((fileSize != 0) && (fileSize != 0xFFFFFFFF) &&
+ GetFileTime(hFile, NULL, NULL, &tWrite)) {
+ char szHead[100];
+ SYSTEMTIME tLocal;
+ char buf[INTERNET_RFC1123_BUFSIZE];
+
+ FileTimeToSystemTime(&tWrite, &tLocal);
+ InternetTimeFromSystemTime(&tLocal, INTERNET_RFC1123_FORMAT,
+ buf, INTERNET_RFC1123_BUFSIZE);
+ sprintf(szHead, "Range: bytes=%d-\r\nIf-Range: %s\r\n",
+ fileSize, buf);
+ HttpAddRequestHeaders(hRequest, szHead, lstrlen(szHead),
+ HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
+ rangereq = TRUE;
+ }
+
+ // This is a loop to handle various potential error when the
+ // connection is made
+ BOOL bCont = TRUE;
+
+ while ((FALSE == ::HttpSendRequest(hRequest, NULL, NULL, NULL, NULL))
+ && bCont ) {
+ // We might have an invalid CA.
+ DWORD dwErrorCode = GetLastError();
+
+ switch(dwErrorCode) {
+ case E_JDHELPER_TIMEOUT:
+ case E_JDHELPER_NAME_NOT_RESOLVED:
+ case E_JDHELPER_CANNOT_CONNECT: {
+ bCont = FALSE;
+ // Display the information dialog
+ if (bUIFeedback) {
+ // decrement download counter to prevent progress
+ // dialog from popping up while the message box is
+ // up
+ m_dlg->bundleInstallComplete();
+ if (dwErrorCode == E_JDHELPER_TIMEOUT) {
+ bRetryHttpRequest =
+ (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT,
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL));
+ } else {
+ bRetryHttpRequest =
+ (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE,
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL));
+ }
+ // re-increment counter because it will be decremented
+ // again upon return
+ m_dlg->bundleInstallStart();
+ bCont = bRetryHttpRequest;
+ }
+ break;
+ }
+ case ERROR_INTERNET_INVALID_CA:
+ case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+ case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+ case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
+ case ERROR_INTERNET_INCORRECT_PASSWORD:
+ case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+ default: {
+ // Unless the user agrees to continue, we just
+ // abandon now !
+ bCont = FALSE;
+
+ // Make sure to test the return code from
+ // InternetErrorDlg user may click OK or Cancel. In
+ // case of Cancel, request should not be resubmitted
+ if (bUIFeedback) {
+ if (ERROR_SUCCESS == ::InternetErrorDlg(
+ NULL, hRequest,
+ dwErrorCode,
+ FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
+ FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
+ FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
+ NULL))
+ bCont = TRUE;
+ }
+ }
+ }
+ }
+
+ if (bCont == FALSE) {
+ // User has denied the request
+ dwDownloadError = 1;
+ __leave;
+ }
+
+ //
+ // Read HTTP status code
+ //
+ DWORD dwErrorCode = GetLastError();
+ DWORD dwStatus=0;
+ DWORD dwStatusSize = sizeof(DWORD);
+
+ if (FALSE == ::HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER |
+ HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL)) {
+ dwErrorCode = GetLastError();
+ }
+
+ bCont = TRUE;
+ while ((dwStatus == HTTP_STATUS_PROXY_AUTH_REQ ||
+ dwStatus == HTTP_STATUS_DENIED) &&
+ bCont) {
+ int result = ::InternetErrorDlg(GetDesktopWindow(), hRequest, ERROR_INTERNET_INCORRECT_PASSWORD,
+ FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
+ FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
+ FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
+ NULL);
+ if (ERROR_CANCELLED == result) {
+ bCont = FALSE;
+ }
+ else {
+ ::HttpSendRequest(hRequest, NULL, 0, NULL, 0);
+
+ // Reset buffer length
+ dwStatusSize = sizeof(DWORD);
+
+ ::HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER |
+ HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize,
+ NULL);
+ }
+ }
+
+ if (dwStatus == HTTP_STATUS_OK ||
+ dwStatus == HTTP_STATUS_PARTIAL_CONTENT) {
+ // Determine content length, so we may show the progress bar
+ // meaningfully
+ //
+ nContentLength = 0;
+ DWORD nLengthSize = sizeof(DWORD);
+ ::HttpQueryInfo(hRequest,
+ HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
+ &nContentLength, &nLengthSize, NULL);
+
+ if (nContentLength <= 0) {
+ // If can't estimate content length, estimate it
+ // to be 6MB
+ nContentLength = 15000000;
+ }
+ else if (rangereq && (fileSize != 0) &&
+ (nContentLength == fileSize)) {
+ // If the file is already downloaded completely and then
+ // we send a range request, the whole file is sent instead
+ // of nothing. So avoid downloading again.
+ // Some times return value is 206, even when whole file
+ // is sent. So check if "Content-range:" is present in the
+ // reply
+ char buffer[256];
+ DWORD length = sizeof(buffer);
+ if(!HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_RANGE,
+ buffer, &length, NULL)) {
+ if(HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED,
+ buffer, &length, NULL)) {
+ SYSTEMTIME systime;
+ FILETIME filtime;
+ InternetTimeToSystemTime(buffer, &systime, NULL);
+ SystemTimeToFileTime(&systime, &filtime);
+ if ((CompareFileTime(&tWrite, &filtime)) == 1) {
+ // no need to download
+ dwDownloadError = 0;
+ __leave;
+ }
+ }
+ else {
+ ::SetFilePointer(hFile, 0, 0, FILE_BEGIN);
+ ::SetEndOfFile(hFile); // truncate the file
+ }
+ }
+
+ }
+
+ TCHAR szBuffer[8096];
+ DWORD dwBufferSize = 8096;
+
+ // Read from HTTP connection and write into
+ // destination file
+ //
+ DWORD nRead = 0;
+ DWORD dwTotalRead = 0;
+ BOOL bCancel = FALSE;
+
+ if (dwStatus == HTTP_STATUS_PARTIAL_CONTENT) {
+ // If we are using resumable download, fake
+ // start time so it looks like we have begun
+ // the download several minutes again.
+ //
+ m_startTime = m_startTime - 100;
+
+ ::SetFilePointer(hFile, 0, 0, FILE_END); // seek to end
+ }
+ else {
+ ::SetFilePointer(hFile, 0, 0, FILE_BEGIN);
+ ::SetEndOfFile(hFile); // truncate the file
+ }
+
+ do {
+ nRead=0;
+
+ if (::InternetReadFile(hRequest, szBuffer, dwBufferSize,
+ &nRead)) {
+ if (nRead) {
+ DWORD dwNumberOfBytesWritten = NULL;
+
+ BOOL ret = WriteFile(hFile, szBuffer, nRead,
+ &dwNumberOfBytesWritten, NULL);
+
+ if (!ret) {
+ // WriteFile failed
+ if (bUIFeedback) {
+ if (GetLastError() == ERROR_DISK_FULL) {
+ bRetryHttpRequest =
+ (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_DISK_FULL_ERROR,
+ IDS_DISK_FULL_ERROR_CAPTION,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ wName));
+ } else {
+ bRetryHttpRequest =
+ (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_DISK_WRITE_ERROR,
+ IDS_DISK_WRITE_ERROR_CAPTION,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ wName));
+ }
+ if (!bRetryHttpRequest) {
+ dwDownloadError = 1;
+ break;
+ }
+ }
+ continue;
+ }
+ }
+
+ dwTotalRead += nRead;
+
+ // update download progress dialog
+ m_dlg->OnProgress(nRead);
+ // Check if download has been cancelled
+ if (m_dlg->isDownloadCancelled()) {
+ m_dlg->decrementProgressMax(nContentLength,
+ dwTotalRead);
+ bCancel = TRUE;
+ break;
+ }
+
+ }
+ else {
+ bCancel = TRUE;
+ break;
+ }
+ }
+ while (nRead);
+
+
+ if (bCancel) {
+ // User has cancelled the operation or InternetRead failed
+ // don't do return here, we need to cleanup
+ dwDownloadError = 1;
+ __leave;
+ }
+ }
+ else if (dwStatus == 416 && (fileSize != 0) &&
+ (fileSize != 0xFFFFFFFF)) {
+ // This error could be returned, When the full file exists
+ // and a range request is sent with range beyond filessize.
+ // The best way to fix this is in future is, to send HEAD
+ // request and get filelength before sending range request.
+ dwDownloadError = 0;
+ __leave;
+ }
+ else if (dwStatus == 403) { // Forbidden from Akamai means we need to get a new download token
+ JNIEnv *env = m_dlg->getJNIEnv();
+ jclass exceptionClass = env->FindClass("java/net/HttpRetryException");
+ if (exceptionClass == NULL) {
+ /* Unable to find the exception class, give up. */
+ __leave;
+ }
+ jmethodID constructor;
+ constructor = env->GetMethodID(exceptionClass,
+ "<init>", "(Ljava/lang/String;I)V");
+ if (constructor != NULL) {
+ jobject exception = env->NewObject(exceptionClass,
+ constructor, env->NewStringUTF("Forbidden"),
+ 403);
+ env->Throw((jthrowable) exception);
+ }
+ __leave;
+ }
+ else if(dwStatus >= 400 && dwStatus < 600) {
+ /* NB: Following case seems to be never used!
+
+ HTTP_STATUS_FORBIDDEN is the same as 403 and
+ 403 was specially handled few lines above! */
+ if (dwStatus == HTTP_STATUS_FORBIDDEN) {
+ if (bUIFeedback) {
+ bRetryHttpRequest = (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_FORBIDDEN,
+ IDS_HTTP_INSTRUCTION_FORBIDDEN,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ L"403"));
+ }
+ }
+ else if (dwStatus == HTTP_STATUS_SERVER_ERROR) {
+ if (bUIFeedback) {
+ bRetryHttpRequest = (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_SERVER_ERROR,
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ L"500"));
+ }
+ }
+ else if (dwStatus == HTTP_STATUS_SERVICE_UNAVAIL) {
+ if (numberOfRetry < 5) {
+ // If the server is busy, automatically retry
+
+ // We wait couple seconds before retry to avoid
+ // congestion
+ for (long i = (long) secondsToWait; i >= 0; i--) {
+ // Update status
+ if (bUIFeedback) {
+ char szBuffer[BUFFER_SIZE];
+ ::LoadString(_Module.GetResourceInstance(),
+ IDS_DOWNLOAD_STATUS_RETRY, szStatus,
+ BUFFER_SIZE);
+ wsprintf(szBuffer, szStatus, i);
+
+ ::SetWindowText(hProgressInfo, szBuffer);
+ }
+
+ // Sleep 1 second
+ ::Sleep(1000);
+ }
+
+ // We use a semi-binary backoff algorithm to
+ // determine seconds to wait
+ numberOfRetry += 1;
+ secondsToWait = secondsToWait + 30;
+ bRetryHttpRequest = TRUE;
+
+ continue;
+ }
+ else {
+ if (bUIFeedback) {
+ bRetryHttpRequest = (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL,
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ L"503"));
+
+ if (bRetryHttpRequest) {
+ numberOfRetry = 0;
+ secondsToWait = 60;
+ continue;
+ }
+ }
+ }
+ }
+ else {
+ if (bUIFeedback) {
+ WCHAR szBuffer[10];
+ _snwprintf(szBuffer, 10, L"%d", dwStatus);
+ bRetryHttpRequest = (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_OTHER,
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ szBuffer));
+ }
+ }
+ if (!bRetryHttpRequest) {
+ dwDownloadError = 1;
+ }
+ }
+ else {
+ if (bUIFeedback) {
+ WCHAR szBuffer[10];
+ _snwprintf(szBuffer, 10, L"%d", dwStatus);
+ bRetryHttpRequest = (IDRETRY == m_dlg->SafeMessageBox(
+ IDS_HTTP_STATUS_OTHER,
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL,
+ szBuffer));
+ }
+ if (!bRetryHttpRequest) {
+ dwDownloadError = 1;
+ }
+ }
+
+
+
+ // Close HTTP request
+ //
+ // This is necessary if the HTTP request
+ // is retried
+ if (hRequest)
+ ::InternetCloseHandle(hRequest);
+ if (hFile != INVALID_HANDLE_VALUE) {
+ ::CloseHandle(hFile);
+ hFile = INVALID_HANDLE_VALUE;
+ }
+ }
+ while (bRetryHttpRequest);
+ }
+ __finally {
+ if (hRequest)
+ ::InternetCloseHandle(hRequest);
+
+ if (hConnect)
+ ::InternetCloseHandle(hConnect);
+
+ if (hOpen)
+ ::InternetCloseHandle(hOpen);
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ ::CloseHandle(hFile);
+ }
+
+
+
+ // Exit dialog
+ if (dwDownloadError == 0) {
+ return S_OK;
+ } else {
+ DeleteFile(szLocalFile);
+ return E_FAIL;
+ }
+}
diff --git a/src/windows/native/sun/jkernel/DownloadHelper.h b/src/windows/native/sun/jkernel/DownloadHelper.h
new file mode 100644
index 000000000..2896ebd05
--- /dev/null
+++ b/src/windows/native/sun/jkernel/DownloadHelper.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef BUFFER_SIZE
+#define BUFFER_SIZE 2048
+#endif
+
+#define E_JDHELPER_TIMEOUT 12002
+#define E_JDHELPER_NAME_NOT_RESOLVED 12007
+#define E_JDHELPER_CANNOT_CONNECT 12029
+
+#include <jni.h>
+#include "DownloadDialog.h"
+
+class DownloadHelper {
+public:
+ DownloadHelper();
+ ~DownloadHelper();
+
+ HRESULT doDownload();
+
+ void setFile(LPCTSTR pszFileName) {
+ m_pszFileName = pszFileName;
+ }
+
+ void setURL(LPCTSTR pszURL) {
+ m_pszURL = pszURL;
+ }
+
+ void setNameText(LPTSTR pszNameText) {
+ m_pszNameText = pszNameText;
+ }
+
+ void setShowProgressDialog(BOOL showProgress) {
+ m_showProgressDialog = showProgress;
+ }
+
+ void setDownloadDialog(CDownloadDialog* dialog) {
+ m_dlg = dialog;
+ }
+
+ void setJavaVM(JavaVM *jvm) {
+ m_jvm = jvm;
+ }
+
+private:
+ HRESULT DownloadFile(const TCHAR* szURL, const TCHAR* szLocalFile,
+ BOOL bResumable, BOOL bUIFeedback);
+
+ BOOL m_showProgressDialog;
+ LPCTSTR m_pszURL;
+ LPCTSTR m_pszFileName;
+ LPTSTR m_pszNameText;
+ time_t m_startTime;
+ CComAutoCriticalSection m_csDownload;
+ CDownloadDialog* m_dlg;
+ JavaVM* m_jvm;
+};
diff --git a/src/windows/native/sun/jkernel/graphics/bullet.bmp b/src/windows/native/sun/jkernel/graphics/bullet.bmp
new file mode 100644
index 000000000..f54142bcf
--- /dev/null
+++ b/src/windows/native/sun/jkernel/graphics/bullet.bmp
Binary files differ
diff --git a/src/windows/native/sun/jkernel/graphics/cautionshield32.bmp b/src/windows/native/sun/jkernel/graphics/cautionshield32.bmp
new file mode 100644
index 000000000..01f82f4df
--- /dev/null
+++ b/src/windows/native/sun/jkernel/graphics/cautionshield32.bmp
Binary files differ
diff --git a/src/windows/native/sun/jkernel/graphics/java-icon.ico b/src/windows/native/sun/jkernel/graphics/java-icon.ico
new file mode 100644
index 000000000..f98f78089
--- /dev/null
+++ b/src/windows/native/sun/jkernel/graphics/java-icon.ico
Binary files differ
diff --git a/src/windows/native/sun/jkernel/graphics/masthead.bmp b/src/windows/native/sun/jkernel/graphics/masthead.bmp
new file mode 100644
index 000000000..f4fa2a8f1
--- /dev/null
+++ b/src/windows/native/sun/jkernel/graphics/masthead.bmp
Binary files differ
diff --git a/src/windows/native/sun/jkernel/graphics/warningmasthead.bmp b/src/windows/native/sun/jkernel/graphics/warningmasthead.bmp
new file mode 100644
index 000000000..65b2a3246
--- /dev/null
+++ b/src/windows/native/sun/jkernel/graphics/warningmasthead.bmp
Binary files differ
diff --git a/src/windows/native/sun/jkernel/kernel.cpp b/src/windows/native/sun/jkernel/kernel.cpp
new file mode 100644
index 000000000..354b47cf2
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel.cpp
@@ -0,0 +1,1621 @@
+/*
+ * 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.
+ */
+
+#define _WIN32_WINNT 0x0500
+#define WINVER 0x0500
+
+#include "stdafx.h"
+#include <shlobj.h>
+#include <atlbase.h>
+#include <locale.h>
+
+CComModule _Module;
+
+#include <atlwin.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "Windows.h"
+#include "WinNT.h"
+#include <shellapi.h>
+#include "DownloadDialog.h"
+#include "DownloadHelper.h"
+#include "kernel.h"
+#include "sun_jkernel_DownloadManager.h"
+#include "sun_jkernel_Bundle.h"
+#include "sun_jkernel_Mutex.h"
+#include "sun_jkernel_BackgroundDownloader.h"
+#include <stdio.h>
+#include <windows.h>
+#include <conio.h>
+#include <tchar.h>
+#include <tchar.h>
+#include <sddl.h>
+#include <Aclapi.h>
+#include <strsafe.h>
+
+BOOL IsPlatformWindowsVista();
+
+#define BUFSIZE 4096
+
+#define JBROKERPIPE "\\\\.\\pipe\\jbrokerpipe"
+#define JREMAINKEY "SOFTWARE\\JavaSoft\\Java Runtime Environment"
+#define JRE_VERSION_REGISTRY_KEY JREMAINKEY "\\" VERSION
+#define ReleaseAndClose(mutex) \
+ if (mutex != NULL) { \
+ ReleaseMutex(mutex); \
+ CloseHandle(mutex); \
+ mutex = NULL; \
+ }
+
+#define KERNEL_DEBUG false
+
+// used to inform kernel that we believe it is running in high integrity
+#define JBROKER_KEY "-Dkernel.spawned.from.jbroker=true -Dkernel.background.download=false"
+
+// this is only available on Vista SDK, hard code it here for now
+#define LABEL_SECURITY_INFORMATION (0x00000010L)
+
+// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity
+LPCSTR LOW_INTEGRITY_SDDL_SACL = "S:(ML;;NW;;;LW)";
+
+CDownloadDialog dlg;
+BOOL createDialog = TRUE;
+
+CComAutoCriticalSection m_csCreateDialog;
+
+typedef BOOL (WINAPI *LPFNInitializeSecurityDescriptor)(
+ PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
+typedef BOOL (WINAPI *LPFNSetSecurityDescriptorDacl)(
+ PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
+ BOOL bDaclDefaulted);
+
+typedef BOOL (WINAPI *LPFNConvertStringSecurityDescriptorToSecurityDescriptorA)(
+ LPCSTR StringSecurityDescriptor, DWORD StringSDRevision,
+ PSECURITY_DESCRIPTOR* SecurityDescriptor,
+ PULONG SecurityDescriptorSize);
+
+typedef BOOL (WINAPI *LPFNGetSecurityDescriptorSacl)(
+ PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent,
+ PACL* pSacl, LPBOOL lpbSaclDefaulted);
+
+typedef DWORD (WINAPI *LPFNSetSecurityInfo)(HANDLE handle,
+ SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
+ PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl);
+
+BOOL APIENTRY DllMain( HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ return TRUE;
+}
+
+char* getStringPlatformChars(JNIEnv* env, jstring jstr) {
+ char *result = NULL;
+ size_t len;
+ const jchar* utf16 = env->GetStringChars(jstr, NULL);
+ len = wcstombs(NULL, utf16, env->GetStringLength(jstr) * 4) + 1;
+ if (len == -1)
+ return NULL;
+ result = (char*) malloc(len);
+ if (wcstombs(result, utf16, len) == -1)
+ return NULL;
+ env->ReleaseStringChars(jstr, utf16);
+ return result;
+}
+
+bool SetObjectToLowIntegrity ( HANDLE hObject,
+ SE_OBJECT_TYPE type = SE_KERNEL_OBJECT ) {
+
+ bool bRet = false;
+ DWORD dwErr = ERROR_SUCCESS;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pSacl = NULL;
+ BOOL fSaclPresent = FALSE;
+ BOOL fSaclDefaulted = FALSE;
+
+ // initialize function pointers
+ HMODULE hModule = LoadLibrary("Advapi32.dll");
+
+ // ConvertStringSecurityDescriptorToSecurityDescriptorA
+ LPFNConvertStringSecurityDescriptorToSecurityDescriptorA
+ lpfnConvertStringSecurityDescriptorToSecurityDescriptorA =
+ (LPFNConvertStringSecurityDescriptorToSecurityDescriptorA)GetProcAddress(
+ hModule,
+ "ConvertStringSecurityDescriptorToSecurityDescriptorA");
+
+ // GetSecurityDescriptorSacl
+ LPFNGetSecurityDescriptorSacl lpfnGetSecurityDescriptorSacl =
+ (LPFNGetSecurityDescriptorSacl)GetProcAddress(hModule,
+ "GetSecurityDescriptorSacl");
+
+ // SetSecurityInfo
+ LPFNSetSecurityInfo lpfnSetSecurityInfo =
+ (LPFNSetSecurityInfo)GetProcAddress(hModule,
+ "SetSecurityInfo");
+
+ if (lpfnConvertStringSecurityDescriptorToSecurityDescriptorA == NULL ||
+ lpfnGetSecurityDescriptorSacl == NULL ||
+ lpfnSetSecurityInfo == NULL) {
+ if (KERNEL_DEBUG) {
+ printf("Fail to initialize function pointer\n");
+ }
+ FreeLibrary(hModule);
+ return FALSE;
+ }
+
+ // Set object to lower integrity
+ if ( lpfnConvertStringSecurityDescriptorToSecurityDescriptorA(
+ LOW_INTEGRITY_SDDL_SACL, SDDL_REVISION_1, &pSD, NULL ) ) {
+ if ( lpfnGetSecurityDescriptorSacl(
+ pSD, &fSaclPresent, &pSacl, &fSaclDefaulted ) ) {
+ dwErr = lpfnSetSecurityInfo(
+ hObject, type, LABEL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, pSacl );
+
+ bRet = (ERROR_SUCCESS == dwErr);
+ }
+
+ LocalFree( pSD );
+ }
+
+ FreeLibrary(hModule);
+ return bRet;
+}
+
+
+JNIEXPORT jlong JNICALL Java_sun_jkernel_Mutex_createNativeMutex
+ (JNIEnv *env , jclass cls, jstring id) {
+ SECURITY_ATTRIBUTES sa;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ BOOL saInitialized = FALSE;
+
+ // initialize function pointers
+ HMODULE hModule = LoadLibrary("Advapi32.dll");
+
+ // InitializeSecurityDescriptor
+ LPFNInitializeSecurityDescriptor lpfnInitializeSecurityDescriptor =
+ (LPFNInitializeSecurityDescriptor)GetProcAddress(hModule,
+ "InitializeSecurityDescriptor");
+
+ // SetSecurityDescriptorDacl
+ LPFNSetSecurityDescriptorDacl lpfnSetSecurityDescriptorDacl =
+ (LPFNSetSecurityDescriptorDacl)GetProcAddress(hModule,
+ "SetSecurityDescriptorDacl");
+
+ if (lpfnInitializeSecurityDescriptor != NULL &&
+ lpfnSetSecurityDescriptorDacl != NULL) {
+
+ // Initialize a security descriptor.
+ pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
+ SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (NULL == pSD) {
+ if (KERNEL_DEBUG) {
+ printf("LocalAlloc Error %u\n", GetLastError());
+ }
+ FreeLibrary(hModule);
+ return NULL;
+ }
+
+ if (!lpfnInitializeSecurityDescriptor(pSD,
+ SECURITY_DESCRIPTOR_REVISION)) {
+ if (KERNEL_DEBUG) {
+ printf("InitializeSecurityDescriptor Error %u\n", GetLastError());
+ }
+ FreeLibrary(hModule);
+ return NULL;
+
+ }
+ // Add the ACL to the security descriptor.
+ if (!lpfnSetSecurityDescriptorDacl(pSD,
+ TRUE, // bDaclPresent flag
+ NULL, // NULL DACL is assigned to the security descriptor,
+ // which allows all access to the object.
+ // This is to allow the mutex to be accessbile by
+ // all users; The background downloader launched
+ // by the installer will be running as SYSTEM user;
+ // while other java process started by the current
+ // user will be running as the current username.
+ FALSE)) // not a default DACL
+ {
+ if (KERNEL_DEBUG) {
+ printf("SetSecurityDescriptorDacl Error %u\n",
+ GetLastError());
+ }
+ FreeLibrary(hModule);
+ return NULL;
+ }
+
+ // Initialize a security attributes structure.
+ sa.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+
+ saInitialized = TRUE;
+ FreeLibrary(hModule);
+ }
+
+ HANDLE m = CreateMutex(saInitialized ? &sa : NULL, FALSE,
+ (LPCSTR) getStringPlatformChars(env, id));
+ if (m == NULL) {
+ if (KERNEL_DEBUG) {
+ printf("CreateMutex Error %u\n", GetLastError());
+ }
+ }
+
+ // set the mutex object to low integrity on vista, so the mutex
+ // can be accessed by different integrity level
+ if (IsPlatformWindowsVista()) {
+ if (!SetObjectToLowIntegrity(m)) {
+ if (KERNEL_DEBUG) {
+ printf("Fail to set Mutex object to low integrity\n");
+ }
+ }
+ }
+ return (jlong)m ;
+}
+
+
+HANDLE getMutexHandle(JNIEnv *env, jobject mutex) {
+ jfieldID handle = env->GetFieldID(env->GetObjectClass(mutex), "handle", "J");
+ return (HANDLE) env->GetLongField(mutex, handle);
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_Mutex_acquire__I
+ (JNIEnv *env, jobject mutex, jint timeout) {
+ HANDLE hmutex = getMutexHandle(env, mutex);
+ if (hmutex != NULL) {
+ int result = WaitForSingleObject(hmutex, timeout);
+ if (result == WAIT_ABANDONED)
+ result = WaitForSingleObject(hmutex, timeout);
+ return (result == WAIT_OBJECT_0);
+ }
+ else
+ return false;
+}
+
+void ThrowByName(JNIEnv *env, const char *name, const char *msg) {
+ jclass cls = env->FindClass(name);
+ /* if cls is NULL, an exception has already been thrown */
+ if (cls != NULL) {
+ env->ThrowNew(cls, msg);
+ }
+ /* free the local ref */
+ env->DeleteLocalRef(cls);
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_acquire__
+ (JNIEnv *env, jobject mutex) {
+ if (!Java_sun_jkernel_Mutex_acquire__I(env, mutex, INFINITE)) {
+ // failed to acquire mutex, most likely because it was already disposed
+ ThrowByName(env, "java/lang/IllegalStateException",
+ "error acquiring mutex");
+ }
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_release
+ (JNIEnv *env, jobject mutex) {
+ HANDLE hmutex = getMutexHandle(env, mutex);
+ if (hmutex != NULL)
+ ReleaseMutex(hmutex);
+ else
+ ThrowByName(env, "java/lang/IllegalStateException",
+ "releasing disposed mutex");
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_destroyNativeMutex
+ (JNIEnv *env, jobject mutex) {
+ HANDLE hmutex = getMutexHandle(env, mutex);
+ if (hmutex != NULL) {
+ Java_sun_jkernel_Mutex_release(env, mutex);
+ CloseHandle(hmutex);
+ }
+}
+
+void createDownloadWindowProc(LPVOID lpParameter) {
+ CDownloadDialog* pDlg = (CDownloadDialog *) lpParameter;
+
+ pDlg->delayedDoModal();
+
+ // dialog destroyed, need to create a new one next time
+ createDialog = TRUE;
+}
+
+
+void createDownloadWindow(LPVOID lpParameter) {
+ // Create a new thread for download window
+ DWORD dwThreadId = NULL;
+ ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) createDownloadWindowProc, lpParameter, 0, &dwThreadId);
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_bundleInstallComplete
+ (JNIEnv *env, jclass dm) {
+ dlg.bundleInstallComplete();
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_bundleInstallStart
+ (JNIEnv *env, jclass dm) {
+
+ dlg.bundleInstallStart();
+}
+
+typedef HRESULT (WINAPI *LPFNIEIsProtectedModeProcess)(BOOL *pbResult);
+
+BOOL isRunningIEProtectedMode() {
+
+ HMODULE hModule = NULL;
+ LPFNIEIsProtectedModeProcess lpfnIEIsProtectedModeProcess;
+
+ __try {
+ hModule = LoadLibrary("ieframe.dll");
+ if (hModule != NULL) {
+
+ lpfnIEIsProtectedModeProcess = (LPFNIEIsProtectedModeProcess)
+ GetProcAddress(hModule, "IEIsProtectedModeProcess");
+
+ if (lpfnIEIsProtectedModeProcess != NULL) {
+ BOOL bProtectedMode = FALSE;
+ HRESULT hr = lpfnIEIsProtectedModeProcess(&bProtectedMode);
+ if ( SUCCEEDED(hr) && bProtectedMode ) {
+ // IE is running in protected mode
+ return TRUE;
+ } else {
+ // IE isn't running in protected mode
+ return FALSE;
+ }
+ }
+ }
+ } __finally {
+ if (hModule != NULL) {
+ FreeLibrary(hModule);
+ }
+ }
+ return FALSE;
+}
+
+/* Return TRUE if current running platform is Windows Vista, FALSE otherwise */
+BOOL IsPlatformWindowsVista() {
+ static BOOL initialized = FALSE;
+ static BOOL isVista = FALSE;
+ OSVERSIONINFO osvi;
+
+ if (initialized) {
+ return isVista;
+ }
+
+ // Initialize the OSVERSIONINFO structure.
+ ZeroMemory( &osvi, sizeof( osvi ) );
+ osvi.dwOSVersionInfoSize = sizeof( osvi );
+
+ GetVersionEx( &osvi ); // Assume this function succeeds.
+
+ if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ osvi.dwMajorVersion == 6 ) {
+ isVista = TRUE;
+ } else {
+ isVista = FALSE;
+ }
+
+ initialized = TRUE;
+
+ return isVista;
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isIEProtectedMode
+ (JNIEnv *env, jclass dm) {
+
+ if (isRunningIEProtectedMode()) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isWindowsVista
+ (JNIEnv *env, jclass dm) {
+
+ if (IsPlatformWindowsVista()) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int sendMessageToBroker(const char * message) {
+ char ackString[1024];
+ HANDLE hp = INVALID_HANDLE_VALUE;
+
+ while (hp == INVALID_HANDLE_VALUE) {
+ hp = CreateNamedPipe(_T(JBROKERPIPE),
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE ,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ 1, // number of pipes that can exist
+ 1024, // output buffer
+ 1024, // input buffer
+ 0, // timeout
+ NULL); // security attributes
+
+ if (hp == INVALID_HANDLE_VALUE) {
+ DWORD err = GetLastError();
+ // we only allow one instance of the pipe; if the instance
+ // already exists, we will get ERROR_ACCESS_DENIED, which means
+ // some other process is using the pipe, so let's try again
+ if (err != ERROR_ACCESS_DENIED && err != ERROR_PIPE_BUSY) {
+ // create pipe failed
+ return 0;
+ }
+ // pipe instance might be in use, keep trying
+ }
+ }
+
+ // Wait for the client to connect; if it succeeds,
+ // the function returns a nonzero value. If the function
+ // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
+ BOOL fConnected = ConnectNamedPipe(hp, NULL) ?
+ TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+
+ if (fConnected)
+ {
+ // Send message to the pipe server.
+ DWORD cbWritten;
+
+ BOOL fSuccess = WriteFile(
+ hp, // pipe handle
+ message, // message
+ (strlen(message)+1)*sizeof(char), // message length
+ &cbWritten, // bytes written
+ NULL); // not overlapped
+
+ if (!fSuccess)
+ {
+ // WriteFile failed
+ CloseHandle(hp);
+ return 0;
+ }
+
+ // wait for ack from server
+ DWORD cbRead;
+ TCHAR chBuf[BUFSIZE];
+
+ do
+ {
+ // Read from the pipe.
+ fSuccess = ReadFile(
+ hp, // pipe handle
+ chBuf, // buffer to receive reply
+ BUFSIZE*sizeof(TCHAR), // size of buffer
+ &cbRead, // number of bytes read
+ NULL); // not overlapped
+
+ if (! fSuccess && GetLastError() != ERROR_MORE_DATA)
+ break;
+
+ sprintf(ackString, "%s", chBuf);
+
+
+ } while (!fSuccess); // repeat loop if ERROR_MORE_DATA
+ }
+
+ CloseHandle(hp);
+
+ if (strcmp(ackString, "SUCCESS") == 0) {
+ // server completed move command successfully
+ return 1;
+ }
+
+ return 0;
+}
+
+int sendMoveMessageToBroker(const char * fromPath, const char * userHome) {
+ // Send move message
+ char * movecmd = "MOVEFILE";
+
+ char * msg = (char*)malloc((strlen(fromPath) + strlen(movecmd) +
+ strlen(userHome) + 3) * sizeof(char));
+
+ sprintf(msg, "%s*%s*%s", movecmd, fromPath, userHome);
+
+ return sendMessageToBroker(msg);
+}
+
+int sendMoveDirMessageToBroker(const char * fromPath, const char * userHome) {
+ // Send move dir message
+ char * movecmd = "MOVEDIR";
+
+ char * msg = (char*)malloc((strlen(fromPath) + strlen(movecmd) +
+ strlen(userHome) + 3) * sizeof(char));
+
+ sprintf(msg, "%s*%s*%s", movecmd, fromPath, userHome);
+
+ return sendMessageToBroker(msg);
+}
+
+
+int sendKillMessageToBroker() {
+ // Send move message
+ char * killcmd = "KILLBROKER";
+ return sendMessageToBroker(killcmd);
+}
+
+
+int sendPerformCompletionMessageToBroker(const char *javaHome) {
+ const char *cmd = "PERFORMCOMPLETION";
+
+ int result = sendMessageToBroker(cmd);
+
+ if (result)
+ sendKillMessageToBroker();
+ return result;
+}
+
+int getConstantInt(JNIEnv *env, jclass cls, const char *name) {
+ jfieldID handle = env->GetStaticFieldID(cls, name, "I");
+ return env->GetStaticIntField(cls, handle);
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_displayError
+ (JNIEnv *env, jclass dm, jint code, jstring arg) {
+ int messageId = IDS_FATAL_ERROR;
+ int titleId = IDS_ERROR_CAPTION;
+ if (code == getConstantInt(env, dm, "ERROR_MALFORMED_BUNDLE_PROPERTIES"))
+ messageId = IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES;
+ else if (code == getConstantInt(env, dm, "ERROR_DOWNLOADING_BUNDLE_PROPERTIES"))
+ messageId = IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES;
+ else if (code == getConstantInt(env, dm, "ERROR_MALFORMED_URL"))
+ messageId = IDS_ERROR_MALFORMED_URL;
+ char message[BUFFER_SIZE];
+ char rawMessage[BUFFER_SIZE];
+ char title[BUFFER_SIZE];
+ ::LoadString(_Module.GetModuleInstance(), titleId, title, BUFFER_SIZE);
+ ::LoadString(_Module.GetModuleInstance(), messageId, rawMessage, BUFFER_SIZE);
+ if (arg != NULL) {
+ char *chars = getStringPlatformChars(env, arg);
+ sprintf(message, rawMessage, chars);
+ }
+ else
+ strcpy(message, rawMessage);
+
+ MessageBox(NULL, message, title, MB_OK|MB_TASKMODAL);
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_askUserToRetryDownloadOrQuit
+ (JNIEnv *env, jclass dm, jint code) {
+
+ int ret;
+ if (code == getConstantInt(env, dm, "ERROR_DISK_FULL")) {
+ ret = dlg.SafeMessageBox(IDS_DISK_FULL_ERROR,
+ IDS_DISK_FULL_ERROR_CAPTION,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL);
+ } else {
+ ret = dlg.SafeMessageBox(IDS_DOWNLOAD_RETRY_TEXT,
+ IDS_DOWNLOAD_RETRY,
+ IDS_ERROR_CAPTION,
+ DIALOG_ERROR_RETRYCANCEL);
+ }
+ if (ret != IDRETRY) {
+ // user choose to exit, return 0
+ return JNI_FALSE;
+ }
+
+ // return 1 (retry the download)
+ return JNI_TRUE;
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_startBackgroundDownloadWithBrokerImpl
+(JNIEnv *env, jclass dm, jstring command) {
+
+ char* szCommand = getStringPlatformChars(env, command);
+
+ // Send createprocess message
+ char * createproccmd = "STARTBACKGROUNDDOWNLOAD";
+
+ char * msg = (char*)malloc((strlen(createproccmd) + strlen(szCommand) + 2) * sizeof(char));
+
+ sprintf(msg, "%s*%s", createproccmd, szCommand);
+
+ sendMessageToBroker(msg);
+
+ free(szCommand);
+}
+
+
+void getParent(const TCHAR *path, TCHAR *dest) {
+ char* lastSlash = max(strrchr(path, '\\'), strrchr(path, '/'));
+ if (lastSlash == NULL) {
+ *dest = NULL;
+ return;
+ }
+ if (path != dest)
+ strcpy(dest, path);
+ *lastSlash = NULL;
+}
+
+
+bool createProcess(const TCHAR *path, const TCHAR *args) {
+ SHELLEXECUTEINFOA shInfo;
+
+ shInfo.cbSize = sizeof(SHELLEXECUTEINFOA);
+ shInfo.fMask = 0;
+ shInfo.hwnd = NULL;
+ shInfo.lpVerb = "runas";
+ shInfo.lpFile = path;
+ shInfo.lpParameters = args;
+ shInfo.lpDirectory = NULL;
+ shInfo.nShow = SW_NORMAL;
+ shInfo.hInstApp = NULL;
+
+ int result = (int) ::ShellExecuteExA(&shInfo);
+ // ShellExecute is documented to return >32 on success, but I'm consistently
+ // getting a return of 1 despite obviously successful results. 1 is not a
+ // documented return code from ShellExecute, and this may have something to
+ // do with the fact that we're using an undocumented verb in the first place
+ // ("runas").
+ return result > 32 || result == 1;
+}
+
+
+bool launchJBroker(const char *szJavaHome) {
+ char szPath[2048];
+ wsprintf(szPath, "%s\\bin\\jbroker.exe", szJavaHome);
+ return createProcess(szPath, NULL);
+}
+
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_launchJBroker
+(JNIEnv *env, jclass dm, jstring javaHomePath) {
+ char* szJavaHome = getStringPlatformChars(env, javaHomePath);
+ bool result = launchJBroker(szJavaHome);
+ free(szJavaHome);
+ return result ? TRUE : FALSE;
+}
+
+
+bool isJBrokerRunning() {
+ HANDLE hMutex = NULL;
+ DWORD ret = 0;
+
+ if (isRunningIEProtectedMode()) {
+
+ // check if jbroker process is running
+ // Use OpenMutex since we have limited access rights.
+ // CreateMutex function will fail with ERROR_ACCESS_DENIED in protected mode
+ hMutex = OpenMutex(SYNCHRONIZE, FALSE, "SunJavaBrokerMutex");
+
+ ret = ::GetLastError();
+
+ if (hMutex != NULL) {
+ CloseHandle(hMutex);
+ }
+
+ if (ret == ERROR_FILE_NOT_FOUND)
+ {
+ // jbroker not running yet, launch it
+ return FALSE;
+ }
+
+ return TRUE;
+
+ } else {
+ hMutex = ::CreateMutex(NULL, TRUE, "SunJavaBrokerMutex");
+
+ if ( (hMutex == NULL) || (::GetLastError() == ERROR_ALREADY_EXISTS)) {
+ // jbroker already running
+ if (hMutex != NULL) ::CloseHandle(hMutex);
+ return TRUE;
+ }
+
+ if (hMutex != NULL) ::CloseHandle(hMutex);
+
+ return FALSE;
+ }
+}
+
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isJBrokerRunning
+(JNIEnv *env, jclass dm) {
+ return isJBrokerRunning() ? TRUE : FALSE;
+}
+
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_moveDirWithBrokerImpl
+ (JNIEnv *env, jclass dm, jstring fromPath, jstring userHome) {
+
+ char* fromPathChars = getStringPlatformChars(env, fromPath);
+
+ char* userHomeChars = getStringPlatformChars(env, userHome);
+
+ int ret = sendMoveDirMessageToBroker(fromPathChars, userHomeChars);
+
+ free(fromPathChars);
+
+ free(userHomeChars);
+
+ if (ret == 0) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_moveFileWithBrokerImpl
+ (JNIEnv *env, jclass dm, jstring fromPath, jstring userHome) {
+
+ char* fromPathChars = getStringPlatformChars(env, fromPath);
+
+ char* userHomeChars = getStringPlatformChars(env, userHome);
+
+ int ret = sendMoveMessageToBroker(fromPathChars, userHomeChars);
+
+ free(fromPathChars);
+
+ free(userHomeChars);
+
+ if (ret == 0) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Throw an exception with the last Windows error code if available.
+ */
+
+void ThrowByNameWithLastError(JNIEnv *env, char *exception, char* msg) {
+ char fullMsg[1024] = {0};
+ if (StringCbPrintf(fullMsg, 1024, "%s. Windows error: %d\n",
+ msg, GetLastError()) != S_OK) {
+
+ // Formatting failed: fall back to msg w/o error code
+ ThrowByName(env, exception, msg);
+ } else {
+ ThrowByName(env, exception, fullMsg);
+ }
+}
+
+/**
+ * Common code for "extra" compression or uncompression. If extra code
+ * not available do nothing but return false. If available, return true
+ * after locating the extra compression library at ".." and the defined
+ * path relative to the native library containing this method's code.
+ * If enabled, compress or uncompress the srcPath file into destpath,
+ * throwing exceptions for errors (see JNI routine docs below for details).
+ */
+
+jboolean extraCommon(BOOL docompress,
+ JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) {
+#ifdef EXTRA_COMP_INSTALL_PATH
+ const char *operation = (docompress == true) ? "e" : "d";
+
+ // This should be shared with the deploy tree and should be defined
+ // in an implementation like LzmaAlone.h. However the deploy build
+ // doesn't exit yet wrt to this function pointer type.
+
+ typedef int (*EXTRACOMPTRTYPE) (int, const char**);
+
+ // Function pointer for invoking the encoder/decoder (uncompressor)
+ static volatile EXTRACOMPTRTYPE mptr = NULL;
+ // Volatile boolean becomes true when mptr init is finished
+
+// Stringifier macros to get the relative library path
+
+#define K_STRING(x) #x
+#define K_GETSTRING(x) K_STRING(x)
+
+ char *srcPathChars = getStringPlatformChars(env, srcPath);
+
+ if (srcPathChars == NULL) {
+ // TODO (for all throw calls). If the class&method are *reliably*
+ // reported to the user these message prefixes are silly.
+ ThrowByName(env, "java/io/IOException",
+ "Bundle.uncompress: GetStringPlatformChars failed");
+ return true;
+ }
+
+ char *destPathChars = getStringPlatformChars(env, destPath);
+ if (destPathChars == NULL) {
+ free(srcPathChars);
+ ThrowByName(env, "java/io/IOException",
+ "Bundle.uncompress: GetStringPlatformChars failed");
+ return true;
+ }
+ if (KERNEL_DEBUG) {
+ printf("LZMA: %s %s to %s\n", operation, srcPathChars, destPathChars);
+ }
+
+
+ // This loop avoids a lot of repetitious code for exception handling.
+ // If any loops are put inside this one be careful to properly
+ // handle exceptions within the inner loops.
+
+ do {
+
+ if (mptr == NULL) {
+
+ // Need to locate and link to the extra compression lib, which
+ // has a pathname relative to the directory containing the library
+ // containing this code, which is assumed to be one directory
+ // "below" the JRE base path. That is, the JRE base path is
+ // assumed to be ".." from the path of this library and then
+ // EXTRA_COMP_INSTALL_PATH from the JRE base path is expected to
+ // be the compression lib path.
+ // But this code is defensive and tries not to fail if the
+ // currently executing library is in ".". It will fail in a
+ // case like this if the extra compression lib path isn't
+ // "./EXTRA_CMP_INSTALL_PATH" (or just "EXTRA_CMP_INSTALL_PATH").
+ // Use macro magic to get the path macro as a string value.
+
+ const char *libRelativePath = K_GETSTRING(EXTRA_COMP_INSTALL_PATH);
+
+ // The max length the base JRE path can be to safely concatenate
+ // libRelativePath, a (possible) separator, and a null terminator.
+ int jreMaxPathLength = MAX_PATH - sizeof(libRelativePath) - 2;
+
+ TCHAR extraLibPath[MAX_PATH] = {0};
+ HMODULE kernel = GetModuleHandle("jkernel");
+ if (kernel != NULL) {
+ DWORD result = GetModuleFileName(kernel, extraLibPath,
+ MAX_PATH-1);
+ if (result > 0) {
+ // remove the name of this library (and maybe a
+ // separator)
+ getParent(extraLibPath, extraLibPath);
+ if (extraLibPath[0] != NULL) {
+ // There was a directory containing the library
+ // (probably "<something or nothing\\>bin"), so
+ // remove that to go up to the assumed JRE base path
+ getParent(extraLibPath, extraLibPath);
+ } else {
+ ThrowByName(env, "java/io/IOException",
+ "bundle uncompression: expected lib path component not found");
+ break;
+ }
+ // This is effectively an assertion that the concat
+ // below cannot overflow
+ if (extraLibPath[0] != NULL) {
+ // Current dir is not ".", so add a separator
+ strcat(extraLibPath, "\\");
+ }
+ if ((strlen(extraLibPath) + 1) > jreMaxPathLength) {
+ ThrowByName(env, "java/io/IOException",
+ "bundle uncompression: JRE base pathname too long");
+ break;
+ }
+ strcat(extraLibPath, libRelativePath);
+ } else {
+ ThrowByName(env, "java/io/IOException",
+ "bundle uncompression: GetModuleFileName failed");
+ break;
+ }
+ } else {
+ ThrowByNameWithLastError(env, "java/io/IOException",
+ "bundle uncompression: GetModuleHandle failed");
+ break;
+ }
+
+ // Load the library and develop a pointer to the decoder routine
+
+ if (KERNEL_DEBUG) {
+ printf("bundle uncompression: extra library path %s\n",
+ extraLibPath);
+ }
+
+ HMODULE handle = LoadLibrary(extraLibPath);
+ if (handle == NULL) {
+ ThrowByNameWithLastError(env, "java/io/IOException",
+ "bundle uncompression: LoadLibrary failed");
+ break;
+ }
+
+ // find the extra uncompression routine
+
+ mptr = (EXTRACOMPTRTYPE) GetProcAddress(handle,
+ "ExtraCompressionMain");
+
+ if (mptr == NULL) {
+ ThrowByNameWithLastError(env, "java/io/IOException",
+ "bundle uncompression: GetProcAddress failed");
+ break;
+ }
+ }
+
+ // Create the arguments for the decoder
+ // Decoder options must go *between* the "d" argument and the
+ // source path arguments and don't forget to keep the 1st arg to
+ // (*mptr) the same as the number of elements of args.
+ const char *args[] = {
+ "", // the shared lib makes no attempt access it's "command name"
+ operation,
+
+ // Special decoder/encoder switch strings would go here
+
+ // For example: "-d24", to set the dictionary size to 16MB
+
+ "-q", // Suppress banner msg output
+
+ // No special option switch strings after here
+
+ srcPathChars,
+ destPathChars
+ };
+ int argc = sizeof(args) / sizeof(const char *);
+ if ((*mptr)(argc, args) != 0) {
+ if (KERNEL_DEBUG) {
+ printf("uncompress lib call failed with args: ");
+ for (int i = 0; i < argc; i++) {
+ printf("%s", args[i]);
+ }
+ printf("\n");
+ }
+ ThrowByName(env, "java/io/IOException",
+ "bundle uncompression: uncompression failed");
+ break;
+ }
+ } while (false);
+
+ free(srcPathChars);
+ free(destPathChars);
+ return TRUE;
+#else
+ if (KERNEL_DEBUG) {
+ printf("LZMA not compiled in!\n");
+ }
+
+ return FALSE;
+#endif // EXTRA_COMP_INSTALL_PATH
+}
+
+/**
+ * Compress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA)
+ * if available, put the compressed data into file destPath and
+ * return true. If extra compression is not available do nothing
+ * with destPath and return false;
+ * @param srcPath the path of the uncompressed file
+ * @param destPath the path of the compressed file, if used
+ * @return true if the extra algorithm was used and destPath created
+ *
+ * @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
+ */
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_Bundle_extraCompress
+ (JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) {
+ return extraCommon(true, env, dm, srcPath, destPath);
+}
+
+/**
+ * Uncompress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA)
+ * if available, put the uncompressed data into file destPath and
+ * return true. If if the extra algorithm is not available, leave the
+ * destination path unchanged and return false;
+ * @param srcPath the path of the file having extra compression
+ * @param destPath the path of the uncompressed file
+ * @return true if the extra algorithm was used
+ *
+ * @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
+ */
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_Bundle_extraUncompress
+ (JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) {
+ return extraCommon(false, env, dm, srcPath, destPath);
+}
+
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_addToTotalDownloadSize
+ (JNIEnv *env, jclass dm, jint size) {
+ dlg.addToTotalContentLength(size);
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_downloadFromURLImpl
+ (JNIEnv *env, jclass dm, jstring url, jobject file, jstring name,
+ jboolean showProgress) {
+ jclass object = env->FindClass("java/lang/Object");
+ jmethodID toString = env->GetMethodID(object, "toString", "()Ljava/lang/String;");
+ jstring urlString = (jstring) env->CallObjectMethod(url, toString);
+ char* urlChars = getStringPlatformChars(env, urlString);
+ if (KERNEL_DEBUG) {
+ printf("Kernel downloadFromURL: %s\n", urlChars);
+ }
+ jstring fileString = (jstring) env->CallObjectMethod(file, toString);
+ char* fileChars = getStringPlatformChars(env, fileString);
+ char* nameChars = getStringPlatformChars(env, name);
+
+ JavaVM *jvm;
+ env->GetJavaVM(&jvm);
+
+ __try
+ {
+
+ m_csCreateDialog.Lock();
+ if (createDialog && showProgress) {
+ // create download progress dialog in a new thread
+ dlg.setJavaVM(jvm);
+ createDownloadWindow(&dlg);
+ createDialog = FALSE;
+ }
+
+ }
+ __finally
+ {
+ m_csCreateDialog.Unlock();
+ }
+
+ DownloadHelper dh;
+
+ dh.setJavaVM(jvm);
+ dh.setURL(urlChars);
+ dh.setFile(fileChars);
+ dh.setNameText((char*) nameChars);
+ dh.setShowProgressDialog(showProgress);
+ dh.setDownloadDialog(&dlg);
+
+ if (dh.doDownload() != S_OK) {
+ // remove incomplete file
+ int ret = DeleteFile(fileChars);
+ }
+
+ free(urlChars);
+ free(fileChars);
+ free(nameChars);
+}
+
+
+void error(char* msg) {
+ MessageBox(NULL, msg, "Java Error", MB_OK);
+}
+
+
+// Replace the dest file with the src file. Returns zero on success, Windows
+// error code otherwise.
+int replace(TCHAR* fullDest, TCHAR* fullSrc) {
+ struct _stat stat;
+ int result = _stat(fullSrc, &stat);
+ if (result == 0) {
+ DeleteFile(fullDest);
+ if (MoveFile(fullSrc, fullDest))
+ return 0;
+ else
+ return GetLastError();
+ }
+ else
+ return ENOENT; // src file not found
+}
+
+
+// Replace the dest file with the src file, where both paths are relative to
+// the specified root. Returns zero on success, Windows error code otherwise.
+int replaceRelative(TCHAR* root, TCHAR* dest, TCHAR* src) {
+ TCHAR fullDest[MAX_PATH];
+ TCHAR fullSrc[MAX_PATH];
+ strcpy(fullDest, root);
+ strcat(fullDest, dest);
+ strcpy(fullSrc, root);
+ strcat(fullSrc, src);
+ return replace(fullDest, fullSrc);
+}
+
+
+// Atomically deletes a file tree. Returns zero on success, Windows
+// error code otherwise.
+int deleteAll(TCHAR* root) {
+ TCHAR tmp[MAX_PATH];
+ if (strlen(root) + 5 > MAX_PATH)
+ return ERROR_BUFFER_OVERFLOW;
+ strcpy(tmp, root);
+ strcat(tmp, ".tmp");
+ struct _stat stat;
+ int result = _stat(tmp, &stat);
+ if (result == 0) {
+ result = !deleteAll(tmp);
+ if (result)
+ return result;
+ }
+ if (!MoveFile(root, tmp))
+ return GetLastError();
+ struct _SHFILEOPSTRUCTA fileOp;
+ memset(&fileOp, NULL, sizeof(fileOp));
+ fileOp.wFunc = FO_DELETE;
+ TCHAR pFrom[MAX_PATH + 1];
+ strcpy(pFrom, tmp);
+ pFrom[strlen(pFrom) + 1] = NULL; // extra null to signify that there is only one file in the list
+ fileOp.pFrom = pFrom;
+ fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
+ return SHFileOperation(&fileOp);
+}
+
+
+// moves all file with "wait='true'" specified in bundles.xml into their final
+// locations. These files are stored under lib/bundles/tmp, e.g. lib/meta-index
+// is stored at lib/bundles/tmp/lib/meta-index.
+// relativePath is the current relative path we are searching (e.g. "lib" for the
+// example above), which begins as the empty string.
+int moveDelayedFiles(TCHAR* javaHome, TCHAR* relativePath) {
+ TCHAR src[MAX_PATH];
+ TCHAR* tmp = "lib\\bundles\\tmp";
+ if (strlen(javaHome) + strlen(relativePath) + strlen(tmp) > MAX_PATH) {
+ error("Path too long.");
+ return ERROR_BUFFER_OVERFLOW;
+ }
+ strcpy(src, javaHome);
+ strcat(src, tmp);
+ if (relativePath[0] != NULL) {
+ strcat(src, "\\");
+ strcat(src, relativePath);
+ }
+
+ struct _stat stat;
+ int result = _stat(src, &stat);
+ if (result == 0) {
+ if (stat.st_mode & _S_IFDIR) { // is a directory, loop through contents
+ strcat(src, "\\*");
+ struct _WIN32_FIND_DATAA file;
+ HANDLE findHandle = FindFirstFile(src, &file);
+ if (findHandle != INVALID_HANDLE_VALUE) {
+ do {
+ if (file.cFileName[0] != '.') {
+ char child[MAX_PATH];
+ strcpy(child, relativePath);
+ strcat(child, "\\");
+ strcat(child, file.cFileName);
+ moveDelayedFiles(javaHome, child);
+ }
+ }
+ while (FindNextFile(findHandle, &file) != 0);
+ FindClose(findHandle);
+ }
+ }
+ else { // normal file, move into place
+ if (strcmp(relativePath, "\\finished")) {
+ TCHAR dest[MAX_PATH];
+ strcpy(dest, javaHome);
+ strcat(dest, relativePath);
+
+ DeleteFile(dest); // just in case; ignore failures
+ if (MoveFile(src, dest))
+ return 0;
+ else
+ return GetLastError();
+ }
+ }
+ }
+ return result;
+}
+
+
+// activates Class Data Sharing
+void activateCDS(const char *javaHome) {
+ char java[MAX_PATH];
+ strcpy(java, javaHome);
+ strcat(java, "bin\\javaw.exe");
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
+ const char *args = " -Xshare:dump";
+ const int argLength = 13;
+ char commandLine[MAX_PATH + argLength + 2];
+ strcpy(commandLine, "\"");
+ strcat(commandLine, java);
+ strcat(commandLine, "\"");
+ strcat(commandLine, args);
+ if (KERNEL_DEBUG)
+ printf("Exec: %s\n", commandLine);
+ if (CreateProcess(java, commandLine, NULL, NULL, FALSE, 0,
+ NULL, NULL, &si, &pi)) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ else
+ printf("Error initializing Class Data Sharing: %d", GetLastError());
+}
+
+typedef BOOL (*LPFNInstallJQS)();
+
+// activates the Java Quickstart Service
+void activateJQS(HMODULE hModule) {
+ LPFNInstallJQS lpfnInstallJQS;
+
+ if (hModule != NULL) {
+ lpfnInstallJQS = (LPFNInstallJQS)GetProcAddress(hModule, "InstallJQS");
+ if (lpfnInstallJQS != NULL) {
+ if ((lpfnInstallJQS)() == false && KERNEL_DEBUG) {
+ printf("InstallJQS returned FALSE\n");
+ }
+ }
+ }
+}
+
+// determines JAVA_HOME and stores it in the specified buffer. Returns true on success.
+BOOL getJavaHome(char* buffer, int bufferSize) {
+ HMODULE kernel = GetModuleHandle("jkernel");
+ if (kernel != NULL) {
+ DWORD result = GetModuleFileName(kernel, buffer, bufferSize);
+ if (result > 0) {
+ getParent(buffer, buffer); // remove "jkernel.dll"
+ if (buffer[0] != NULL)
+ getParent(buffer, buffer); // remove "bin"
+ if (buffer[0] != NULL) {
+ strcat(buffer, "\\");
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+typedef unsigned int (WINAPI *LPFNPostPing)(LPVOID err);
+HANDLE PostPing(HMODULE hModule, char* fname, DWORD err)
+{
+ LPFNPostPing lpfnPostPing;
+ HANDLE hThread = NULL;
+ lpfnPostPing = (LPFNPostPing)GetProcAddress(hModule, fname);
+ if (lpfnPostPing != NULL) {
+ printf("############# ERROR CODE: %d\n", err);
+ hThread = (HANDLE)_beginthreadex(NULL, 0, lpfnPostPing,
+ (LPVOID)err, 0, NULL);
+ if (hThread == NULL)
+ lpfnPostPing((LPVOID)err);
+ }
+ return hThread;
+}
+
+void postPingAndWait(char* fname, DWORD err) {
+ TCHAR path[MAX_PATH];
+ if (getJavaHome(path, MAX_PATH)) {
+ strcat(path, "bin\\regutils.dll");
+ HANDLE hThread = NULL;
+ HMODULE hModule = LoadLibrary(path);
+ if (hModule != NULL) {
+ hThread = PostPing(hModule, fname, err);
+ if (hThread != NULL) {
+ DWORD dwRet = 0;
+ WaitForSingleObject(hThread, 60*1000);
+ GetExitCodeThread(hThread, &dwRet);
+ CloseHandle(hThread);
+ }
+ }
+ }
+ else
+ printf("error determining JAVA_HOME for ping\n");
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_postDownloadError
+ (JNIEnv *env, jclass dm, jint error) {
+ postPingAndWait("PostKernelDLComp", error);
+}
+
+JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_postDownloadComplete
+ (JNIEnv *env, jclass dm) {
+ Java_sun_jkernel_DownloadManager_postDownloadError(env, dm, ERROR_SUCCESS);
+}
+
+bool spawnedFromJBroker() {
+ return strstr(GetCommandLine(), JBROKER_KEY) != NULL;
+}
+
+
+// Determines if we have sufficient access to go ahead and perform completion.
+// This is true either if we are not on Vista (in which case we can't elevate
+// privileges anyway and have to hope for the best) or if we are on Vista and
+// running at High integrity level.
+bool highIntegrity() {
+ if (!IsPlatformWindowsVista())
+ return TRUE;
+ else {
+ // directly determining this would require access to Vista-specific
+ // APIs, which aren't supported by our current build configurations.
+ // Instead we look for the presence of a flag on the command line to
+ // indicate that we were launched by the jbroker process. This is
+ // actually safer, as it prevents us from re-launching another JRE in
+ // the event that we somehow didn't end up with high integrity.
+ return spawnedFromJBroker();
+ }
+}
+
+JNIEXPORT jint JNICALL Java_sun_jkernel_DownloadManager_getCurrentProcessId
+ (JNIEnv *env, jclass dm) {
+ return (jint) GetCurrentProcessId();
+}
+
+JNIEXPORT jstring JNICALL Java_sun_jkernel_DownloadManager_getVisitorId0
+ (JNIEnv *env, jclass dm) {
+ CRegKey swKey, jsKey, juKey, pKey;
+ if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ if (juKey.Open(jsKey, "Java Update", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ if (pKey.Open(juKey, "Policy", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ DWORD dwCount = BUFSIZE;
+ char* keyValue = new char[BUFSIZE];
+ if (pKey.QueryValue(keyValue, "VisitorId", &dwCount) != ERROR_SUCCESS){
+ return NULL;
+ }
+ jstring visitorId = env->NewStringUTF(keyValue);
+
+ return visitorId;
+}
+
+
+JNIEXPORT jstring JNICALL Java_sun_jkernel_DownloadManager_getUrlFromRegistry
+ (JNIEnv *env, jclass dm) {
+
+ CRegKey swKey, jsKey;
+ if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ DWORD dwCount = BUFSIZE;
+ char * keyValue = new char[BUFSIZE];
+ if (jsKey.QueryValue(keyValue, "KernelDownloadUrl", &dwCount) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ jstring downloadKeyValue = env->NewStringUTF(keyValue);
+
+ return downloadKeyValue;
+}
+
+
+
+jboolean getBooleanRegistryKey(char *name, jboolean defaultValue) {
+ // Check DWORD registry key
+ // HKEY_LOCAL_MACHINE/Software/JavaSoft/<name>
+
+ CRegKey swKey, jsKey;
+ if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){
+ return NULL;
+ }
+
+ DWORD dwValue = 0;
+ if (jsKey.QueryValue(dwValue, name) != ERROR_SUCCESS){
+
+ // Key does not exist, will return default value
+ return defaultValue;
+ }
+
+ return dwValue != 0;
+}
+
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_BackgroundDownloader_getBackgroundDownloadKey
+ (JNIEnv *env, jclass dm) {
+ return getBooleanRegistryKey("KernelBackgroundDownload", TRUE);
+}
+
+
+JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_getDebugKey
+ (JNIEnv *env, jclass dm) {
+ return getBooleanRegistryKey("KernelDebug", FALSE);
+}
+
+
+// Called by the launcher before the JVM starts. If all kernel bundles have been
+// downloaded, this function performs various post-download cleanups such as
+// moving the merged rt.jar into place. At the end of cleanup, the JRE should
+// be indistinguishable from the non-kernel JRE.
+void preJVMStart() {
+ char rawMsg[BUFFER_SIZE];
+ char msg[BUFFER_SIZE];
+ HMODULE kernel = GetModuleHandle("jkernel");
+ if (kernel != NULL) {
+ TCHAR javaHome[MAX_PATH];
+ DWORD result = GetModuleFileName(kernel, javaHome, MAX_PATH);
+ if (result > 0) {
+ getParent(javaHome, javaHome); // remove "jkernel.dll"
+ if (javaHome[0] != NULL)
+ getParent(javaHome, javaHome); // remove "bin"
+ if (javaHome[0] != NULL) {
+ // should now be pointing to correct java.home
+ strcat(javaHome, "\\");
+ bool jbroker = spawnedFromJBroker();
+ HANDLE file;
+ TCHAR rt[MAX_PATH];
+ strcpy(rt, javaHome);
+ strcat(rt, "lib\\rt.jar");
+ HANDLE startMutex = CreateMutex(NULL, FALSE, "jvmStart");
+ if (!jbroker) { // else mutex is already held by the pre-jbroker JVM
+ if (KERNEL_DEBUG)
+ printf("Locking startMutex\n");
+ WaitForSingleObject(startMutex, INFINITE);
+ if (KERNEL_DEBUG)
+ printf("Locked startMutex\n");
+ // open rt.jar for reading. This prevents other JREs from being
+ // able to acquire a write lock on rt.jar, which is used as a test
+ // to ensure that no other JREs are running.
+ // The failure to close the file handle is intentional -- if we
+ // close it, there will be a brief window between the close and
+ // when the JRE reopens it during which another jre could get
+ // a write lock on it, hosing us.
+ file = CreateFile(rt, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
+ if (file == INVALID_HANDLE_VALUE) {
+ ReleaseAndClose(startMutex);
+ return;
+ }
+ if (KERNEL_DEBUG)
+ printf("Opened rt.jar for reading\n");
+ }
+ TCHAR finished[MAX_PATH];
+ TCHAR* finishedPath = "lib\\bundles\\tmp\\finished";
+ if (strlen(javaHome) + strlen(finishedPath) < MAX_PATH) {
+ strcpy(finished, javaHome);
+ strcat(finished, finishedPath);
+ struct _stat finishedStat;
+ result = _stat(finished, &finishedStat);
+ if (result == 0) { // JRE has been fully downloaded but not yet cleaned up
+ if (KERNEL_DEBUG)
+ printf("Beginning completion.\n");
+ if (!jbroker)
+ CloseHandle(file);
+ if (highIntegrity()) {
+ // attempt to open rt.jar for exclusive write access -- if this succeeds,
+ // we know no other JREs are running
+ file = CreateFile(rt, GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
+ if (file == INVALID_HANDLE_VALUE) {
+ // must be another JRE running...
+ ReleaseAndClose(startMutex);
+ return;
+ }
+ if (KERNEL_DEBUG)
+ printf("Opened rt.jar for writing.\n");
+ CloseHandle(file);
+ if (KERNEL_DEBUG)
+ printf("Closed rt.jar.\n");
+ int result = replaceRelative(javaHome, "lib\\rt.jar",
+ "lib\\bundles\\tmp\\merged-rt.jar");
+ if (result != 0 && result != ENOENT) {
+ ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, rawMsg, BUFFER_SIZE);
+ wsprintf(msg, rawMsg, javaHome, "lib\\rt.jar");
+ error(msg);
+ ReleaseAndClose(startMutex);
+ return;
+ }
+ result = replaceRelative(javaHome, "lib\\resources.jar",
+ "lib\\bundles\\tmp\\merged-resources.jar");
+ if (result != 0 && result != ENOENT) {
+ ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, rawMsg, BUFFER_SIZE);
+ wsprintf(msg, rawMsg, javaHome, "lib\\resources.jar");
+ error(msg);
+ ReleaseAndClose(startMutex);
+ return;
+ }
+
+ TCHAR bundles[MAX_PATH];
+ strcpy(bundles, javaHome);
+ strcat(bundles, "lib\\bundles");
+ if (moveDelayedFiles(javaHome, "")) {
+ ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, msg, BUFFER_SIZE);
+ error(msg);
+ ReleaseAndClose(startMutex);
+ return;
+ }
+
+ TCHAR kernel[MAX_PATH];
+ strcpy(kernel, javaHome);
+ strcat(kernel, "bin\\kernel");
+ result = deleteAll(kernel);
+ if (result != 0 && result != ENOENT) {
+ ::LoadString(_Module.GetModuleInstance(), IDS_FILE_DELETE_ERROR, rawMsg, BUFFER_SIZE);
+ wsprintf(msg, rawMsg, kernel);
+ error(msg);
+ ReleaseAndClose(startMutex);
+ return;
+ }
+
+ if (deleteAll(bundles)) {
+ // fail silently, CR #6643218
+ printf("deleteAll failed!\n");
+ ReleaseAndClose(startMutex);
+ return;
+ }
+
+ TCHAR kernelMap[MAX_PATH];
+ strcpy(kernelMap, javaHome);
+ strcat(kernelMap, "lib\\kernel.map");
+ result = deleteAll(kernelMap);
+ if (result != 0 && result != ENOENT) {
+ ::LoadString(_Module.GetModuleInstance(), IDS_FILE_DELETE_ERROR, rawMsg, BUFFER_SIZE);
+ wsprintf(msg, rawMsg, kernelMap);
+ error(msg);
+ ReleaseAndClose(startMutex);
+ return;
+ }
+
+ strcpy(rt, javaHome);
+ strcat(rt, "bin\\regutils.dll");
+ HANDLE hThread = NULL;
+ HMODULE hModule = LoadLibrary(rt);
+ if (hModule != NULL)
+ hThread = PostPing(hModule, "PostKernelComp", ERROR_SUCCESS);
+ if (KERNEL_DEBUG)
+ printf("Activating JQS.\n");
+ activateJQS(hModule);
+
+ if (KERNEL_DEBUG)
+ printf("Activating CDS.\n");
+ activateCDS(javaHome);
+
+ if (hThread != NULL) {
+ DWORD dwRet = 0;
+ WaitForSingleObject(hThread, 60*1000);
+ GetExitCodeThread(hThread, &dwRet);
+ CloseHandle(hThread);
+ }
+ if (hModule != NULL)
+ FreeLibrary(hModule);
+ } else {
+ bool jbroker = isJBrokerRunning();
+ if (!jbroker) {
+ // remove trailing slash
+ javaHome[strlen(javaHome) - 1] = 0;
+ jbroker = launchJBroker(javaHome);
+ if (!jbroker) {
+ ::LoadString(_Module.GetModuleInstance(),
+ IDS_JBROKER_ERROR,
+ msg,
+ BUFFER_SIZE);
+ error(msg);
+ }
+ }
+ if (jbroker)
+ sendPerformCompletionMessageToBroker(javaHome);
+ }
+ }
+ }
+ if (KERNEL_DEBUG)
+ printf("Releasing startMutex.\n");
+ ReleaseAndClose(startMutex);
+ } else {
+ ::LoadString(_Module.GetModuleInstance(), IDS_JAVA_HOME_ERROR, msg, BUFFER_SIZE);
+ error(msg);
+ }
+ } else {
+ ::LoadString(_Module.GetModuleInstance(), IDS_KERNEL_HOME_ERROR, msg, BUFFER_SIZE);
+ error(msg);
+ }
+ } else {
+ ::LoadString(_Module.GetModuleInstance(), IDS_KERNEL_HOME_ERROR, msg, BUFFER_SIZE);
+ error(msg);
+ }
+}
diff --git a/src/windows/native/sun/jkernel/kernel.def b/src/windows/native/sun/jkernel/kernel.def
new file mode 100644
index 000000000..1e05fd0fd
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel.def
@@ -0,0 +1,28 @@
+;
+; 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.
+;
+
+LIBRARY jkernel
+EXPORTS
+ preJVMStart @1
diff --git a/src/windows/native/sun/jkernel/kernel.h b/src/windows/native/sun/jkernel/kernel.h
new file mode 100644
index 000000000..f48ca5a23
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+void preJVMStart();
diff --git a/src/windows/native/sun/jkernel/kernel.rc b/src/windows/native/sun/jkernel/kernel.rc
new file mode 100644
index 000000000..c84853a53
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel.rc
@@ -0,0 +1,198 @@
+/*
+ * 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 "version.rc"
+
+#include "resource.h"
+#define APSTUDIO_READONLY_SYMBOLS
+#include "afxres.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+IDI_JAVA ICON DISCARDABLE "graphics\\java-icon.ico"
+IDI_MASTHEAD BITMAP DISCARDABLE "graphics\\masthead.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+// Include foreign resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+#include "kernel_ja.rc"
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Chinese (P.R.C.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+#pragma code_page(936)
+#endif //_WIN32
+#include "kernel_zh.rc"
+#endif // Chinese (P.R.C.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Korean resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR)
+#ifdef _WIN32
+LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
+#pragma code_page(949)
+#endif //_WIN32
+#include "kernel_ko.rc"
+#endif // Korean resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Chinese (Taiwan) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHT)
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
+#pragma code_page(950)
+#endif //_WIN32
+#include "kernel_zh_TW.rc"
+#endif // Chinese (Taiwan) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_de.rc"
+#endif // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Spanish (Castilian) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESP)
+#ifdef _WIN32
+LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_es.rc"
+#endif // Spanish (Castilian) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_fr.rc"
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Italian (Italy) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
+#ifdef _WIN32
+LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_it.rc"
+#endif // Italian (Italy) resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Swedish resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
+#ifdef _WIN32
+LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_sv.rc"
+#endif // Swedish resources
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+#include "kernel_en.rc"
+#endif // English resources
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/src/windows/native/sun/jkernel/kernel_de.rc b/src/windows/native/sun/jkernel/kernel_de.rc
new file mode 100644
index 000000000..9daf4452b
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_de.rc
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Zustzliche Komponenten erforderlich"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 4, 220, 30
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Abbrechen", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "Wenn Sie die Installation zustzlicher Komponenten, die fr die Anwendung erforderlich sind, abbrechen, wird die Anwendung mglicherweise geschlossen.\n\nMchten Sie die Installation zustzlicher Komponenten wirklich abbrechen?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Abbrechen - Zustzliche Komponenten"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Verbindungszeitberschreitung"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Internetverbindung kann nicht hergestellt werden"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Serverfehler (Fehler %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "Der Dienst nicht verfgbar (Fehler %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "Zugriff verweigert oder verboten (Fehler %s)"
+ IDS_HTTP_STATUS_OTHER "Bei der Anfrage ist ein Fehler aufgetreten. Mchten Sie die Anfrage wiederholen?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "Whrend der Server auf die Anforderung wartete, kam es zu einer Zeitberschreitung."
+ IDS_HTTP_STATUS_FORBIDDEN "Der Server hat die Anforderung verstanden, verweigert jedoch deren Ausfhrung."
+ IDS_HTTP_STATUS_SERVER_ERROR "Der Server stie auf eine unerwartete Bedingung, die das Ausfhren der Anforderung verhinderte."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "Der Dienst ist vorbergehend berlastet."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "Server beschftigt. Erneuter Versuch in %ld Sekunden ..."
+
+ IDS_ERROR_CAPTION "Fehler - Java Kernel"
+ IDS_HOURSMINUTESECOND "Verbleibende Zeit (geschtzt): %d Stunden, %d Minuten und %.0f Sekunden"
+ IDS_HOURMINUTESECOND "Verbleibende Zeit (geschtzt): %d Stunde, %d Minuten und %.0f Sekunden"
+ IDS_MINUTESECOND "Verbleibende Zeit (geschtzt): %d Minuten %.0f Sekunden"
+ IDS_SECOND "Verbleibende Zeit (geschtzt): %.0f Sekunden"
+ IDS_DISK_FULL_ERROR_CAPTION "Festplatte voll"
+ IDS_DISK_FULL_ERROR "Java Kernel konnte erforderliche Komponenten nicht herunterladen, da der Datentrger voll ist. Noch einmal versuchen?"
+ IDS_DISK_WRITE_ERROR_CAPTION "Fehler beim Schreiben auf Datentrger"
+ IDS_DISK_WRITE_ERROR "Java Kernel hat beim Schreiben uf den Datentrger einen Fehler verursacht Noch einmal versuchen?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java Kernel kann aufgrund der aktuellen Internetverbindungseinstellungen Ihres Systems nicht fortfahren. berprfen Sie in der Windows-Systemsteuerung unter 'Internetoptionen -> Verbindungen' die Einstellungen und Proxy-Angaben."
+
+ IDS_DOWNLOAD_RETRY "Downloadfehler"
+ IDS_DOWNLOAD_RETRY_TEXT "Beim Herunterladen einiger bentigter Komponenten ist ein Fehler aufgetreten. Mchten Sie noch einmal versuchen, diese Komponenten herunterzuladen?"
+
+ IDS_DOWNLOAD "Zustzliche Komponenten werden installiert."
+ IDS_DOWNLOAD_UNPACKING "Entpacken des Pakets"
+ IDS_DOWNLOAD_TEXT "Die Java-Anwendung wird starten, sobald zustzliche Komponenten heruntergeladen und installiert sind."
+
+ IDS_FILE_UPDATE_ERROR "Beim Aktualisieren von %s%s ist ein Fehler aufgetreten."
+ IDS_FILE_DELETE_ERROR "Beim Entfernen von %s ist ein Fehler aufgetreten."
+ IDS_JAVA_HOME_ERROR "Java-Verzeichnis kann nicht ermittelt werden."
+ IDS_KERNEL_HOME_ERROR "Pfad der jkernel.dll kann nicht ermittelt werden."
+ IDS_JBROKER_ERROR "jbroker.exe kann nicht gestartet werden."
+ IDS_FATAL_ERROR "Java konnte einige erforderliche Komponenten nicht herunterladen. Das Programm wird geschlossen."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java konnte keine Verbindung zum Downloadserver herstellen. Das Programm wird geschlossen."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Bei der Verbindung mit dem Downloadserver ist ein Fehler aufgetreten. Das Programm wird geschlossen."
+ IDS_ERROR_MALFORMED_URL "Java konnte von URL '%s' keinen Dowload ausfhren. Das Programm wird geschlossen."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_en.rc b/src/windows/native/sun/jkernel/kernel_en.rc
new file mode 100644
index 000000000..b1d15984a
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_en.rc
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Additional Components Needed"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Cancel", 2, 285, 100, 46, 14
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "Canceling the installation of additional components which the application needs may cause the application to exit.\n\nAre you sure you want to cancel the installation of additional components?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Cancel - Additional Components"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Connection Timed Out"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Unable to connect to the Internet"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Server error (Error %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "Service Unavailable (Error %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "Access Denied or Forbidden (Error %s)"
+ IDS_HTTP_STATUS_OTHER "An error has occured during this request. Do you want to try the request again?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "The server used to download the requested components is not responding and the connection has timed out. Do you want to try to connect again?"
+ IDS_HTTP_STATUS_FORBIDDEN "You do not have permission to access the server to download the components requested by the application. Retry your access to the server?"
+ IDS_HTTP_STATUS_SERVER_ERROR "An error occured on the server and it could not complete the request. Do you want to try the request again?"
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "The requested service is temporarily unavailable. Do you want to try the request again?"
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "Server is currently busy, retry in %ld seconds ..."
+
+ IDS_ERROR_CAPTION "Java Installer"
+ IDS_HOURSMINUTESECOND "Estimated time remaining: %d hours %d minutes %.0f seconds"
+ IDS_HOURMINUTESECOND "Estimated time remaining: %d hour %d minutes %.0f seconds"
+ IDS_MINUTESECOND "Estimated time remaining: %d minutes %.0f seconds"
+ IDS_SECOND "Estimated time remaining: %.0f seconds"
+ IDS_DISK_FULL_ERROR_CAPTION "Disk Full %s"
+ IDS_DISK_FULL_ERROR "There is not enough space on the disk to download the requested components. Clear space on the disk and then Retry."
+ IDS_DISK_WRITE_ERROR_CAPTION "Can't write to the disk %s"
+ IDS_DISK_WRITE_ERROR "An error occurred during writing to the disk. Please check that the disk is not write protected."
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java cannot connect to the Internet. Please check that the Internet Connection settings are correct (these can be found in the Windows Control Panel under Internet Options > Connection) and that your firewall allows java.exe to access the Internet."
+
+ IDS_DOWNLOAD_RETRY "Download error"
+ IDS_DOWNLOAD_RETRY_TEXT "An error occurred during the download of some requested components. Do you want to try the download of these components again?"
+
+ IDS_DOWNLOAD "Installing Additional Components"
+ IDS_DOWNLOAD_UNPACKING "Unpacking bundle"
+ IDS_DOWNLOAD_TEXT "The Java application will start when additional components that it requires are downloaded and installed."
+
+ IDS_FILE_UPDATE_ERROR "An error occurred while updating %s%s."
+ IDS_FILE_DELETE_ERROR "An error occurred while removing %s."
+ IDS_JAVA_HOME_ERROR "Unable to determine Java home directory."
+ IDS_KERNEL_HOME_ERROR "Unable to determine path to jkernel.dll."
+ IDS_JBROKER_ERROR "Unable to launch jbroker.exe."
+ IDS_FATAL_ERROR "Java was unable to download required components. The program will now exit."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java was unable to communicate with the download server. The program will now exit."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java encountered an error communicating with the download server. The program will now exit."
+ IDS_ERROR_MALFORMED_URL "Java was unable to download from the URL '%s'. The program will now exit."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_es.rc b/src/windows/native/sun/jkernel/kernel_es.rc
new file mode 100644
index 000000000..119a35e7f
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_es.rc
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Componentes adicionales necesarios"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 8, 225, 20
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Cancelar", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "Cancelar la instalacin de los componentes adicionales que necesita la aplicacin puede hacer que se cierre la aplicacin.\n\nSeguro que desea cancelar la instalacin de componentes adicionales?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Cancelar - Componentes adicionales"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Se ha agotado el tiempo de espera de la conexin"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "No es posible conectarse a Internet"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Ha habido un error en el servidor (error %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "El servicio no est disponible (error %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "El acceso se ha denegado o est prohibido (error %s)"
+ IDS_HTTP_STATUS_OTHER "Ha habido un error en el transcurso de esta solicitud. Desea ejecutar de nuevo la solicitud?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "El servidor ha agotado el tiempo de espera de la solicitud."
+ IDS_HTTP_STATUS_FORBIDDEN "El servidor ha podido interpretar la solicitud, pero la rechaza."
+ IDS_HTTP_STATUS_SERVER_ERROR "El servidor ha encontrado una condicin inesperada que le ha impedido satisfacer la solicitud."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "El servicio est temporalmente sobrecargado."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "El servidor est ocupado en este momento, se volver a intentar la conexin en %ld segundos..."
+
+ IDS_ERROR_CAPTION "Error - Java Kernel"
+ IDS_HOURSMINUTESECOND "Tiempo restante estimado: %d horas %d minutos %.0f segundos"
+ IDS_HOURMINUTESECOND "Tiempo restante estimado: %d hora %d minutos %.0f segundos"
+ IDS_MINUTESECOND "Tiempo restante estimado: %d minutos %.0f segundos"
+ IDS_SECOND "Tiempo restante estimado: %.0f segundos"
+ IDS_DISK_FULL_ERROR_CAPTION "Disco lleno"
+ IDS_DISK_FULL_ERROR "Java Kernel no puede descargar los componentes necesarios porque el disco est lleno. Desea volver a intentarlo?"
+ IDS_DISK_WRITE_ERROR_CAPTION "Error de escritura en disco"
+ IDS_DISK_WRITE_ERROR "Se ha producido un error cuando Java Kernel intentaba escribir en el disco. Desea volver a intentarlo?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java Kernel no puede continuar con la configuracin actual de conexin a Internet del sistema. En el Panel de control de Windows, compruebe Opciones de Internet -> Conexiones para verificar que la informacin de la configuracin y de proxy sea la correcta."
+
+ IDS_DOWNLOAD_RETRY "Error de descarga"
+ IDS_DOWNLOAD_RETRY_TEXT "Se ha producido un error durante la descarga de algunos componentes solicitados. Quiere volver a intentar descargar estos componentes?"
+
+ IDS_DOWNLOAD "Instalacin de componentes adicionales"
+ IDS_DOWNLOAD_UNPACKING "Desempaquetando paquete"
+ IDS_DOWNLOAD_TEXT "La aplicacin Java se iniciar cuando los componentes adicionales necesarios se hayan descargado e instalado."
+
+ IDS_FILE_UPDATE_ERROR "Se ha producido un error al actualizar %s%s."
+ IDS_FILE_DELETE_ERROR "Se ha producido un error al eliminar %s."
+ IDS_JAVA_HOME_ERROR "Imposible determinar el directorio de inicio Java."
+ IDS_KERNEL_HOME_ERROR "Imposible determinar la ruta a jkernel.dll."
+ IDS_JBROKER_ERROR "Imposible iniciar jbroker.exe."
+ IDS_FATAL_ERROR "Java no ha podido descargar los componentes necesarios. El programa se cerrar."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java no ha podido comunicarse con el servidor de descarga. El programa se cerrar."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Se ha producido un error en la comunicacin entre Java y el servidor de descarga. El programa se cerrar."
+ IDS_ERROR_MALFORMED_URL "Java no ha podido realizar la descarga desde el URL '%s'. El programa se cerrar."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_fr.rc b/src/windows/native/sun/jkernel/kernel_fr.rc
new file mode 100644
index 000000000..0ea343479
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_fr.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Composants supplmentaires requis"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 4, 220, 30
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Annuler", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "L'annulation de l'installation de composants supplmentaires ncessaires l'application risque d'entraner la fermeture de celle-ci.\n\nVoulez-vous vraiment annuler l'installation des composants supplmentaires ?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Annuler : composants supplmentaires"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Dlai de connexion dpass"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Connexion Internet impossible"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Erreur de serveur (erreur %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "Service non disponible (erreur %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "Accs refus ou interdit (erreur %s)"
+ IDS_HTTP_STATUS_OTHER "Une erreur s'est produite lors de cette demande. Voulez-vous effectuer nouveau la demande ?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "Temporisation du serveur lors de l'attente de la requte."
+ IDS_HTTP_STATUS_FORBIDDEN "Le serveur a compris la requte mais refuse de la satisfaire."
+ IDS_HTTP_STATUS_SERVER_ERROR "Le serveur a rencontr une condition inattendue l'empchant de satisfaire la requte."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "Le service est temporairement surcharg."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "Le serveur est occup ; veuillez ressayer dans %ld secondes..."
+
+ IDS_ERROR_CAPTION "Erreur - Java Kernel"
+ IDS_HOURSMINUTESECOND "Temps restant prvu : %d heures %d minutes %.0f secondes"
+ IDS_HOURMINUTESECOND "Temps restant prvu : %d heure %d minutes %.0f secondes"
+ IDS_MINUTESECOND "Temps restant prvu : %d minutes %.0f secondes"
+ IDS_SECOND "Temps restant prvu : %.0f secondes"
+ IDS_DISK_FULL_ERROR_CAPTION "Disque satur"
+ IDS_DISK_FULL_ERROR "En raison de la saturation du disque, Java Kernel n'a pas t en mesure de tlcharger les composants requis. Voulez-vous ressayer ?"
+ IDS_DISK_WRITE_ERROR_CAPTION "Erreur d'criture sur le disque"
+ IDS_DISK_WRITE_ERROR "Java Kernel a rencontr une erreur lors de l'criture sur le disque. Voulez-vous ressayer ?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java Kernel ne peut pas s'excuter avec les paramtres de connexion Internet actuels de votre systme. Dans le Panneau de configuration de Windows, cliquez sur Options Internet -> Connexions pour vrifier les paramtres et informations de proxy."
+
+ IDS_DOWNLOAD_RETRY "Erreur de tlchargement"
+ IDS_DOWNLOAD_RETRY_TEXT "Une erreur s'est produite lors du tlchargement de certains composants requis. Souhaitez-vous ressayer de tlcharger ces composants ?"
+
+ IDS_DOWNLOAD "Installation de composants supplmentaires"
+ IDS_DOWNLOAD_UNPACKING "Dcompression du bundle"
+ IDS_DOWNLOAD_TEXT "L'application Java dmarre lorsque des composants supplmentaires requis sont tlchargs et installs."
+
+ IDS_FILE_UPDATE_ERROR "Une erreur s'est produite lors de la mise jour de %s%s."
+ IDS_FILE_DELETE_ERROR "Une erreur s'est produite lors de la suppression de %s."
+ IDS_JAVA_HOME_ERROR "Le rpertoire d'accueil Java est introuvable."
+ IDS_KERNEL_HOME_ERROR "Le chemin de jkernel.dll est introuvable."
+ IDS_JBROKER_ERROR "Impossible de lancer jbroker.exe."
+ IDS_FATAL_ERROR "Java n'a pas t en mesure de tlcharger les composants requis. Fermeture imminente du programme."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java n'a pas t en mesure de communiquer avec le serveur de tlchargement. Fermeture imminente du programme."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java a rencontr une erreur lors de la communication avec le serveur de tlchargement. Fermeture imminente du programme."
+ IDS_ERROR_MALFORMED_URL "Java n'a pas t en mesure de raliser le tlchargement partir de l'URL '%s'. Fermeture imminente du programme."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_it.rc b/src/windows/native/sun/jkernel/kernel_it.rc
new file mode 100644
index 000000000..4c0a58ba8
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_it.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Componenti aggiuntivi richiesti"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 4, 220, 30
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Annulla", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "Se si annulla l'installazione di componenti aggiuntivi necessari per l'applicazione, quest'ultima potrebbe chiudersi.\n\nAnnullare l'installazione di componenti aggiuntivi?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Annulla - Componenti aggiuntivi"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Timeout della connessione"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Impossibile stabilire una connessione a Internet"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Errore del server (errore %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "Servizio non disponibile (errore %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "Accesso negato o vietato (errore %s)"
+ IDS_HTTP_STATUS_OTHER "Errore durante la richiesta. Provare a reinviare la richiesta?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "Tempo scaduto del server in attesa della richiesta."
+ IDS_HTTP_STATUS_FORBIDDEN "Il server ha ricevuto la richiesta ma non ne consente l'elaborazione."
+ IDS_HTTP_STATUS_SERVER_ERROR "Il server ha rilevato una condizione imprevista che ha impedito di soddisfare la richiesta."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "Il servizio temporaneamente sovraccarico."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "Server occupato, riprovare tra %ld secondi..."
+
+ IDS_ERROR_CAPTION "Errore - Java Kernel"
+ IDS_HOURSMINUTESECOND "Tempo rimanente previsto: %d ore %d minuti %.0f secondi"
+ IDS_HOURMINUTESECOND "Tempo rimanente previsto: %d ora %d minuti %.0f secondi"
+ IDS_MINUTESECOND "Tempo rimanente previsto: %d minuti %.0f secondi"
+ IDS_SECOND "Tempo rimanente previsto: %.0f secondi"
+ IDS_DISK_FULL_ERROR_CAPTION "Disco pieno"
+ IDS_DISK_FULL_ERROR "Java Kernel non ha effettuato il download dei componenti necessari perché il disco è pieno. Riprovare?"
+ IDS_DISK_WRITE_ERROR_CAPTION "Errore di scrittura sul disco"
+ IDS_DISK_WRITE_ERROR "Java Kernel ha rilevato un errore durante la scrittura sul disco. Riprovare?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Non possibile utilizzare Java Kernel con le impostazioni di connessione Internet attive nel sistema. Nel Pannello di controllo di Windows, selezionare Opzioni Internet -> Connessioni per controllare che le impostazioni e le informazioni sul proxy siano corrette."
+
+ IDS_DOWNLOAD_RETRY "Errore di download"
+ IDS_DOWNLOAD_RETRY_TEXT "Si verificato un errore durante il download di alcuni componenti richiesti. Ritentare il download di tali componenti?"
+
+ IDS_DOWNLOAD "Installazione di componenti aggiuntivi in corso"
+ IDS_DOWNLOAD_UNPACKING "Decompressione del bundle in corso"
+ IDS_DOWNLOAD_TEXT "L'applicazione Java verr avviata dopo il download e l'installazione dei componenti richiesti."
+
+ IDS_FILE_UPDATE_ERROR "Errore durante l'aggiornamento di %s%s."
+ IDS_FILE_DELETE_ERROR "Errore durante la rimozione di %s."
+ IDS_JAVA_HOME_ERROR "Impossibile determinare la directory home di Java."
+ IDS_KERNEL_HOME_ERROR "Impossibile determinare il percorso di jkernel.dll."
+ IDS_JBROKER_ERROR "Impossibile avviare jbroker.exe."
+ IDS_FATAL_ERROR "Java non in grado di scaricare i componenti necessari. Il programma verr terminato."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java non in grado di comunicare con il server di download. Il programma verr terminato."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java ha rilevato un errore durante la comunicazione con il server di download. Il programma verr terminato."
+ IDS_ERROR_MALFORMED_URL "Java non in grado di eseguire il download dall'URL '%s'. Il programma verr terminato."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_ja.rc b/src/windows/native/sun/jkernel/kernel_ja.rc
new file mode 100644
index 000000000..198cb9170
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_ja.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "ljR|[lgKv"
+EXSTYLE WS_EX_APPWINDOW
+FONT 10, "MS UI Gothic"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "AvP[VKvƂljR|[lg̃CXg[LZƁAAvP[VI”\܂B\n\nljR|[lg̃CXg[LZĂ낵łH"
+ IDS_DOWNLOAD_CANCEL_CAPTION "LZ - ljR|[lg"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "ڑ^CAEg܂"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "C^[lbgɐڑł܂"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "T[o[G[ (G[ %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "T[rXps (G[ %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "ANZXۂ܂͋֎~Ă܂ (G[ %s)"
+ IDS_HTTP_STATUS_OTHER "̗v̏ɃG[܂BvĎs܂?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "vҋ@ɃT[o[^CAEg܂B"
+ IDS_HTTP_STATUS_FORBIDDEN "T[o[́AvFĂ܂AsۂĂ܂B"
+ IDS_HTTP_STATUS_SERVER_ERROR "T[o[́Av̎sW\Ȃ󋵂ɑ܂B"
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "T[rXꎞIɃI[o[[hĂ܂B"
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "T[o[͌݃rW[łB%ld bɍĎs܂ ..."
+
+ IDS_ERROR_CAPTION "G[ - Java J[l"
+ IDS_HOURSMINUTESECOND "\zc莞: %d %d %.0f b"
+ IDS_HOURMINUTESECOND "\zc莞: %d %d %.0f b"
+ IDS_MINUTESECOND "\zc莞: %d %.0f b"
+ IDS_SECOND "\zc莞: %.0f b"
+ IDS_DISK_FULL_ERROR_CAPTION "fBXNςł"
+ IDS_DISK_FULL_ERROR "fBXNς̂߁AJava J[lKvȃR|[lg_E[hł܂łBx܂?"
+ IDS_DISK_WRITE_ERROR_CAPTION "fBXN݃G["
+ IDS_DISK_WRITE_ERROR "Java J[lfBXNւ̏ݎɃG[o܂Bx܂?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java J[ĺAg̃VXě݂̃C^[lbgڑݒł͓삵܂BWindows ̃Rg[plŁAuC^[lbgIvVv -> uڑvIāAݒ肨уvLV񂪐ƂmFĂB"
+
+ IDS_DOWNLOAD_RETRY "_E[hG["
+ IDS_DOWNLOAD_RETRY_TEXT "vꂽR|[lg̈ꕔ_E[hɃG[܂B̃R|[lg̃_E[hēx݂܂ ?"
+
+ IDS_DOWNLOAD "ljR|[lgCXg[Ă܂"
+ IDS_DOWNLOAD_UNPACKING "ohWJĂ܂"
+ IDS_DOWNLOAD_TEXT "Java AvP[V́AK{̒ljR|[lg̃_E[hуCXg[ɋN܂B"
+
+ IDS_FILE_UPDATE_ERROR "%s%s ̍XVɃG[܂B"
+ IDS_FILE_DELETE_ERROR "%s ̍폜ɃG[܂B"
+ IDS_JAVA_HOME_ERROR "Java z[fBNg𔻒ł܂B"
+ IDS_KERNEL_HOME_ERROR "jkernel.dll ̃pX𔻒ł܂B"
+ IDS_JBROKER_ERROR "jbroker.exe Nł܂B"
+ IDS_FATAL_ERROR "Java KvȃR|[lg_E[hł܂łBvO͏I܂B"
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java _E[hT[o[ƒʐMł܂łBvO͏I܂B"
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java _E[hT[o[Ƃ̒ʐMɃG[o܂BvO͏I܂B"
+ IDS_ERROR_MALFORMED_URL "Java URL '%s' _E[hł܂łBvO͏I܂B"
+END
diff --git a/src/windows/native/sun/jkernel/kernel_ko.rc b/src/windows/native/sun/jkernel/kernel_ko.rc
new file mode 100644
index 000000000..bf8495e0a
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_ko.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "߰ ʿ"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE " α׷ ʿ ߰ ġ ϸ α׷ ֽϴ.\n\n߰ ġ Ͻðڽϱ?"
+ IDS_DOWNLOAD_CANCEL_CAPTION " - ߰ "
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT " ð ʰ"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "ͳݿ ϴ."
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR " ( %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "񽺸 ( %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "׼ źεǾų ( %s)"
+ IDS_HTTP_STATUS_OTHER " û ߻߽ϴ. û ٽ õϽðڽϱ?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT " û ٸ ð ʰǾϴ."
+ IDS_HTTP_STATUS_FORBIDDEN " û ϱ⸦ źմϴ."
+ IDS_HTTP_STATUS_SERVER_ERROR " û ϴ ġ ߰ߵǾϴ."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL " Ͻ ϵǾϴ."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY " ̹Ƿ %ld Ŀ ٽ õϽʽÿ."
+
+ IDS_ERROR_CAPTION " - Java Ŀ"
+ IDS_HOURSMINUTESECOND " ð: %dð %d %.0f"
+ IDS_HOURMINUTESECOND " ð: %dð %d %.0f"
+ IDS_MINUTESECOND " ð: %d %.0f"
+ IDS_SECOND " ð: %.0f"
+ IDS_DISK_FULL_ERROR_CAPTION "ũ "
+ IDS_DISK_FULL_ERROR "ũ Java Kernel ʿ Ҹ ٿε ߽ϴ. ٽ õϽðڽϱ?"
+ IDS_DISK_WRITE_ERROR_CAPTION "ũ "
+ IDS_DISK_WRITE_ERROR "ũ Java Kernel ߻߽ϴ. ٽ õϽðڽϱ?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "ý ͳ δ Java Kernel ϴ. Windows ǿ ͳ ɼ -> Ͽ Ͻ ùٸ ȮϽʽÿ."
+
+ IDS_DOWNLOAD_RETRY "ٿε "
+ IDS_DOWNLOAD_RETRY_TEXT "û Ҹ ٿεϴ ߻߽ϴ. Ҹ ٽ ٿεϽðڽϱ?"
+
+ IDS_DOWNLOAD "߰ ġ"
+ IDS_DOWNLOAD_UNPACKING " Ǯ"
+ IDS_DOWNLOAD_TEXT "ʿ ߰ Ұ ٿεǾ ġǸ Java α׷ ۵˴ϴ."
+
+ IDS_FILE_UPDATE_ERROR "%s%s() Ʈϴ ߻߽ϴ."
+ IDS_FILE_DELETE_ERROR "%s() ϴ ߻߽ϴ."
+ IDS_JAVA_HOME_ERROR "Java Ȩ 丮 Ȯ ϴ."
+ IDS_KERNEL_HOME_ERROR "jkernel.dll θ Ȯ ϴ."
+ IDS_JBROKER_ERROR "jbroker.exe ϴ."
+ IDS_FATAL_ERROR "ʿ Ҹ ٿε ߽ϴ. α׷ ˴ϴ."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "ٿε ߽ϴ. α׷ ˴ϴ."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "ٿε ߻߽ϴ. α׷ ˴ϴ."
+ IDS_ERROR_MALFORMED_URL "URL '%s' ٿε ߽ϴ. α׷ ˴ϴ."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_sv.rc b/src/windows/native/sun/jkernel/kernel_sv.rc
new file mode 100644
index 000000000..b3df33635
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_sv.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Ytterligare komponenter behvs"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "Avbryt", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "Programmet kan avslutas om du avbryter installationen av ytterligare komponenter som r ndvndiga fr programmet.\n\nVill du avbryta installationen av ytterligare komponenter?"
+ IDS_DOWNLOAD_CANCEL_CAPTION "Avbryt - Ytterligare komponenter"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "Anslutningen avbrts p grund av timeout"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Det gr inte att ansluta till Internet."
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "Serverfel (Fel %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "Tjnsten r inte tillgnglig (Fel %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "tkomst nekad eller frbjuden (Fel %s)"
+ IDS_HTTP_STATUS_OTHER "Ett fel intrffade i samband med begran. Vill du frska skicka begran igen?"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "Ett tidsfel intrffade medan servern vntade p begran."
+ IDS_HTTP_STATUS_FORBIDDEN "Servern frstod begran men vgrar uppfylla den."
+ IDS_HTTP_STATUS_SERVER_ERROR "Ett ovntat tillstnd som innebr att begran inte kan uppfyllas ptrffades."
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "Tjnsten r tillflligt verbelastad."
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "Servern r upptagen fr nrvarande. Frsk igen om %ld sekund(er) ..."
+
+ IDS_ERROR_CAPTION "Fel - Java Kernel"
+ IDS_HOURSMINUTESECOND "terstende tid: %d timmar %d minuter %.0f sekunder"
+ IDS_HOURMINUTESECOND "terstende tid: %d timme %d minuter %.0f sekunder"
+ IDS_MINUTESECOND "terstende tid: %d minuter %.0f sekunder"
+ IDS_SECOND "terstende tid: %.0f sekunder"
+ IDS_DISK_FULL_ERROR_CAPTION "Disken r full"
+ IDS_DISK_FULL_ERROR "Java Kernel kunde inte ladda ned ndvndiga komponenter drfr att disken r full. Frska igen?"
+ IDS_DISK_WRITE_ERROR_CAPTION "Fel vid skrivning till disk"
+ IDS_DISK_WRITE_ERROR "Java Kernel sttte p ett fel vid skrivning till disken. Frska igen?"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "Java Kernel kan inte fortstta med systemets aktuella instllningar fr Internetanslutning. ppna Kontrollpanelen, Internet-alternativ > Anslutningar och kontrollera att instllningarna och proxyinformationen stmmer."
+
+ IDS_DOWNLOAD_RETRY "Nedladdningsfel"
+ IDS_DOWNLOAD_RETRY_TEXT "Ett fel uppstod under nedladdning av vissa begrda komponenter. Vill du frska ladda ned dessa komponenter igen?"
+
+ IDS_DOWNLOAD "Ytterligare komponenter installeras"
+ IDS_DOWNLOAD_UNPACKING "Uppackning av paket"
+ IDS_DOWNLOAD_TEXT "Java-applikationen startar nr ytterligare komponenter som krvs r nedladdade och installerade."
+
+ IDS_FILE_UPDATE_ERROR "Ett fel uppstod nr %s%s uppdaterades."
+ IDS_FILE_DELETE_ERROR "Ett fel uppstod nr %s skulle tas bort."
+ IDS_JAVA_HOME_ERROR "Det gr inte att avgra Javas hemkatalog"
+ IDS_KERNEL_HOME_ERROR "Det gr inte att avgra skvgen till jkernell.dll."
+ IDS_JBROKER_ERROR "Det gr inte att starta jbroker.exe."
+ IDS_FATAL_ERROR "Det gick inte att ladda ned de ndvndiga komponenterna med Java. Programmet avslutas."
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Det gick inte att upprtta ngon kommunikation mellan Java och nedladdningsservern. Programmet avslutas."
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Det uppstod ett fel i kommunikationen mellan Java och nedladdningsservern. Programmet avslutas."
+ IDS_ERROR_MALFORMED_URL "Det gick inte att ladda ned frn webbadressen '%s'. Programmet avslutas."
+END
diff --git a/src/windows/native/sun/jkernel/kernel_zh.rc b/src/windows/native/sun/jkernel/kernel_zh.rc
new file mode 100644
index 000000000..886744518
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_zh.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION ""
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "ȡ", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "ȡװӦóĶܻᵼ¸Ӧó˳\n\nǷȷҪȡװ"
+ IDS_DOWNLOAD_CANCEL_CAPTION "ȡ - "
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "ѳʱ"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "޷ӵ Internet"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "󣨴 %s"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "񲻿ã %s"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "ܾʻֹʣ %s"
+ IDS_HTTP_STATUS_OTHER "ڴڼִǷҪ"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "ȴʱʱ"
+ IDS_HTTP_STATUS_FORBIDDEN "ѽ󣬵ִܾС"
+ IDS_HTTP_STATUS_SERVER_ERROR "޷"
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "ʱء"
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "æ %ld ..."
+
+ IDS_ERROR_CAPTION " - Java Kernel"
+ IDS_HOURSMINUTESECOND "ʣʱ:%d Сʱ %d %.0f "
+ IDS_HOURMINUTESECOND "ʣʱ:%d Сʱ %d %.0f "
+ IDS_MINUTESECOND "ʣʱ:%d %.0f "
+ IDS_SECOND "ʣʱ:%.0f "
+ IDS_DISK_FULL_ERROR_CAPTION ""
+ IDS_DISK_FULL_ERROR "ڴJava Kernel ޷Ƿԣ"
+ IDS_DISK_WRITE_ERROR_CAPTION "д"
+ IDS_DISK_WRITE_ERROR "ִдʱ Java Kernel Ƿԣ"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "ʹϵͳǰ Internet õ£Java Kernel ޷ִС Windows""""У""Internet ѡ""->""""ȷúʹϢȷ"
+
+ IDS_DOWNLOAD_RETRY "ش"
+ IDS_DOWNLOAD_RETRY_TEXT "ijЩڼ䷢ǷҪһЩ"
+
+ IDS_DOWNLOAD "װ"
+ IDS_DOWNLOAD_UNPACKING "ڽѹ"
+ IDS_DOWNLOAD_TEXT "زװ Java Ӧó󣬸Ӧó"
+
+ IDS_FILE_UPDATE_ERROR " %s%s ʱ"
+ IDS_FILE_DELETE_ERROR "ɾ %s ʱ"
+ IDS_JAVA_HOME_ERROR "޷ȷ Java Ŀ¼"
+ IDS_KERNEL_HOME_ERROR "޷ȷ jkernel.dll ·"
+ IDS_JBROKER_ERROR "޷ jbroker.exe"
+ IDS_FATAL_ERROR "Java ޷ڳ˳"
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java ޷طͨšڳ˳"
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java طͨʱڳ˳"
+ IDS_ERROR_MALFORMED_URL "Java ޷ URL '%s' ִءڳ˳"
+END
diff --git a/src/windows/native/sun/jkernel/kernel_zh_TW.rc b/src/windows/native/sun/jkernel/kernel_zh_TW.rc
new file mode 100644
index 000000000..d0882b997
--- /dev/null
+++ b/src/windows/native/sun/jkernel/kernel_zh_TW.rc
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 340, 120
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "һݪL"
+EXSTYLE WS_EX_APPWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "", IDC_DOWNLOAD_MASTHEAD, 0, 0, 340, 39
+ LTEXT "", IDC_MASTHEAD_TEXT, 60, 14, 200, 12
+ CONTROL "", IDC_STATIC,"Static", SS_BLACKFRAME | SS_SUNKEN,
+ 0, 39, 340, 1
+ LTEXT "", IDC_DOWNLOAD_TEXT, 12, 60, 316, 20
+ LTEXT "", IDC_TIME_REMAINING, 12, 90, 316, 10
+ CONTROL "Progress1",1006,"msctls_progress32",PBS_SMOOTH,
+ 12, 100, 265, 14
+ PUSHBUTTON "", 2, 285, 100, 46, 14
+END
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ 105, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 63
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DOWNLOAD_CANCEL_MESSAGE "wε{һݪLAi|ɭPε{C\n\nzTwnw˨LH"
+ IDS_DOWNLOAD_CANCEL_CAPTION " - L"
+ IDS_DOWNLOAD_CANCEL_INSTRUCTION ""
+ IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT "suO"
+ IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE "Lksuܺں"
+ IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR "A~ (~ %s)"
+ IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL "LkϥΪA (~ %s)"
+ IDS_HTTP_INSTRUCTION_FORBIDDEN "ڵθTs (~ %s)"
+ IDS_HTTP_STATUS_OTHER "bШDoͿ~CO_nսШDH"
+
+// HTTP status code
+ IDS_HTTP_STATUS_REQUEST_TIMEOUT "AݽШDɥX{OɡC"
+ IDS_HTTP_STATUS_FORBIDDEN "AAѸӽШDAbڵ{C"
+ IDS_HTTP_STATUS_SERVER_ERROR "AJ{ШDwC"
+ IDS_HTTP_STATUS_SERVICE_UNAVAIL "AȼȮɶWC"
+
+
+ IDS_DOWNLOAD_STATUS_RETRY "AثeB󦣸LAAЦb %ld ᭫..."
+
+ IDS_ERROR_CAPTION "~ - Java Kernel"
+ IDS_HOURSMINUTESECOND "wѾlɶG%d p %d %.0f "
+ IDS_HOURMINUTESECOND "wѾlɶG%d p %d %.0f "
+ IDS_MINUTESECOND "wѾlɶG%d %.0f "
+ IDS_SECOND "wѾlɶG%.0f "
+ IDS_DISK_FULL_ERROR_CAPTION "ϺФw"
+ IDS_DISK_FULL_ERROR "ѩϺФwAJava Kernel LkUһݪCO_nաH"
+ IDS_DISK_WRITE_ERROR_CAPTION "ϺмgJ~"
+ IDS_DISK_WRITE_ERROR "Java Kernel bgJܺϺЮɹJ~CO_nաH"
+ IDS_HTTP_STATUS_SERVER_NOT_REACHABLE "btΥثeںsu]wUAJava Kernel Lk~Cb WindowsuxvAЮֹuںﶵv->usuvAHTw]wMNzATTC"
+
+ IDS_DOWNLOAD_RETRY "U~"
+ IDS_DOWNLOAD_RETRY_TEXT "UYǩһݤɵoͿ~CO_nդUoǤH"
+
+ IDS_DOWNLOAD "bw˨L"
+ IDS_DOWNLOAD_UNPACKING "bY"
+ IDS_DOWNLOAD_TEXT "Uæw˨LһݤAJava ε{NҰʡC"
+
+ IDS_FILE_UPDATE_ERROR "s %s%s ɵoͿ~C"
+ IDS_FILE_DELETE_ERROR " %s ɵoͿ~C"
+ IDS_JAVA_HOME_ERROR "LkTw Java DؿC"
+ IDS_KERNEL_HOME_ERROR "LkTw jkernel.dll |C"
+ IDS_JBROKER_ERROR "LkҰ jbroker.exeC"
+ IDS_FATAL_ERROR "Java LkUһݪC{NߧYC"
+ IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES "Java LkPUAiqTC{NߧYC"
+ IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES "Java bPUAiqTɹJF@ӿ~C{NߧYC"
+ IDS_ERROR_MALFORMED_URL "Java Lkq URLu%svUC{NߧYC"
+END
diff --git a/src/windows/native/sun/jkernel/resource.h b/src/windows/native/sun/jkernel/resource.h
new file mode 100644
index 000000000..424531d55
--- /dev/null
+++ b/src/windows/native/sun/jkernel/resource.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+//
+//
+
+
+// HTTP status code
+#define IDS_HTTP_STATUS_FORBIDDEN 403
+#define IDS_HTTP_STATUS_REQUEST_TIMEOUT 408
+#define IDS_HTTP_STATUS_SERVER_ERROR 500
+#define IDS_HTTP_STATUS_SERVICE_UNAVAIL 503
+
+
+
+#define IDS_HTTP_INSTRUCTION_REQUEST_TIMEOUT 2408
+#define IDS_HTTP_INSTRUCTION_SERVICE_UNAVAIL 2503
+#define IDS_HTTP_INSTRUCTION_FORBIDDEN 2403
+#define IDS_HTTP_INSTRUCTION_SERVER_NOT_REACHABLE 2035
+#define IDS_HTTP_INSTRUCTION_UNKNOWN_ERROR 2036
+#define IDS_HTTP_STATUS_OTHER 2037
+
+#define IDS_DOWNLOAD_STATUS_RETRY 3004
+
+#define IDD_DOWNLOAD_DIALOG 105
+#define IDI_JAVA 114
+#define IDI_MASTHEAD 115
+#define IDC_DOWNLOAD_PROGRESS 1006
+#define IDC_DOWNLOAD_INFO 1007
+#define IDC_DOWNLOAD_STATUS 1008
+#define IDC_DOWNLOAD_ANIMATE 1009
+#define IDS_ERROR_CAPTION 2004
+#define IDS_HOURSMINUTESECOND 2007
+#define IDS_HOURMINUTESECOND 2008
+#define IDS_MINUTESECOND 2009
+#define IDS_SECOND 2010
+#define IDS_DISK_FULL_ERROR 2023
+#define IDS_DISK_FULL_ERROR_CAPTION 2024
+#define IDS_DISK_WRITE_ERROR 2025
+#define IDS_DISK_WRITE_ERROR_CAPTION 2026
+#define IDS_HTTP_STATUS_SERVER_NOT_REACHABLE 2028
+#define IDS_FATAL_ERROR 2029
+#define IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES 2030
+#define IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES 2031
+#define IDS_ERROR_MALFORMED_URL 2032
+
+#define IDS_DOWNLOAD_CANCEL_CAPTION 2038
+#define IDS_DOWNLOAD_CANCEL_INSTRUCTION 2039
+#define IDS_DOWNLOAD_CANCEL_MESSAGE 2040
+
+// codes for download and install dialog
+#define IDC_MASTHEAD_TEXT 116
+#define IDC_DOWNLOAD_MASTHEAD 121
+#define IDC_TIME_REMAINING 122
+#define IDC_DOWNLOAD_TEXT 123
+
+// codes for download retry dialog
+#define IDS_DOWNLOAD_RETRY 130
+#define IDS_DOWNLOAD_RETRY_TEXT 131
+
+#define IDS_DOWNLOAD_UNPACKING 3900
+#define IDS_DOWNLOAD 4000
+#define IDS_DOWNLOAD_TEXT 4001
+
+// codes for completion cleanup
+#define IDS_FILE_UPDATE_ERROR 4101
+#define IDS_FILE_DELETE_ERROR 4103
+#define IDS_JAVA_HOME_ERROR 4104
+#define IDS_KERNEL_HOME_ERROR 4105
+#define IDS_JBROKER_ERROR 4106
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 128
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1016
+#define _APS_NEXT_SYMED_VALUE 103
+#endif
+#endif
diff --git a/src/windows/native/sun/jkernel/stdafx.cpp b/src/windows/native/sun/jkernel/stdafx.cpp
new file mode 100644
index 000000000..f0c6e9f3f
--- /dev/null
+++ b/src/windows/native/sun/jkernel/stdafx.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// stdafx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#include <statreg.cpp>
+#endif
+
+#include <atlimpl.cpp>
diff --git a/src/windows/native/sun/jkernel/stdafx.h b/src/windows/native/sun/jkernel/stdafx.h
new file mode 100644
index 000000000..131c1a393
--- /dev/null
+++ b/src/windows/native/sun/jkernel/stdafx.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#if !defined(AFX_STDAFX_H__FBC6C744_18F8_11D6_9DF1_0001023B10AA__INCLUDED_)
+#define AFX_STDAFX_H__FBC6C744_18F8_11D6_9DF1_0001023B10AA__INCLUDED_
+
+#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>
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__FBC6C744_18F8_11D6_9DF1_0001023B10AA__INCLUDED)
diff --git a/src/windows/native/sun/jkernel/version.rc b/src/windows/native/sun/jkernel/version.rc
new file mode 100644
index 000000000..1d2cbb0f3
--- /dev/null
+++ b/src/windows/native/sun/jkernel/version.rc
@@ -0,0 +1,73 @@
+/*
+ * 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 "afxres.h"
+
+// Need 2 defines so macro argument to XSTR will get expanded before quoting.
+#define XSTR(x) STR(x)
+#define STR(x) #x
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION JDK_FVER
+ PRODUCTVERSION JDK_FVER
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only
+ FILEOS 0x4L
+ // FILETYPE should be 0x1 for .exe and 0x2 for .dll
+ FILETYPE JDK_FTYPE
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", XSTR(JDK_COMPANY) "\0"
+ VALUE "FileDescription", XSTR(JDK_COMPONENT) "\0"
+ VALUE "FileVersion", XSTR(JDK_VER) "\0"
+ VALUE "Full Version", XSTR(JDK_BUILD_ID) "\0"
+ VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0"
+ VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0"
+ VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0"
+ VALUE "ProductName", XSTR(JDK_NAME) "\0"
+ VALUE "ProductVersion", XSTR(JDK_VER) "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/src/windows/native/sun/windows/awt.rc b/src/windows/native/sun/windows/awt.rc
index 7eb4d41af..a5367ecb5 100644
--- a/src/windows/native/sun/windows/awt.rc
+++ b/src/windows/native/sun/windows/awt.rc
@@ -48,8 +48,8 @@ SECURITY_WARNING_2 ICON DISCARDABLE "security_warning.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION J2SE_FVER
- PRODUCTVERSION J2SE_FVER
+ FILEVERSION JDK_FVER
+ PRODUCTVERSION JDK_FVER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -59,22 +59,22 @@ VS_VERSION_INFO VERSIONINFO
// FILEOS 0x4 is Win32, 0x40004 is Win32 NT only
FILEOS 0x4L
// FILETYPE should be 0x1 for .exe and 0x2 for .dll
- FILETYPE J2SE_FTYPE
+ FILETYPE JDK_FTYPE
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", XSTR(J2SE_COMPANY) "\0"
- VALUE "FileDescription", XSTR(J2SE_COMPONENT) "\0"
- VALUE "FileVersion", XSTR(J2SE_VER) "\0"
- VALUE "Full Version", XSTR(J2SE_BUILD_ID) "\0"
- VALUE "InternalName", XSTR(J2SE_INTERNAL_NAME) "\0"
- VALUE "LegalCopyright", XSTR(J2SE_COPYRIGHT) "\0"
- VALUE "OriginalFilename", XSTR(J2SE_FNAME) "\0"
- VALUE "ProductName", XSTR(J2SE_NAME) "\0"
- VALUE "ProductVersion", XSTR(J2SE_VER) "\0"
+ VALUE "CompanyName", XSTR(JDK_COMPANY) "\0"
+ VALUE "FileDescription", XSTR(JDK_COMPONENT) "\0"
+ VALUE "FileVersion", XSTR(JDK_VER) "\0"
+ VALUE "Full Version", XSTR(JDK_BUILD_ID) "\0"
+ VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0"
+ VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0"
+ VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0"
+ VALUE "ProductName", XSTR(JDK_NAME) "\0"
+ VALUE "ProductVersion", XSTR(JDK_VER) "\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/windows/resource/unpack200_proto.exe.manifest b/src/windows/resource/unpack200_proto.exe.manifest
new file mode 100644
index 000000000..739f9b994
--- /dev/null
+++ b/src/windows/resource/unpack200_proto.exe.manifest
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity version="IMVERSION"
+ processorArchitecture="X86"
+ name="unpack200.exe"
+ type="win32"/>
+
+ <description>Java(TM) SE Runtime Environment unpack200 Process.</description>
+ <!-- Identify the application security requirements. -->
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel
+ level="asInvoker"
+ uiAccess="false"/>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+</assembly>
diff --git a/src/windows/resource/version.rc b/src/windows/resource/version.rc
index 414795624..dff3ae50f 100644
--- a/src/windows/resource/version.rc
+++ b/src/windows/resource/version.rc
@@ -37,8 +37,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION J2SE_FVER
- PRODUCTVERSION J2SE_FVER
+ FILEVERSION JDK_FVER
+ PRODUCTVERSION JDK_FVER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -48,22 +48,22 @@ VS_VERSION_INFO VERSIONINFO
// FILEOS 0x4 is Win32, 0x40004 is Win32 NT only
FILEOS 0x4L
// FILETYPE should be 0x1 for .exe and 0x2 for .dll
- FILETYPE J2SE_FTYPE
+ FILETYPE JDK_FTYPE
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
- VALUE "CompanyName", XSTR(J2SE_COMPANY) "\0"
- VALUE "FileDescription", XSTR(J2SE_COMPONENT) "\0"
- VALUE "FileVersion", XSTR(J2SE_VER) "\0"
- VALUE "Full Version", XSTR(J2SE_BUILD_ID) "\0"
- VALUE "InternalName", XSTR(J2SE_INTERNAL_NAME) "\0"
- VALUE "LegalCopyright", XSTR(J2SE_COPYRIGHT) "\0"
- VALUE "OriginalFilename", XSTR(J2SE_FNAME) "\0"
- VALUE "ProductName", XSTR(J2SE_NAME) "\0"
- VALUE "ProductVersion", XSTR(J2SE_VER) "\0"
+ VALUE "CompanyName", XSTR(JDK_COMPANY) "\0"
+ VALUE "FileDescription", XSTR(JDK_COMPONENT) "\0"
+ VALUE "FileVersion", XSTR(JDK_VER) "\0"
+ VALUE "Full Version", XSTR(JDK_BUILD_ID) "\0"
+ VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0"
+ VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0"
+ VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0"
+ VALUE "ProductName", XSTR(JDK_NAME) "\0"
+ VALUE "ProductVersion", XSTR(JDK_VER) "\0"
END
END
BLOCK "VarFileInfo"
diff --git a/test/java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java b/test/java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java
index 4375385e5..9be8b5267 100644
--- a/test/java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java
+++ b/test/java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java
@@ -416,5 +416,3 @@ class GlobalListener implements AWTEventListener {
// }
}
}
-
-
diff --git a/test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java b/test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java
index 220ccaf6b..f508d6152 100644
--- a/test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java
+++ b/test/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java
@@ -105,4 +105,3 @@ class TestFailedException extends RuntimeException {
super("Test failed: " + msg);
}
}
-
diff --git a/test/java/awt/font/Rotate/TranslatedOutlineTest.java b/test/java/awt/font/Rotate/TranslatedOutlineTest.java
index d94b37535..f2ea25082 100644
--- a/test/java/awt/font/Rotate/TranslatedOutlineTest.java
+++ b/test/java/awt/font/Rotate/TranslatedOutlineTest.java
@@ -66,4 +66,3 @@ public class TranslatedOutlineTest {
throw new RuntimeException("Outline was not detected");
}
}
-
diff --git a/test/java/awt/font/Threads/FontThread.java b/test/java/awt/font/Threads/FontThread.java
index 0db9ae2c3..3cd2fc8f0 100644
--- a/test/java/awt/font/Threads/FontThread.java
+++ b/test/java/awt/font/Threads/FontThread.java
@@ -85,5 +85,3 @@ public class FontThread extends Thread {
}
}
}
-
-
diff --git a/test/java/security/AccessControlContext/FailureDebugOption.java b/test/java/security/AccessControlContext/FailureDebugOption.java
index df48203ec..f372b3e51 100644
--- a/test/java/security/AccessControlContext/FailureDebugOption.java
+++ b/test/java/security/AccessControlContext/FailureDebugOption.java
@@ -47,4 +47,3 @@ public class FailureDebugOption {
}
}
}
-
diff --git a/test/javax/swing/JPopupMenu/6691503/bug6691503.java b/test/javax/swing/JPopupMenu/6691503/bug6691503.java
index a044ac3b6..a258ab68e 100644
--- a/test/javax/swing/JPopupMenu/6691503/bug6691503.java
+++ b/test/javax/swing/JPopupMenu/6691503/bug6691503.java
@@ -109,5 +109,3 @@ public class bug6691503 {
});
}
}
-
-
diff --git a/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
index 3dcd07673..64de767e1 100644
--- a/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
+++ b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
@@ -106,4 +106,3 @@ public class TestRSACipherWrap extends PKCS11Test {
main(new TestRSACipherWrap());
}
}
-
diff --git a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
index 56eff7e3f..499c102f8 100644
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
@@ -113,4 +113,3 @@ public class AsyncSSLSocketClose implements Runnable
}
}
-
diff --git a/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java b/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
index c6098fbf7..a2aff33f4 100644
--- a/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
+++ b/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
@@ -305,4 +305,3 @@ public class CloseKeepAliveCached {
}
}
}
-