Merge
authoryhuang
Sun, 17 Jan 2010 18:42:34 -0800
changeset 4619 dd3bacb9f730
parent 4618 ff5d0801d4b7 (current diff)
parent 4598 84421ca43e39 (diff)
child 4620 3effa7542ca5
child 5303 0c91825f1cfa
Merge
--- a/jdk/make/Makefile	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/Makefile	Sun Jan 17 18:42:34 2010 -0800
@@ -74,6 +74,7 @@
 import_product    -- copy in the product components \n\
 import_fastdebug  -- copy in the fastdebug components \n\
 import_debug      -- copy in the debug components \n\
+modules           -- build the jdk and jre module images (experimental) \n\
 sccs_get          -- make sure all SCCS files are up-to-date (need SCCS) \n\
 create_links      -- create softlinks in Solaris 32bit build to 64bit dirs \n\
 "
@@ -257,6 +258,7 @@
 # Release engineering targets.
 #
 include $(BUILDDIR)/common/Release.gmk
+include $(BUILDDIR)/common/Modules.gmk
 
 #
 # Cscope targets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/common/Modules.gmk	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,442 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+JDK_MODULE_IMAGE_DIR = $(ABS_OUTPUTDIR)/jdk-module-image
+JRE_MODULE_IMAGE_DIR = $(ABS_OUTPUTDIR)/jre-module-image
+
+#
+# modules   Target to build jdk and jre module image
+#
+#           There is one jar file per module containing classes only.
+#           All module jars are currently placed under jre/lib directory.
+#
+# Open issues that need further investigation:
+# 1. Classes in jre/lib/ext/dnsns.jar are currently put in jre/lib/jndi-dns
+#    module.
+# 2. Signed jars
+#    For JDK build, signed jars are copied to the build.
+#    All jars in the module image are unsigned.
+# 3. jre/lib/security/US_export_policy.jar and local_policy.jar
+#    are not included in the module image yet.
+
+MODULE_IMAGEBINDIR = bin
+
+#
+# Targets.
+#
+INITIAL_MODULE_IMAGE_JRE=initial-module-image-jre
+INITIAL_MODULE_IMAGE_JDK=initial-module-image-jdk
+ifeq ($(PLATFORM), solaris)
+  ifeq ($(ARCH_DATA_MODEL), 64)
+    INITIAL_MODULE_IMAGE_JRE=initial-module-image-jre-sol64
+    INITIAL_MODULE_IMAGE_JDK=initial-module-image-jdk-sol64
+  endif
+endif
+
+modules modules-clobber \
+initial-module-image-jre initial-module-image-jdk \
+initial-module-image-jre-sol64 initial-module-image-jdk-sol64 \
+trim-module-image-jre trim-module-image-jdk \
+process-module-image-jre process-module-image-jdk ::
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+
+# Order is important here, trim jre after jdk image is created
+modules:: sanity-module-images post-sanity-module-images  \
+	 $(INITIAL_MODULE_IMAGE_JRE) $(INITIAL_MODULE_IMAGE_JDK) \
+	 trim-module-image-jre trim-module-image-jdk \
+	 process-module-image-jre process-module-image-jdk
+
+# Don't use these
+module-image-jre:: initial-module-image-jre trim-module-image-jre process-module-image-jre
+module-image-jdk:: initial-module-image-jdk trim-module-image-jdk process-module-image-jdk
+
+#
+# Paths to these files we need
+JDK_MODULE_LICENSES   = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
+JDK_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%64)
+JDK_MODULE_DOCFILES   = $(OTHER_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
+
+JRE_MODULE_LICENSES   = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
+JRE_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%64)
+JRE_MODULE_DOCFILES   = $(OTHER_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
+JRE_MODULE_DOCFILES  += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX))
+
+###### RULES
+
+# JDK files
+$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%
+	$(process-doc-file)
+# Removes LICENSE_VERSION or not
+ifdef LICENSE_VERSION
+$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+else
+$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%
+	$(process-doc-file)
+endif
+
+# JRE files 
+$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+# Add $(TEXT_SUFFIX) suffix
+ifdef TEXT_SUFFIX
+$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+endif
+# Removes LICENSE_VERSION or not
+ifdef LICENSE_VERSION
+$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+else
+$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+endif
+
+######################################################
+# JRE Image
+######################################################
+
+MODULES_TEMPDIR=$(ABS_TEMPDIR)/modules
+MODULES_LIB = $(ABS_OUTPUTDIR)/modules
+
+gen-modules:
+	$(CD) modules; $(MAKE) all
+
+initial-module-image-jre-setup:
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)
+	$(MKDIR) -p $(JRE_MODULE_IMAGE_DIR)
+
+# 64-bit solaris jre image contains only the 64-bit add-on files.
+initial-module-image-jre-sol64:: initial-module-image-jre-setup \
+			  $(JRE_MODULE_LICENSES) $(JRE_MODULE_64_LICENSES)
+	@# Use tar instead of cp to preserve the symbolic links
+	for dir in bin lib ; do \
+	  ( $(CD) $(OUTPUTDIR) && \
+		$(TAR) cf - `$(FIND) $$dir -name '$(ARCH)' -print` | \
+		($(CD) $(JRE_MODULE_IMAGE_DIR) && $(TAR) xf -) ) ; \
+	done
+	@# Remove some files from the jre area
+	for t in $(NOTJRETOOLS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin$(ISA_DIR)/$$t ; \
+	done
+	$(RM) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'orb.idl'`
+	$(RM) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'ir.idl'`
+
+# Construct an initial jre image (initial jdk jre) no trimming or stripping
+initial-module-image-jre:: initial-module-image-jre-setup \
+		    $(JRE_LICENSES) $(JRE_MODULE_DOCFILES) \
+		    gen-modules \
+		    $(BUILDMETAINDEX_JARFILE)
+	@# Copy in bin directory
+	$(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR)
+	@# CTE plugin security change require new empty directory lib/applet
+	$(MKDIR) -p $(JRE_MODULE_IMAGE_DIR)/lib/applet
+	@# Copy files but not .jar in lib directory 
+	$(CD) $(OUTPUTDIR) && $(FIND) lib -depth | $(EGREP) -v ".jar$$" | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR)
+	@#
+	@# copy modules to jre/lib
+	@#
+	$(CP) -rf $(MODULES_LIB)/jre/lib/* $(JRE_MODULE_IMAGE_DIR)/lib 
+	@# Make sure all directories are read/execute for everyone
+	$(CHMOD) a+rx `$(FIND) $(JRE_MODULE_IMAGE_DIR) -type d`
+	@# Remove some files from the jre area
+	for t in $(NOTJRETOOLS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin$(ISA_DIR)/$$t ; \
+	done
+	@# Remove orb.idl and ir.idl from jre
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'orb.idl' -exec $(RM) \{} \;
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'ir.idl' -exec $(RM) \{} \;
+	@# Generate meta-index to make boot and extension class loaders lazier
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \
+	    $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
+		-o meta-index *.jar
+	@$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && $(java-vm-cleanup)
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/lib/ext && \
+	    $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
+		-o meta-index *.jar
+	@$(CD) $(JRE_MODULE_IMAGE_DIR)/lib/ext && $(java-vm-cleanup)
+ifeq ($(PLATFORM), windows)
+	@# Remove certain *.lib files
+	$(CD) $(JRE_MODULE_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_MODULE_IMAGE_DIR)/bin && $(RM) -r kernel
+  endif
+endif # Windows
+ifneq ($(PLATFORM), windows)
+	$(call copy-man-pages,$(JRE_MODULE_IMAGE_DIR),$(JRE_MAN_PAGES))
+endif # !windows
+
+# Trim out any extra files not for the jre shipment but wanted in the jdk jre.
+#   (Note the jdk WILL want the jre image before this trimming)
+#   Removes server VM on Windows 32bit.
+#   Remove certain shared libraries that should not be in the jre image
+#      but should be in the jdk jre image.
+trim-module-image-jre::
+ifeq ($(PLATFORM), windows)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)/bin/server
+  endif
+  ifdef NOTJRE_SHARED_LIBS
+	for l in $(NOTJRE_SHARED_LIBS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin/$$l ; \
+	done ;
+  endif
+else # PLATFORM
+  ifdef NOTJRE_SHARED_LIBS
+	for l in $(NOTJRE_SHARED_LIBS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/lib/$(LIBARCH)/$$l ; \
+	done ;
+  endif
+endif # PLATFORM
+
+# Get list of all Elf files in the jre
+JRE_MODULE_ELF_LIST=$(MODULES_TEMPDIR)/jre-elf-files.list
+$(JRE_MODULE_ELF_LIST):
+	@$(prep-target)
+ifneq ($(PLATFORM), windows)
+	$(RM) $@
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -type f -name \*.$(LIB_SUFFIX) >> $@
+	$(FILE) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+endif
+
+# Post process the image (strips and mcs on Elf files we are shipping)
+#   (Note the jdk WILL want the jre image before this processing)
+process-module-image-jre:: $(JRE_MODULE_ELF_LIST)
+ifneq ($(POST_STRIP_PROCESS), )
+	for f in `$(CAT) $(JRE_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_STRIP_PROCESS) $${f}; \
+	  $(POST_STRIP_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+ifneq ($(POST_MCS_PROCESS), )
+	for f in `$(CAT) $(JRE_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_MCS_PROCESS) $${f}; \
+	  $(POST_MCS_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+	$(RM) $(JRE_MODULE_ELF_LIST)
+
+######################################################
+# JDK Image
+######################################################
+# Note: cpio ($(CPIO)) sometimes leaves directories without rx access.
+
+initial-module-image-jdk-setup:
+	$(RM) -r $(JDK_MODULE_IMAGE_DIR)
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/jre
+	($(CD) $(JRE_MODULE_IMAGE_DIR) && $(FIND) . -depth -print \
+	      | $(CPIO) -pdum $(JDK_MODULE_IMAGE_DIR)/jre )
+	$(RM) -rf $(JDK_MODULE_IMAGE_DIR)/jre/man
+	$(CHMOD) a+rx `$(FIND) $(JDK_MODULE_IMAGE_DIR) -type d`
+
+initial-module-image-jdk64-bindemos:
+	for dir in bin demo ; do \
+	  ( $(CD) $(OUTPUTDIR) && \
+		$(TAR) cf - `$(FIND) $$dir -name '$(LIBARCH)' -print` | \
+		($(CD) $(JDK_MODULE_IMAGE_DIR) && $(TAR) xf -) ) ; \
+        done
+
+# Solaris 64 bit image is special
+initial-module-image-jdk-sol64:: initial-module-image-jdk-setup \
+			  initial-module-image-jdk64-bindemos \
+			  $(JDK_MODULE_LICENSES) $(JDK_MODULARLIZED_64_LICENSES)
+
+# DB files to add
+ifeq ($(OPENJDK),true)
+
+initial-module-image-jdk-db:
+
+else
+
+# Create the list of db *.zip files to bundle with jdk
+ABS_DB_PATH  :=$(call FullPath,$(CLOSED_SHARE_SRC)/db)
+DB_ZIP_LIST = $(shell $(LS) $(ABS_DB_PATH)/*.zip 2>/dev/null)
+
+initial-module-image-jdk-db: $(DB_ZIP_LIST)
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/db
+	for d in $(DB_ZIP_LIST); do \
+          ($(CD) $(JDK_MODULE_IMAGE_DIR)/db && $(UNZIP) -o $$d); \
+	done
+
+endif
+
+# Standard jdk image
+initial-module-image-jdk:: initial-module-image-jdk-setup \
+		    initial-module-image-jdk-db \
+		    $(JDK_MODULE_LICENSES) $(JDK_MODULE_DOCFILES)
+	$(MKDIR) $(JDK_MODULE_IMAGE_DIR)/lib
+	@#
+	@# copy jdk modules to jdk/lib
+	@#
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/lib
+	$(CP) -rf $(MODULES_LIB)/lib/* $(JDK_MODULE_IMAGE_DIR)/lib 
+  ifeq ($(PLATFORM), windows)
+	@#
+	@# lib/
+	@#
+	$(CP) $(LIBDIR)/$(LIB_PREFIX)jvm.$(LIB_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/lib
+	$(CP) $(LIBDIR)/$(LIB_PREFIX)jawt.$(LIB_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/lib
+	@#
+	@# bin/
+	@#
+	@# copy all EXE files and only certain DLL files from BINDIR
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/bin
+	$(CP) $(BINDIR)/*$(EXE_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+	$(CP) $(BINDIR)/jli.$(LIBRARY_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+    ifeq ($(ARCH_DATA_MODEL), 32)
+      ifeq ($(COMPILER_VERSION), VS2003)
+	$(CP) $(BINDIR)/msvc*71.$(LIBRARY_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+      endif
+    endif
+  else # PLATFORM
+	@#
+	@# bin/
+	@#
+	($(CD) $(BINDIR)/.. && $(TAR) cf - \
+	    `$(FIND) bin \( -type f -o -type l \) -print `) | \
+	    ($(CD) $(JDK_MODULE_IMAGE_DIR) && $(TAR) xf -)
+  endif # PLATFORM
+	@#
+	@# lib/ct.sym
+	@#
+	$(MKDIR) -p $(OUTPUTDIR)/symbols/META-INF/sym
+	$(JAVAC_CMD) -XDprocess.packages -proc:only \
+	    -processor com.sun.tools.javac.sym.CreateSymbols \
+	    -Acom.sun.tools.javac.sym.Jar=$(RT_JAR) \
+	    -Acom.sun.tools.javac.sym.Dest=$(OUTPUTDIR)/symbols/META-INF/sym/rt.jar \
+	    $(CORE_PKGS) $(NON_CORE_PKGS) $(EXCLUDE_PROPWARN_PKGS)
+	$(BOOT_JAR_CMD) c0f $(LIBDIR)/ct.sym \
+	    -C $(OUTPUTDIR)/symbols META-INF $(BOOT_JAR_JFLAGS)
+	@$(java-vm-cleanup)
+	$(CP) $(LIBDIR)/ct.sym $(JDK_MODULE_IMAGE_DIR)/lib/ct.sym
+	@#
+	@# CORBA supported orb.idl and ir.idl should be copied to lib
+	@#
+	$(CP) $(LIBDIR)/orb.idl $(JDK_MODULE_IMAGE_DIR)/lib/orb.idl
+	$(CP) $(LIBDIR)/ir.idl $(JDK_MODULE_IMAGE_DIR)/lib/ir.idl
+  ifeq ($(PLATFORM), linux)
+	@#
+	@# on Linux copy jexec from jre/lib to /lib
+	@#
+	$(CP) $(LIBDIR)/jexec $(JDK_MODULE_IMAGE_DIR)/lib/jexec
+  endif # PLATFORM
+	@#
+	@# demo, include
+	@#
+	$(CP) -r -f $(DEMODIR) $(JDK_MODULE_IMAGE_DIR)
+	$(CP) -r -f $(SAMPLEDIR) $(JDK_MODULE_IMAGE_DIR)
+	$(CP) -r $(INCLUDEDIR) $(JDK_MODULE_IMAGE_DIR)
+	@#
+	@# Swing BeanInfo generation
+	@#
+	$(CD) javax/swing/beaninfo && $(MAKE) JDK_IMAGE_DIR=$(JDK_MODULE_IMAGE_DIR) swing-1.2-beans
+ifneq ($(PLATFORM), windows)
+	$(call copy-man-pages,$(JDK_MODULE_IMAGE_DIR),$(JDK_MAN_PAGES))
+endif # !windows
+
+# Trim out files we don't want to ship
+trim-module-image-jdk::
+	@# Remove tools that should not be part of SDK.
+	for t in $(NOTJDKTOOLS); do \
+	    $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \
+		  $(JDK_MODULE_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \
+	done
+
+# Get list of Elf files in the jdk
+JDK_MODULE_ELF_LIST=$(MODULES_TEMPDIR)/jdk-elf-files.list
+$(JDK_MODULE_ELF_LIST):
+	@$(prep-target)
+ifneq ($(PLATFORM), windows)
+	$(RM) $@
+	$(FIND) $(JDK_MODULE_IMAGE_DIR)/jre/lib -type f -name \*.$(LIB_SUFFIX) >> $@
+	$(FILE) `$(FIND) $(JDK_MODULE_IMAGE_DIR)/jre/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+	file `$(FIND) $(JDK_MODULE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+endif
+
+# Post process the image (strips and mcs on files we are shipping)
+process-module-image-jdk:: $(JDK_MODULE_ELF_LIST)
+ifneq ($(POST_STRIP_PROCESS), )
+	for f in `$(CAT) $(JDK_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_STRIP_PROCESS) $${f}; \
+	  $(POST_STRIP_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+ifneq ($(POST_MCS_PROCESS), )
+	for f in `$(CAT) $(JDK_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_MCS_PROCESS) $${f}; \
+	  $(POST_MCS_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+	$(RM) $(JDK_MODULE_ELF_LIST)
+
+######################################################
+# clobber
+######################################################
+modules-clobber::
+	$(RM) -r $(JDK_MODULE_IMAGE_DIR)
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)
+
+#
+# TODO - nop for now
+sanity-module-images post-sanity-module-images:
+
+modules modules-clobber::
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+	@$(java-vm-cleanup)
+
+.PHONY: modules module-image-jre module-image-jdk \
+	initial-module-image-jre initial-module-image-jdk \
+	initial-module-image-jre-sol64 initial-module-image-jdk-sol64 \
+        initial-module-image-jdk-setup \
+	initial-module-image-jdk-db \
+        initial-module-image-jdk64-bindemos \
+        initial-module-image-jre-setup \
+	trim-module-image-jre trim-module-image-jdk \
+	process-module-image-jre process-module-image-jdk \
+	install-previous-jre install-previous-jdk \
+	modules-clobber
+
+# Force rule
+FRC:
+
--- a/jdk/make/java/java/mapfile-vers	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/java/mapfile-vers	Sun Jan 17 18:42:34 2010 -0800
@@ -150,10 +150,8 @@
 		Java_java_lang_StrictMath_asin;
 		Java_java_lang_StrictMath_atan;
 		Java_java_lang_StrictMath_atan2;
-		Java_java_lang_StrictMath_ceil;
 		Java_java_lang_StrictMath_cos;
 		Java_java_lang_StrictMath_exp;
-		Java_java_lang_StrictMath_floor;
 		Java_java_lang_StrictMath_log;
 		Java_java_lang_StrictMath_log10;
 		Java_java_lang_StrictMath_pow;
--- a/jdk/make/java/java/reorder-i586	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/java/reorder-i586	Sun Jan 17 18:42:34 2010 -0800
@@ -107,4 +107,3 @@
 text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/java/reorder-sparc	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/java/reorder-sparc	Sun Jan 17 18:42:34 2010 -0800
@@ -105,4 +105,3 @@
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
 text: .text%Java_java_lang_StrictMath_sqrt;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/java/reorder-sparcv9	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/java/reorder-sparcv9	Sun Jan 17 18:42:34 2010 -0800
@@ -101,4 +101,3 @@
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
 text: .text%Java_java_lang_StrictMath_sqrt;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/jli/Makefile	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/jli/Makefile	Sun Jan 17 18:42:34 2010 -0800
@@ -152,7 +152,6 @@
 STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
 
 $(STATIC_LIBRARY_DIR): $(OBJDIR)
-	@$(prep-target)
 	@$(MKDIR) $(STATIC_LIBRARY_DIR)
 
 $(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
--- a/jdk/make/java/nio/FILES_java.gmk	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/nio/FILES_java.gmk	Sun Jan 17 18:42:34 2010 -0800
@@ -234,6 +234,7 @@
 	sun/nio/cs/UTF_16BE.java \
 	sun/nio/cs/UTF_16LE.java \
 	sun/nio/cs/UTF_8.java \
+	sun/nio/cs/Unicode.java \
 	sun/nio/cs/UnicodeDecoder.java \
 	sun/nio/cs/UnicodeEncoder.java \
 	sun/nio/cs/UTF_32.java \
--- a/jdk/make/java/nio/genBuffer.sh	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/make/java/nio/genBuffer.sh	Sun Jan 17 18:42:34 2010 -0800
@@ -44,6 +44,7 @@
 
 case $type in
   char)  fulltype=character;;
+  int)   fulltype=integer;;
   *)     fulltype=$type;;
 esac
 
@@ -54,6 +55,11 @@
   long | double)  LBPV=3;;
 esac
 
+case $type in 
+  float|double) floatingPointOrIntegralType=floatingPointType;;
+  *)            floatingPointOrIntegralType=integralType;;
+esac
+
 typesAndBits() {
 
   type="$1"; BO="$2"
@@ -101,6 +107,7 @@
 
 $SPP <$SRC >$DST \
   -K$type \
+  -K$floatingPointOrIntegralType \
   -Dtype=$type \
   -DType=$Type \
   -Dfulltype=$fulltype \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/Makefile	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,145 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Modularizing the JDK
+#
+
+BUILDDIR = ..
+include $(BUILDDIR)/common/Defs.gmk
+
+CLASSANALYZER_JAR=$(BUILDTOOLJARDIR)/classanalyzer.jar
+JAVA_FLAGS=$(JAVA_TOOLS_FLAGS) -Xbootclasspath:$(CLASSBINDIR)
+
+MODULE_LIB = $(ABS_OUTPUTDIR)/modules
+MAINMANIFEST=$(JDK_TOPDIR)/make/tools/manifest.mf
+MODULE_JAR_MANIFEST_FILE=$(ABS_TEMPDIR)/manifest.tmp
+
+TMP=$(ABS_TEMPDIR)/modules
+MODULE_CLASSLIST = $(TMP)/classlist
+MODULE_CLASSES = $(TMP)/classes
+MODULE_LIST = $(MODULE_CLASSLIST)/modules.list
+
+# Modules in the modules/ext directory
+EXT_MODULES = localedata security-sunec security-sunjce
+
+# Build PKCS#11 on all platforms except 64-bit Windows.
+# We exclude windows-amd64 because we don't have any
+# 64-bit PKCS#11 implementations to test with on that platform.
+PKCS11 = security-sunpkcs11
+ifeq ($(ARCH_DATA_MODEL), 64)
+  ifeq ($(PLATFORM), windows)
+    PKCS11 =
+  endif
+endif
+
+EXT_MODULES += $(PKCS11)
+
+# Build Microsoft CryptoAPI provider only on (non-64-bit) Windows platform.
+ifeq ($(PLATFORM), windows)
+  ifneq ($(ARCH_DATA_MODEL), 64)
+    EXT_MODULES += security-sunmscapi
+  endif
+endif
+
+
+JDK_MODULES = tools
+
+SUBDIRS = tools
+all build clean clobber::
+	$(SUBDIRS-loop)
+
+all:: unpack-jars gen-classlist modularize
+
+$(CLASSANALYZER_JAR):
+	$(CD) tools && $(MAKE) all
+
+JAR_LIST := $(shell $(FIND) $(ABS_OUTPUTDIR)/lib -name \*.jar -depth) 
+unpack-jars:
+	$(RM) -rf $(MODULE_CLASSES)
+	$(MKDIR) -p $(MODULE_CLASSES)
+	$(CP) -rf $(CLASSBINDIR)/* $(MODULE_CLASSES)
+	for jf in  $(JAR_LIST) ; do \
+	   $(CD) $(MODULE_CLASSES) && $(BOOT_JAR_CMD) xf $$jf $(BOOT_JAR_JFLAGS);\
+	done
+
+gen-classlist: $(CLASSANALYZER_JAR)
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+	@$(RM) -rf $(MODULE_CLASSLIST)
+	@$(MKDIR) -p $(MODULE_CLASSLIST)
+
+	@# Use java in the default tool directory.
+	@# OUTPUTDIR for solaris 64-bit doesn't have the tools.
+	$(JAVA_TOOLS_DIR)/java $(JAVA_FLAGS) \
+		-Dclassanalyzer.debug \
+		-jar $(CLASSANALYZER_JAR) \
+		-jdkhome $(OUTPUTDIR) \
+	        -config modules.config \
+	        -config modules.group \
+		-depconfig jdk7.depconfig \
+		-depconfig optional.depconfig \
+		-showdynamic \
+		-output $(MODULE_CLASSLIST)
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+
+modularize: $(MODULE_JAR_MANIFEST_FILE)
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+	@$(RM) -rf $(MODULE_LIB)
+	@$(MKDIR) -p $(MODULE_LIB)/lib
+	@$(MKDIR) -p $(MODULE_LIB)/jre/lib/ext
+
+	@# create modules
+	for m in `$(NAWK) '{print $$1}' $(MODULE_LIST)` ; do \
+   	   $(ECHO) "Creating module $$m" ; \
+   	   $(SED) -e 's%\\%\/%g' < $(MODULE_CLASSLIST)/$$m.classlist > $(TMP)/tmp.cf ; \
+	   if [ -f $(MODULE_CLASSLIST)/$$m.resources ] ; then \
+   	       $(SED) -e 's%\\%\/%g' < $(MODULE_CLASSLIST)/$$m.resources >> $(TMP)/tmp.cf ; \
+           fi ; \
+	   $(CD) $(MODULE_CLASSES) && \
+               $(BOOT_JAR_CMD) c0mf $(MODULE_JAR_MANIFEST_FILE) \
+		   $(MODULE_LIB)/$$m.jar \
+		   @$(TMP)/tmp.cf \
+                   $(BOOT_JAR_JFLAGS) ; \
+	done
+	@$(CD) $(MODULE_CLASSES) && $(java-vm-cleanup)
+	@# move modules to lib, jre/lib, or jre/lib/ext
+	for m in $(EXT_MODULES) ; do \
+	   $(MV) $(MODULE_LIB)/$$m.jar $(MODULE_LIB)/jre/lib/ext ; \
+	done
+	for m in $(JDK_MODULES) ; do \
+	   $(MV) $(MODULE_LIB)/$$m.jar $(MODULE_LIB)/lib ; \
+	done
+	$(MV) $(MODULE_LIB)/*.jar $(MODULE_LIB)/jre/lib
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+
+$(MODULE_JAR_MANIFEST_FILE):
+	$(SED) -e "s/@@RELEASE@@/$(RELEASE)/" $(MAINMANIFEST) > $@
+
+clean clobber::
+	$(RM) -rf $(MODULE_CLASSLIST)
+	$(RM) -rf $(MODULE_LIB)
+	$(RM) -f $(MODULE_JAR_MANIFEST_FILE)
+	$(RM) -f $(CLASSANALYZER_JAR)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/bootmodule.roots	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,199 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+
+#
+# List of root classes/methods, each line of the following syntax:
+# <class name> 
+# <method name> <signature>|*
+# exclude <class>|<method> 
+
+# The boot module generated based on this rootset does not support
+# - security permission check
+# - non-standard charset
+# - logging output
+# - resource bundles
+#   including error output from the launcher 
+
+# VM preloaded classes
+java.lang.Object
+java.lang.String
+java.lang.Class
+java.lang.Cloneable
+java.lang.ClassLoader
+java.lang.System
+java.lang.Throwable
+java.lang.Error
+java.lang.ThreadDeath
+java.lang.Exception
+java.lang.RuntimeException
+java.security.ProtectionDomain
+java.security.AccessControlContext
+java.lang.ClassNotFoundException
+java.lang.NoClassDefFoundError
+java.lang.ClassCastException
+java.lang.ArrayStoreException
+java.lang.VirtualMachineError
+java.lang.OutOfMemoryError
+java.lang.StackOverflowError
+java.lang.IllegalMonitorStateException
+java.lang.ref.Reference
+java.lang.ref.SoftReference
+java.lang.ref.WeakReference
+java.lang.ref.FinalReference
+java.lang.ref.PhantomReference
+java.lang.ref.Finalizer
+java.lang.Runnable
+java.lang.Thread
+java.lang.ThreadGroup
+java.util.Properties
+java.lang.reflect.AccessibleObject
+java.lang.reflect.Member
+java.lang.reflect.Field
+java.lang.reflect.Method
+java.lang.reflect.Constructor
+java.lang.reflect.Type
+sun.reflect.MagicAccessorImpl
+sun.reflect.MethodAccessorImpl
+sun.reflect.ConstructorAccessorImpl
+sun.reflect.DelegatingClassLoader
+sun.reflect.ConstantPool
+sun.reflect.UnsafeStaticFieldAccessorImpl
+java.util.Vector
+java.lang.StringBuffer
+java.lang.StackTraceElement
+java.nio.Buffer
+java.lang.Boolean
+java.lang.Character
+java.lang.Float
+java.lang.Double
+java.lang.Byte
+java.lang.Short
+java.lang.Integer
+java.lang.Long
+java.lang.NullPointerException
+java.lang.ArithmeticException
+java.lang.Compiler
+
+
+# Root methods
+java.lang.ClassLoader.getSystemClassLoader ()Ljava/lang/ClassLoader;
+java.lang.System.initializeSystemClass ()V
+sun.launcher.LauncherHelper.checkAndLoadMain (ZZLjava/lang/String;)Ljava/lang/Object;
+
+# The tool doesn't automatically find superclasses and parse the method
+# if overridden as it tries to reduce unnecessary classes being pulled in.
+# The following forces the dependency to be included the result.
+sun.net.www.protocol.file.Handler.<init> ()V
+sun.net.www.protocol.jar.Handler.<init> ()V
+sun.net.www.protocol.file.Handler.openConnection *
+sun.net.www.protocol.jar.Handler.openConnection *
+sun.misc.URLClassPath$JarLoader.<init>  (Ljava/net/URL;Ljava/net/URLStreamHandler;Ljava/util/HashMap;)V
+sun.misc.URLClassPath$FileLoader.<init> (Ljava/net/URL;)V
+sun.misc.URLClassPath$FileLoader.getClassPath *
+sun.misc.URLClassPath$FileLoader.getResource *
+sun.misc.URLClassPath$JarLoader.getResource *
+sun.misc.URLClassPath$JarLoader.getClassPath *
+
+# permission collections
+java.io.FilePermission.newPermissionCollection ()Ljava/security/PermissionCollection;
+java.security.BasicPermission.newPermissionCollection ()Ljava/security/PermissionCollection;
+
+# native
+java.io.UnixFileSystem
+java.io.UnixFileSystem.<init> ()V
+java.io.UnixFileSystem.canonicalize *
+java.io.Win32FileSystem
+java.io.Win32FileSystem.<init> ()V
+java.io.Win32FileSystem.canonicalize *
+java.io.WinNTFileSystem
+java.io.WinNTFileSystem.<init> ()V
+java.io.WinNTFileSystem.canonicalize *
+
+# missing
+java.util.HashMap.<init> ()V
+java.util.HashMap$EntrySet.iterator *
+
+# Called from native GetStringPlatformChars (jni_util.c)
+java.lang.String.getBytes *
+
+# charset
+sun.nio.cs.US_ASCII.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_8.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_8.newDecoder  *
+sun.nio.cs.UTF_16.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_16.newDecoder  *
+sun.nio.cs.UTF_32.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_32.newDecoder  *
+
+# hashcode
+java.util.jar.Attributes$Name.hashCode *
+
+# nio
+sun.nio.ByteBuffered
+sun.nio.ch.DirectBuffer
+java.nio.DirectByteBuffer
+java.nio.MappedByteBuffer
+java.nio.DirectLongBufferU
+
+# resource files
+sun.launcher.resources.launcher
+
+sun.misc.Launcher$AppClassLoader.getPermissions *
+sun.misc.Launcher$AppClassLoader.loadClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$AppClassLoader.findClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$ExtClassLoader.getPermissions *
+sun.misc.Launcher$ExtClassLoader.loadClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$ExtClassLoader.findClass  (Ljava/lang/String;)Ljava/lang/Class;
+java.lang.ClassLoader.checkPackageAccess *
+java.lang.ClassLoader.findClass *
+java.lang.ClassLoader.defineClass *
+java.net.URLClassLoader.getPermissions *
+java.net.URLClassLoader.findClass *
+java.net.URLClassLoader.defineClass *
+java.security.SecureClassLoader.defineClass *
+# need to parse superclasses <init>
+java.security.SecureClassLoader.<init> ()V
+
+exclude sun.security.provider.PolicyFile.<init>
+exclude java.lang.ClassLoader.compareCerts
+exclude java.security.cert.Certificate.equals
+# unsigned jars - no verifier
+exclude java.util.jar.JarFile.initializeVerifier
+exclude java.util.jar.JarVerifier 
+exclude sun.security.util.SignatureFileVerifier.<init>
+
+
+# what about other charset
+exclude sun.misc.Service
+exclude java.util.ServiceLoader
+
+# exclude support for localized messages
+exclude java.util.ResourceBundle.getBundle
+exclude java.text.MessageFormat
+exclude sun.util.logging.PlatformLogger$LoggerProxy.format *
+
+# exclude nio and miscellaneous classes
+exclude java.nio.channels.**
+exclude sun.misc.FloatingDecimal
+exclude sun.misc.FormattedFloatingDecimal
+exclude sun.misc.FDBigInt 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/jdk7.depconfig	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,473 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+
+# private java.lang.Object createInetSocketAddress(java.lang.String, int)
+@ClassForName
+  com.sun.jndi.ldap.Connection -> java.net.InetSocketAddress
+  com.sun.jndi.ldap.Connection -> java.net.SocketAddress
+
+# com.sun.jndi.ldap.VersionHelper
+@ClassForName(optional)
+  com.sun.jndi.ldap.VersionHelper -> com.sun.jndi.ldap.VersionHelper*
+
+# private static void initMethodHandles()
+@ClassForName
+  com.sun.jndi.toolkit.corba.CorbaUtils -> javax.rmi.CORBA.Stub
+  com.sun.jndi.toolkit.corba.CorbaUtils -> javax.rmi.PortableRemoteObject
+
+# com.sun.naming.internal.ResourceManager$AppletParameter
+@ClassForName(optional)
+  com.sun.naming.internal.ResourceManager$AppletParameter -> java.applet.Applet
+
+# private static boolean loadProviderAsService()
+@Provider
+  com.sun.net.httpserver.spi.HttpServerProvider -> META-INF/services/com.sun.net.httpserver.spi.HttpServerProvider
+
+# com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT
+@ClassForName
+  com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT -> javax.xml.XMLConstants
+
+# public static java.beans.PersistenceDelegate getPersistenceDelegate(java.lang.Class)
+@ClassForName
+  java.beans.MetaData -> java.beans.*_PersistenceDelegate
+
+# private static java.lang.reflect.Method getNanosMethod()
+@ClassForName(optional)
+  java.beans.java_sql_Timestamp_PersistenceDelegate -> java.sql.Timestamp
+
+# java.beans.java_util_Collections$CheckedCollection_PersistenceDelegate
+@ClassForName
+  java.beans.java_util_Collections$CheckedCollection_PersistenceDelegate -> java.util.Collections$CheckedCollection
+
+# java.beans.java_util_Collections$CheckedMap_PersistenceDelegate
+@ClassForName
+  java.beans.java_util_Collections$CheckedMap_PersistenceDelegate -> java.util.Collections$CheckedMap
+
+# private static java.lang.Object getType(java.lang.Object)
+@ClassForName
+  java.beans.java_util_EnumMap_PersistenceDelegate -> java.util.EnumMap
+
+# private java.lang.Integer getAxis(java.lang.Object)
+@ClassForName
+  java.beans.javax_swing_Box_PersistenceDelegate -> javax.swing.BoxLayout
+
+# java.lang.Double
+@Inline
+  java.lang.Double -> sun.misc.FloatConsts
+  java.lang.Double -> sun.misc.DoubleConsts
+
+# java.lang.Float
+@Inline
+  java.lang.Float -> sun.misc.FloatConsts
+  java.lang.Float -> sun.misc.DoubleConsts
+
+# java.net.DefaultDatagramSocketImplFactory
+@ClassForName(optional)
+  java.net.DefaultDatagramSocketImplFactory -> java.net.*DatagramSocketImpl
+
+# private static sun.net.spi.nameservice.NameService createNSProvider(java.lang.String)
+@Provider
+  java.net.InetAddress -> META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+
+# static java.net.InetAddressImpl create()
+@ClassForName
+  java.net.InetAddressImplFactory -> java.net.*Inet[46]AddressImpl
+
+# private static void init()
+@NativeFindClass
+  java.net.PlainDatagramSocketImpl -> java.io.FileDescriptor
+
+# java.net.ProxySelector
+@ClassForName
+  java.net.ProxySelector -> sun.net.spi.DefaultProxySelector
+
+# static java.net.URLStreamHandler getURLStreamHandler(java.lang.String)
+@ClassForName(optional)
+  java.net.URL -> sun.net.www.protocol.*.Handler
+
+# private java.net.ContentHandler lookupContentHandlerClassFor(java.lang.String)
+@ClassForName
+  java.net.URLConnection -> sun.net.www.content.*
+
+# private static java.nio.channels.spi.AsynchronousChannelProvider loadProviderAsService()
+@Provider
+  java.nio.channels.spi.AsynchronousChannelProvider$ProviderHolder -> META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider
+
+# private static boolean loadProviderFromProperty()
+@ClassForName
+  java.nio.channels.spi.SelectorProvider -> sun.nio.ch.DefaultSelectorProvider
+
+# private static boolean loadProviderAsService()
+@Provider
+  java.nio.channels.spi.SelectorProvider -> META-INF/services/java.nio.channels.spi.SelectorProvider
+
+# private static java.util.Iterator providers()
+@Provider
+  java.nio.charset.Charset -> META-INF/services/java.nio.charset.spi.CharsetProvider
+
+# private static void probeExtendedProvider()
+@ClassForName(optional)
+  java.nio.charset.Charset -> sun.nio.cs.ext.ExtendedCharsets
+
+# public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>, java.lang.ClassLoader)
+@Provider
+  java.nio.file.FileSystems -> META-INF/services/java.nio.file.FileSystemProvider
+
+# private static java.util.List<java.nio.file.spi.FileTypeDetector> loadInstalledDetectors()
+@Provider
+  java.nio.file.Files$DefaultFileTypeDetectorHolder -> META-INF/services/java.nio.file.spi.FileTypeDetector
+
+# public static java.util.List<java.nio.file.spi.FileSystemProvider> installedProviders()
+@Provider
+  java.nio.file.spi.FileSystemProvider -> META-INF/services/java.nio.file.FileSystemProvider
+
+# private static java.rmi.server.RMIClassLoaderSpi initializeProvider()
+@Provider
+  java.rmi.server.RMIClassLoader -> META-INF/services/java.rmi.server.RMIClassLoaderSpi
+
+# private static void initializeSystemScope()
+@ClassForName(optional)
+  java.security.IdentityScope -> sun.security.provider.IdentityDatabase
+
+# static java.security.Policy getPolicyNoCheck()
+@ClassForName
+  java.security.Policy -> sun.security.provider.PolicyFile
+
+# private static java.lang.Class getSpiClass(java.lang.String)
+@ClassForName
+  java.security.Security -> java.security.*Spi
+
+# private static void invalidateSMCache(java.lang.String)
+@ClassForName
+  java.security.Security -> java.lang.SecurityManager
+
+# private static void loadInitialDrivers()
+@Provider
+  java.sql.DriverManager -> META-INF/services/java.sql.Driver
+
+# private static java.text.BreakIterator createBreakInstance(java.util.Locale, int, java.lang.String, java.lang.String)
+@Provider
+  java.text.BreakIterator -> META-INF/services/java.util.spi.BreakIteratorProvider
+
+# public static java.text.Collator getInstance(java.util.Locale)
+@Provider
+  java.text.Collator -> META-INF/services/java.util.spi.CollatorProvider
+
+# private static java.text.DateFormat get(int, int, int, java.util.Locale)
+@Provider
+  java.text.DateFormat -> META-INF/services/java.util.spi.DateNameProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.DateFormatSymbols -> META-INF/services/java.util.spi.DateFormatSymbolsProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.DecimalFormatSymbols -> META-INF/services/java.util.spi.DecimalFormatSymbolsProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.NumberFormat -> META-INF/services/java.util.spi.NumberFormatProvider
+
+# public java.lang.String getDisplayName(java.util.Locale)
+@Provider
+  java.util.Currency -> META-INF/services/java.util.spi.CurrencyNameProvider
+
+# java.util.Formatter
+@Inline
+  java.util.Formatter -> sun.misc.DoubleConsts
+
+# java.util.Locale
+@Inline
+  java.util.Locale -> java.util.LocaleISOData
+
+# private java.lang.String getDisplayString(java.lang.String, java.util.Locale, int)
+@Provider
+  java.util.Locale -> META-INF/services/java.util.spi.LocaleNameProvider
+
+# private static java.util.prefs.PreferencesFactory factory1()
+@ClassForName
+  java.util.prefs.Preferences -> java.util.prefs.WindowsPreferencesFactory
+  java.util.prefs.Preferences -> java.util.prefs.FileSystemPreferencesFactory
+
+# private static java.util.prefs.PreferencesFactory factory1()
+@Provider
+  java.util.prefs.Preferences -> META-INF/services/java.util.prefs.PreferencesFactory
+
+# public void registerApplicationClasspathSpis()
+@Provider
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.IIOServiceProvider
+
+# private void registerInstalledProviders()
+@Provider
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageReaderSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageWriterSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageReaderWriterSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageTranscoderSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageInputStreamSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageOutputStreamSpi
+
+# public javax.naming.ldap.ExtendedResponse createExtendedResponse(java.lang.String, byte[], int, int)
+@Provider
+  javax.naming.ldap.StartTlsRequest -> META-INF/services/javax.naming.ldap.StartTlsResponse
+
+# private static java.util.ArrayList getAllLookupServices()
+@Provider
+  javax.print.PrintServiceLookup -> META-INF/services/javax.print.PrintServiceLookup
+
+# private static java.util.ArrayList getAllFactories()
+@Provider
+  javax.print.StreamPrintServiceFactory -> META-INF/services/javax.print.StreamPrintServiceFactory
+
+# private void initEngines(java.lang.ClassLoader)
+@Provider
+  javax.script.ScriptEngineManager -> META-INF/services/javax.script.ScriptEngineFactory
+
+# private void initializeInputMethodLocatorList()
+@Provider
+  sun.awt.im.ExecutableInputMethodManager -> META-INF/services/java.awt.im.spi.InputMethodDescriptor
+
+# private static java.lang.Class getConverterClass(int, java.lang.String)
+@ClassForName(optional)
+  sun.io.Converters -> sun.io.*
+
+# public static sun.java2d.cmm.PCMM getModule()
+@Provider
+  sun.java2d.cmm.CMSManager -> META-INF/services/sun.java2d.cmm.PCMM
+
+# public static sun.java2d.pipe.RenderingEngine getInstance()
+@Provider
+  sun.java2d.pipe.RenderingEngine -> META-INF/services/sun.java2d.pipe.RenderingEngine
+
+# public static sun.java2d.pipe.RenderingEngine getInstance()
+@ClassForName(optional)
+  sun.java2d.pipe.RenderingEngine -> sun.dc.DuctusRenderingEngine
+
+# sun.misc.FloatingDecimal
+@Inline
+  sun.misc.FloatingDecimal -> sun.misc.FloatConsts
+  sun.misc.FloatingDecimal -> sun.misc.DoubleConsts
+
+# sun.misc.FormattedFloatingDecimal
+@Inline
+  sun.misc.FormattedFloatingDecimal -> sun.misc.FloatConsts
+  sun.misc.FormattedFloatingDecimal -> sun.misc.DoubleConsts
+
+# sun.misc.FpUtils
+@Inline
+  sun.misc.FpUtils -> sun.misc.FloatConsts
+  sun.misc.FpUtils -> sun.misc.DoubleConsts
+
+# public java.net.URLStreamHandler createURLStreamHandler(java.lang.String)
+@ClassForName(optional)
+  sun.misc.Launcher$Factory -> sun.net.www.protocol.*.Handler
+
+# private static sun.net.NetHooks$Provider loadProvider(java.lang.String)
+@ClassForName(optional)
+  sun.net.NetHooks -> sun.net.spi.SdpProvider
+
+# sun.net.idn.StringPrep
+@Inline
+  sun.net.idn.StringPrep -> sun.net.idn.UCharacterDirection
+
+# private static boolean init()
+@NativeFindClass
+  sun.net.spi.DefaultProxySelector -> java.net.Proxy
+  sun.net.spi.DefaultProxySelector -> java.net.Proxy$Type
+  sun.net.spi.DefaultProxySelector -> java.net.InetSocketAddress
+
+# private static java.nio.channels.Channel createChannel()
+@ClassForName
+  sun.nio.ch.InheritedChannel -> java.io.FileDescriptor
+
+# private static void initDBBConstructor()
+@ClassForName
+  sun.nio.ch.Util -> java.nio.DirectByteBuffer
+
+# private static void initDBBRConstructor()
+@ClassForName
+  sun.nio.ch.Util -> java.nio.DirectByteBufferR
+
+# private java.nio.charset.Charset lookup(java.lang.String)
+@ClassForName(optional)
+  sun.nio.cs.FastCharsetProvider -> sun.nio.cs.*
+
+# sun.nio.cs.ext.ExtendedCharsets
+@ClassForName(optional)
+  sun.nio.cs.ext.ExtendedCharsets -> sun.nio.cs.ext.*
+
+# sun.nio.cs.ext.ExtendedCharsets
+@ClassForName(optional)
+  sun.nio.cs.ext.ExtendedCharsets -> sun.nio.cs.ext.*
+
+# public static java.nio.file.spi.FileSystemProvider create()
+@ClassForName
+  sun.nio.fs.DefaultFileSystemProvider -> sun.nio.fs.SolarisFileSystemProvider
+  sun.nio.fs.DefaultFileSystemProvider -> sun.nio.fs.LinuxFileSystemProvider
+
+# sun.rmi.server.MarshalInputStream
+@ClassForName
+  sun.rmi.server.MarshalInputStream -> sun.rmi.server.Activation$ActivationSystemImpl_Stub
+  sun.rmi.server.MarshalInputStream -> sun.rmi.registry.RegistryImpl_Stub
+
+# private java.security.Provider doLoadProvider()
+@ClassForName(optional)
+  sun.security.jca.ProviderConfig -> sun.security.pkcs11.SunPKCS11
+  sun.security.jca.ProviderConfig -> sun.security.provider.Sun
+  sun.security.jca.ProviderConfig -> sun.security.rsa.SunRsaSign
+  sun.security.jca.ProviderConfig -> sun.security.ec.SunEC
+  sun.security.jca.ProviderConfig -> com.sun.net.ssl.internal.ssl.Provider
+  sun.security.jca.ProviderConfig -> com.sun.crypto.provider.SunJCE
+  sun.security.jca.ProviderConfig -> sun.security.jgss.SunProvider
+  sun.security.jca.ProviderConfig -> com.sun.security.sasl.Provider
+  sun.security.jca.ProviderConfig -> org.jcp.xml.dsig.internal.dom.XMLDSigRI
+  sun.security.jca.ProviderConfig -> sun.security.smartcardio.SunPCSC
+  sun.security.jca.ProviderConfig -> sun.security.mscapi.SunMSCAPI
+
+# public static java.security.Provider getSunProvider()
+@ClassForName
+  sun.security.jca.Providers -> sun.security.provider.Sun
+  sun.security.jca.Providers -> sun.security.provider.VerificationProvider
+
+# private static sun.security.jgss.spi.MechanismFactory getMechFactoryImpl(java.security.Provider, java.lang.String, org.ietf.jgss.Oid, sun.security.jgss.GSSCaller)
+@ClassForName
+  sun.security.jgss.ProviderList -> sun.security.jgss.spi.MechanismFactory
+
+# sun.security.jgss.wrapper.SunNativeProvider
+@NativeFindClass
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.Oid
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.GSSException
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSNameElement
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSCredElement
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.NativeGSSContext
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.SunNativeProvider
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.MessageProp
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.ChannelBinding
+  sun.security.jgss.wrapper.SunNativeProvider -> java.net.InetAddress
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSLibStub
+
+# static void ensureLoaded()
+@NativeFindClass
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.Krb5
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.Ticket
+  sun.security.krb5.Credentials -> sun.security.krb5.PrincipalName
+  sun.security.krb5.Credentials -> sun.security.util.DerValue
+  sun.security.krb5.Credentials -> sun.security.krb5.EncryptionKey
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.TicketFlags
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.KerberosTime
+
+# public static java.lang.String getDefaultCacheName()
+@ClassForName(optional)
+  sun.security.krb5.internal.ccache.FileCredentialsCache -> com.sun.security.auth.module.UnixSystem
+
+# sun.security.pkcs.PKCS9Attribute
+@ClassForName
+  sun.security.pkcs.PKCS9Attribute -> sun.security.util.ObjectIdentifier
+  sun.security.pkcs.PKCS9Attribute -> java.util.Date
+  sun.security.pkcs.PKCS9Attribute -> sun.security.pkcs.SignerInfo
+  sun.security.pkcs.PKCS9Attribute -> sun.security.x509.CertificateExtensions
+
+# protected T engineGetKeySpec(java.security.Key, java.lang.Class<T>)
+@ClassForName
+  sun.security.provider.DSAKeyFactory -> java.security.spec.DSAPublicKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.X509EncodedKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.DSAPrivateKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.PKCS8EncodedKeySpec
+
+# protected T engineGetParameterSpec(java.lang.Class<T>)
+@ClassForName
+  sun.security.provider.DSAParameters -> java.security.spec.DSAParameterSpec
+
+# sun.security.provider.VerificationProvider
+@ClassForName(optional)
+  sun.security.provider.VerificationProvider -> sun.security.provider.Sun
+  sun.security.provider.VerificationProvider -> sun.security.rsa.SunRsaSign
+
+# sun.security.provider.certpath.URICertStore$LDAP
+@ClassForName(optional)
+  sun.security.provider.certpath.URICertStore$LDAP -> sun.security.provider.certpath.ldap.LDAPCertStoreHelper
+
+# sun.security.smartcardio.PCSC
+@NativeFindClass
+  sun.security.smartcardio.PCSC -> sun.security.smartcardio.PCSCException
+
+# sun.security.ssl.HandshakeMessage
+@ClassForName
+  sun.security.ssl.HandshakeMessage -> java.security.MessageDigest$Delegate
+
+# sun.security.ssl.JsseJce
+@ClassForName(optional)
+  sun.security.ssl.JsseJce -> sun.security.krb5.PrincipalName
+
+# sun.security.x509.OIDMap$OIDInfo
+@ClassForName
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectKeyIdentifierExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.KeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PrivateKeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectAlternativeNameExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.IssuerAlternativeNameExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.BasicConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLNumberExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLReasonCodeExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.NameConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PolicyMappingsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.AuthorityKeyIdentifierExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PolicyConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.NetscapeCertTypeExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CertificatePoliciesExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.ExtendedKeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.InhibitAnyPolicyExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLDistributionPointsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CertificateIssuerExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectInfoAccessExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.AuthorityInfoAccessExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.IssuingDistributionPointExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.DeltaCRLIndicatorExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.FreshestCRLExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.OCSPNoCheckExtension
+
+# sun.util.LocaleServiceProviderPool$AllAvailableLocales
+@Provider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.BreakIteratorProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.CollatorProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DateFormatProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DateFormatSymbolsProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DecimalFormatSymbolsProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.NumberFormatProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.CurrencyNameProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.LocaleNameProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.TimeZoneNameProvider
+
+# private static final java.lang.String[] retrieveDisplayNames(sun.util.resources.OpenListResourceBundle, java.lang.String, java.util.Locale)
+@Provider
+  sun.util.TimeZoneNameUtility -> META-INF/services/java.util.spi.TimeZoneNamePProvider
+
+# public static sun.util.calendar.CalendarSystem forName(java.lang.String)
+@ClassForName
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.Gregorian
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.LocalGregorianCalendar
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.JulianCalendar
+
+# sun.util.logging.LoggingSupport
+@ClassForName(optional)
+  sun.util.logging.LoggingSupport -> java.util.logging.LoggingProxyImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/modules.config	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,858 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+// These classes are not referenced in the JDK but we can't
+// remove them for compatibility reason.  Define this module
+// first so that other modules don't need to exclude these clases
+module private-legacy {
+    include sun.misc.Cache*,
+            sun.misc.ClassLoaderUtil,
+            sun.misc.Compare,
+            sun.misc.ConditionLock,
+            sun.misc.CRC16,
+            sun.misc.Lock,
+            sun.misc.Regexp,
+            sun.misc.RequestProcessor,
+            sun.misc.Sort,
+            sun.misc.Request,
+            sun.misc.Timeable,
+            sun.misc.Timer,
+            sun.misc.TimerThread,
+            sun.misc.TimerTickThread,
+            sun.misc.UCDecoder,
+            sun.misc.UCEncoder,
+            sun.misc.UUDecoder,
+            sun.misc.UUEncoder,
+            com.sun.net.ssl.SSLContext,
+            sun.net.NetworkServer,
+            sun.net.URLCanonicalizer,
+            sun.reflect.misc.ConstructorUtil,
+            sun.reflect.FieldInfo,
+            sun.reflect.SignatureIterator,
+            sun.reflect.generics.reflectiveObjects.NotImplementedException,
+            sunw.io.Serializable,
+            sunw.util.EventListener,
+            sunw.util.EventObject;
+}
+
+// Deprecated classes that aren't referenced/used go here.
+module deprecated {
+    // add deprecated security classes once b78 is promoted
+}
+
+/**************************************************************************/
+
+module base {
+    // core classes
+    include java.lang.*,
+            java.lang.annotation.*,
+            java.lang.ref.*,
+            java.lang.reflect.*,
+            java.math.*,
+            java.net.*,
+            java.util.*,
+            java.util.concurrent.**,
+            java.util.jar.*,
+            java.util.regex.*,
+            java.util.spi.*,
+            java.util.zip.*,
+            java.text.**;
+
+    exclude java.util.jar.Pack200*,
+            java.util.XMLUtils,
+            java.text.Bidi;
+
+    include java.io.*, java.nio.*, java.nio.charset.**;
+    exclude java.io.TempFileHelper, java.nio.BufferPoolMXBean;
+
+    // security APIs
+    // javax.crypto and javax.security.auth are included to avoid inconsistent
+    // spliting of JCA and JAAS. This adds about 85k. Also note that some deprecated
+    // classes must be included for now (see 6876158, 6876170)
+    include java.security.*,
+            java.security.cert.*,
+            java.security.interfaces.*,
+            java.security.spec.*,
+            javax.security.auth.**,
+            javax.crypto.**;
+
+    // Sun and RSA security providers (except LDAP CertStore)
+    // roots sun.security.provider.* sun.security.provider.certpath.* sun.security.rsa.*
+    include com.sun.security.auth.PrincipalComparator,
+            com.sun.security.auth.SubjectCodeSource,
+            com.sun.security.auth.login.**,
+            com.sun.security.auth.Policy*,
+            sun.security.action.*,
+            sun.security.ec.*,
+            sun.security.jca.*,
+            sun.security.pkcs.*,
+            sun.security.provider.*,
+            sun.security.provider.certpath.*,
+            sun.security.rsa.*,
+            sun.security.util.*,
+            sun.security.validator.*,
+            sun.security.x509.*,
+            sun.security.timestamp.*;
+
+    // this list is based on the classlist generated from the rootset
+    // need investigation
+    exclude sun.security.ec.ECD*,
+            sun.security.ec.ECKeyPairGenerator,
+            sun.security.ec.SunEC*,
+            sun.security.pkcs.PKCS10*,
+            sun.security.pkcs.EncodingException,
+            sun.security.util.AuthResources_*,
+            sun.security.util.Resources_*,
+            sun.security.util.BigInt,
+            sun.security.util.HostnameChecker,
+            sun.security.x509.CertAndKeyGen,
+            sun.security.util.PathList;
+
+    // Kerberos not needed
+    exclude javax.security.auth.kerberos.**,
+            sun.security.jgss.**,
+            sun.security.krb5.**,
+            sun.security.ssl.Kerberos*,
+            org.ietf.jgss.**;
+
+   // property events and annotations
+   include java.beans.ChangeListenerMap,
+           java.beans.IndexedPropertyChangeEvent,
+           java.beans.PropertyChange*,
+           java.beans.PropertyVetoException,
+           java.beans.VetoableChange*,
+           java.beans.ConstructorProperties;
+
+    // mandatory charsets
+    include sun.nio.cs.*;
+
+    exclude sun.nio.cs.AbstractCharsetProvider,
+            sun.nio.cs.CharsetMapping,
+            sun.nio.cs.IBM*,
+            sun.nio.cs.ISO*,
+            sun.nio.cs.KOI8_*,
+            sun.nio.cs.MS125*,
+            sun.nio.cs.UTF_32*,
+            sun.nio.cs.SingleByteDecoder,
+            sun.nio.cs.SingleByteEncoder;
+
+    allow   sun.nio.cs.ISO_8859_1,
+            sun.nio.cs.ISO_8859_15,
+            sun.nio.cs.MS1252;
+
+    include sun.text.*,
+            sun.text.normalizer.*;
+
+    // resource files
+    include sun/text/resources/*.icu;
+
+    exclude sun.text.bidi.*,
+            sun.text.CharArrayCodePointIterator,
+            sun.text.CharSequenceCodePointIterator,
+            sun.text.CharacterIteratorCodePointIterator,
+            sun.text.CodePointIterator;
+
+    include sun.util.*,
+            sun.util.calendar.*,
+            sun.util.logging.*,
+            sun.util.resources.LocaleData,
+            sun.util.resources.LocaleNamesBundle,
+            sun.util.resources.OpenListResourceBundle;
+
+    // US_en locale
+    include sun.text.resources.BreakIteratorInfo,
+            sun.text.resources.FormatData,
+            sun.text.resources.FormatData_en_US,
+            sun.util.resources.CalendarData,
+            sun.util.resources.CalendarData_en,
+            sun.util.resources.TimeZoneNames,
+            sun.util.resources.TimeZoneNames_en,
+            sun.util.resources.TimeZoneNamesBundle,
+            sun.util.resources.LocaleNames,
+            sun.util.resources.LocaleNames_en,
+            sun.util.resources.LocalenamesBundles,
+            sun.util.resources.CurrencyNames,
+            sun.util.resources.CurrencyNames_en_US,
+            sun.util.EmptyListResourceBundle;
+
+    // resources file needed by
+    // - sun.misc.ExtensionInfo
+    // - sun.security.provider.PolicyFile
+    // - com.sun.security.auth.PolicyFile
+    include sun.misc.resources.Messages,
+            sun.security.util.Resources,
+            sun.security.util.AuthResources;
+
+    // java.nio.channels and java.nio.file not in base
+    include sun.nio.ch.Interruptible,
+            sun.nio.ch.DirectBuffer,
+            sun.nio.ByteBuffered;
+
+    include sun.reflect.**;
+
+    // protocol handlers
+    include sun.net.www.protocol.file.*,
+            sun.net.www.protocol.jar.*,
+            sun.net.www.protocol.http.*;
+
+    include sun.net.*,
+            sun.net.spi.*,
+            sun.net.idn.*,
+            sun.net.util.*,
+            sun.net.www.*,
+            sun.net.www.http.*,
+            sun.net.spi.nameservice.*;
+
+    // resource file for sun.net.idn
+    include sun/net/idn/*;
+
+    // classes in net-compat
+    exclude sun.net.Telnet*, sun.net.TransferProtocolClient;
+
+    // classes in deploy
+    exclude sun.net.www.protocol.http.AuthCacheBridge;
+
+    // classes in security-jsse
+    exclude java.net.SecureCacheResponse;
+
+    // launcher
+    include sun.launcher.LauncherHelper, sun.launcher.resources.launcher;
+
+    include sun.misc.*;
+    exclude sun.misc.FIFOQueueEnumerator,
+            sun.misc.LIFOQueueEnumerator,
+            sun.misc.GC,
+            sun.misc.PerformanceLogger,
+            sun.misc.Queue,
+            sun.misc.QueueElement,
+            sun.misc.Ref,
+            sun.misc.VMSupport;
+
+    // On Windows, OSEnvironment dependency
+    include sun.io.Win32ErrorMode;
+}
+
+/**************************************************************************/
+
+module charsets {
+    include sun.nio.cs.ext.**;
+
+    include sun.nio.cs.AbstractCharsetProvider,
+            sun.nio.cs.CharsetMapping,
+            sun.nio.cs.IBM*,
+            sun.nio.cs.ISO*,
+            sun.nio.cs.KOI8_*,
+            sun.nio.cs.MS125*,
+            sun.nio.cs.SingleByte*,
+            sun.nio.cs.UTF_32*;
+
+    exclude sun.nio.cs.ISO_8859_1,
+            sun.nio.cs.MS1252;
+
+    // legacy sun.io converters
+    include sun.io.*;
+}
+
+/**************************************************************************/
+
+// For now, retains the current JRE extensions where localedata.jar in jre/lib/ext 
+module localedata {
+    include sun.util.resources.*_ar,
+            sun.util.resources.*_ar_*,
+            sun.util.resources.*_hi,
+            sun.util.resources.*_hi_*,
+            sun.util.resources.*_iw,
+            sun.util.resources.*_iw_*,
+            sun.util.resources.*_ja,
+            sun.util.resources.*_ja_*,
+            sun.util.resources.*_ko,
+            sun.util.resources.*_ko_*,
+            sun.util.resources.*_th,
+            sun.util.resources.*_th_*,
+            sun.util.resources.*_vi,
+            sun.util.resources.*_vi_*,
+            sun.util.resources.*_zh,
+            sun.util.resources.*_zh_*;
+    include sun.text.resources.*_ar,
+            sun.text.resources.*_ar_*,
+            sun.text.resources.*_hi,
+            sun.text.resources.*_hi_*,
+            sun.text.resources.*_iw,
+            sun.text.resources.*_iw_*,
+            sun.text.resources.*_ja,
+            sun.text.resources.*_ja_*,
+            sun.text.resources.*_ko,
+            sun.text.resources.*_ko_*,
+            sun.text.resources.*_th,
+            sun.text.resources.*_th_*,
+            sun.text.resources.*_vi,
+            sun.text.resources.*_vi_*,
+            sun.text.resources.*_zh,
+            sun.text.resources.*_zh_*;
+}
+
+module resources {
+    include sun.text.resources.*, sun.util.resources.*, sun.misc.resources.*;
+}
+
+/**************************************************************************/
+
+module nio {
+    include java.nio.channels.**, java.nio.file.**, com.sun.nio.file.**;
+
+    // this is excluded from base
+    include java.io.TempFileHelper;
+
+    // provider implementations and their dependencies
+    include sun.nio.ch.*, sun.nio.fs.**;
+    exclude sun.nio.ch.Sctp*;
+}
+
+/**************************************************************************/
+
+module pack200 {
+    include java.util.jar.Pack200*, com.sun.java.util.jar.pack.**;
+}
+
+/**************************************************************************/
+
+module logging {
+    include java.util.logging.*, sun.util.logging.**;
+    exclude java.util.logging.PlatformLoggingMXBean;
+
+    // Formatter for HTTP messages
+    include sun.net.www.protocol.http.logging.*;
+}
+
+/**************************************************************************/
+
+module management-snmp {
+    include com.sun.jmx.snmp.**, sun.management.snmp.**;
+}
+
+module management-iiop {
+    include com.sun.jmx.remote.protocol.iiop.*;
+
+    // stubs and ties
+    include javax.management.remote.rmi._*,
+            org.omg.stub.javax.management.remote.rmi.**;
+}
+
+module management {
+    include java.lang.management.*, com.sun.management.**, sun.management.**;
+    include javax.management.**, com.sun.jmx.**;
+
+    // other management interfaces
+    include java.nio.BufferPoolMXBean;
+    include java.util.logging.PlatformLoggingMXBean;
+
+    // supporting classes in sun.misc
+    include sun.misc.VMSupport;
+}
+
+/**************************************************************************/
+
+module instrument {
+    // java.lang.instrument
+    include java.lang.instrument.*, sun.instrument.*;
+
+    // tracing
+    include com.sun.tracing.**, sun.tracing.**;
+
+    // HPROF support
+    include com.sun.demo.jvmti.hprof.*;
+}
+
+/**************************************************************************/
+
+module rmi-activation {
+    include java.rmi.activation.**,
+            sun.rmi.server.Act*,
+            sun.rmi.server.InactiveGroupException;
+}
+
+module rmi {
+    include java.rmi.**, sun.rmi.**, com.sun.rmi.**;
+
+    // SSL factories are in rmi
+    include javax.rmi.ssl.**;
+
+    // rmic is in tools
+    exclude sun.rmi.rmic.**;
+
+    // supporting classes in sun.misc and dependencies
+    include sun.misc.GC;
+}
+
+/**************************************************************************/
+
+module prefs {
+    include java.util.prefs.*;
+}
+
+/**************************************************************************/
+
+module security-jsse {
+    include javax.net.**,
+            javax.security.cert.*,
+            java.net.SecureCacheResponse,
+            com.sun.net.ssl.**,
+            com.sun.security.cert.internal.x509.*,
+            sun.security.ssl.*,
+            sun.net.www.protocol.https.**,
+            sun.security.internal.interfaces.Tls*,
+            sun.security.internal.spec.Tls*,
+            sun.security.util.HostnameChecker;
+}
+
+module security-sunpkcs11 {
+    include sun.security.pkcs11.**;
+}
+
+module security-sunjce {
+    include com.sun.crypto.provider.*;
+}
+
+module security-sunec {
+    include sun.security.ec.*;
+}
+
+module security-sunmscapi {
+    include sun.security.mscapi.*;
+}
+
+module security-kerberos {
+    include javax.security.auth.kerberos.*,
+            com.sun.security.jgss.**,
+            com.sun.security.auth.module.Krb5LoginModule,
+            com.sun.security.sasl.gsskerb.**,             // GSSAPI SASL mechanism
+            sun.security.jgss.**,
+            sun.security.ssl.krb5.**,
+            sun.security.krb5.**,
+            org.ietf.jgss.**,
+            sun.net.www.protocol.http.spnego.*;
+}
+
+module security-sasl {
+    include javax.security.sasl.**,
+            com.sun.security.sasl.**;
+}
+
+module security-xmldsig {
+    include javax.xml.crypto.**,
+            org.jcp.xml.dsig.**,
+            com.sun.org.apache.xml.internal.security.**;
+}
+
+module security-smartcardio {
+    include javax.smartcardio.**, sun.security.smartcardio.**;
+}
+
+module security-misc {
+    include com.sun.security.auth.**, sun.security.util.AuthResources_*,
+            sun.security.pkcs.*,
+            sun.security.pkcs12.*;
+
+    // this class is a candidate to be removed.
+    include sun.security.util.BigInt;
+}
+
+module security-resources {
+    include sun.security.util.Resources_*;
+}
+
+module security-compat {
+    include java.security.acl.*, sun.security.acl.*;
+}
+
+/**************************************************************************/
+
+module jndi-ldap {
+    include javax.naming.ldap.**,
+            com.sun.jndi.ldap.**,
+            com.sun.jndi.url.ldap.*,
+            com.sun.jndi.url.ldaps.*,
+            sun.security.provider.certpath.ldap.**;
+}
+
+module jndi-rmiregistry {
+    include com.sun.jndi.rmi.**, com.sun.jndi.url.rmi.**;
+}
+
+module jndi-dns {
+    include com.sun.jndi.dns.**, com.sun.jndi.url.dns.**;
+    include sun.net.dns.**;                 // to access DNS config.
+    include sun.net.spi.nameservice.dns.**; // for DNS-only name service.
+}
+
+module jndi-cosnaming {
+    include com.sun.jndi.cosnaming.**,
+            com.sun.jndi.toolkit.corba.**,
+            com.sun.jndi.url.corbaname.**,
+            com.sun.jndi.url.iiop.**,
+            com.sun.jndi.url.iiopname.**;
+}
+
+// framework/API and classes used by providers
+module jndi {
+    include javax.naming.**,
+            com.sun.naming.**,
+            com.sun.jndi.toolkit.ctx.**,
+            com.sun.jndi.toolkit.dir.**,
+            com.sun.jndi.toolkit.url.**;
+}
+
+/**************************************************************************/
+
+module jdbc-base {
+    include java.sql.**, javax.sql.*;
+    exclude javax.sql.XA*;
+}
+
+module jdbc-enterprise {
+    include javax.sql.**, com.sun.rowset.**;
+}
+
+module jdbc-odbc {
+    include sun.jdbc.odbc.**;
+}
+
+/**************************************************************************/
+
+module scripting {
+    include javax.script.**;
+
+    // supporting classes for scripting engines
+    include com.sun.script.util.**;
+}
+
+module scripting-rhino {
+    include com.sun.script.javascript.**, sun.org.mozilla.javascript.**;
+}
+
+/**************************************************************************/
+
+module httpserver {
+    include com.sun.net.httpserver.**, sun.net.httpserver.**;
+}
+
+/**************************************************************************/
+
+module sctp {
+    // API and dependencies
+    include com.sun.nio.sctp.**, sun.nio.ch.Sctp*;
+}
+
+/**************************************************************************/
+
+module langtools {
+    include javax.tools.**, javax.lang.model.**, javax.annotation.processing.**;
+
+    // include mirror API for now
+    include com.sun.mirror.**;
+
+    // include the JSR292 APIs for now
+    include java.dyn.**, sun.dyn.**;
+}
+
+/**************************************************************************/
+
+module beans {
+    include java.beans.**, com.sun.beans.**, sun.beans.**;
+}
+
+/**************************************************************************/
+
+module jaxp-parsers-api {
+    include javax.xml.*, javax.xml.parsers.**,
+            org.w3c.dom.**, org.w3c.sax.**, org.xml.sax.**;
+}
+
+module jaxp-api {
+    include javax.xml.**;
+    exclude javax.xml.crypto.**,   // XML-DSIG
+            javax.xml.bind.**,     // JAX-WS
+            javax.xml.soap.**,
+            javax.xml.ws.**;
+}
+
+module jaxp-xerces-impl {
+    include com.sun.org.apache.xerces.internal.**;
+
+    // include in xerces-impl due to circular dependencies
+    include com.sun.org.apache.xml.internal.serialize.**,
+            com.sun.xml.internal.stream.**;
+    exclude com.sun.xml.internal.stream.buffer.**;  // JAX-WS
+}
+
+// required by Xerces and JAX-WS
+module jaxp-xerces-resolver {
+    include com.sun.org.apache.xml.internal.resolver.**;
+}
+
+module jaxp-xalan {
+    include com.sun.org.apache.xalan.internal.**,
+            com.sun.org.apache.xpath.internal.**,
+            com.sun.org.apache.xml.internal.dtm.**,
+            com.sun.org.apache.xml.internal.res.**,
+            com.sun.org.apache.xml.internal.serializer.**,
+            com.sun.org.apache.xml.internal.utils.**,
+            com.sun.org.apache.bcel.internal.**,
+            com.sun.org.apache.regexp.internal.**,
+            com.sun.java_cup.internal.**;
+}
+
+/**************************************************************************/
+
+module jaxws-tools {
+    include com.sun.codemodel.**,
+            com.sun.xml.internal.dtdparser.**,
+            com.sun.xml.internal.rngom.**,
+            com.sun.xml.internal.xsom.**,
+            com.sun.istack.internal.tools.**,
+            com.sun.istack.internal.ws.**,
+            com.sun.tools.internal.xjc.**,
+            com.sun.tools.internal.ws.**,
+            com.sun.tools.internal.jxc.**,
+            org.relaxng.datatype.**;
+}
+
+module jaxws {
+    include javax.jws.**,
+            javax.xml.bind.**,
+            javax.xml.soap.**,
+            javax.xml.ws.**,
+            org.relaxng.**,
+            com.sun.istack.internal.*,
+            com.sun.istack.internal.localization.*,
+            com.sun.xml.internal.**;
+
+    // include JAF in this module
+    include javax.activation.**, com.sun.activation.**;
+
+    include META-INF/mailcap.default,
+            META-INF/mimetypes.default;
+}
+
+/**************************************************************************/
+module enterprise-base {
+    include javax.transaction.**,  // JTA
+            javax.annotation.*;    // Common annotations (JSR-250)
+}
+
+/**************************************************************************/
+module corba {
+    include javax.activity.**,
+            javax.rmi.*,
+            javax.rmi.CORBA.*,
+            javax.transaction.**,
+            com.sun.corba.**,
+            com.sun.org.omg.**,
+            org.omg.**,
+            sun.corba.**;
+
+    // JMX remote API
+    exclude org.omg.stub.javax.management.**;
+}
+
+/**************************************************************************/
+
+module client {
+    include java.applet.**,
+            java.awt.**,
+            javax.accessibility.*,
+            javax.imageio.**,
+            javax.print.**,
+            javax.sound.**,
+            javax.swing.**,
+            sun.applet.**,
+            sun.audio.**,
+            sun.awt.**,
+            sun.dc.**,
+            sun.font.**,
+            sun.java2d.**,
+            sun.print.**,
+            sun.swing.**,
+            com.sun.accessibility.**,
+            com.sun.awt.**,
+            com.sun.image.**,
+            com.sun.imageio.**,
+            com.sun.java.swing.*,       // sajdi also contains classes in a subpackage;
+                                        // so use '*' instead of '**' 
+            com.sun.java.swing.plaf.**,
+            com.sun.media.**,
+            com.sun.swing.**;
+
+    // Bidi class in client module for now
+    include java.text.Bidi, sun.text.bidi.*;
+
+    // PerformanceLogger and dependencies
+    include sun.misc.Ref, sun.misc.PerformanceLogger;
+
+    // misc. dependencies that we need to examine
+    include sun.text.CodePointIterator,
+            sun.text.Char*,
+            sun.misc.Queue*,
+            sun.misc.FIFOQueueEnumerator,
+            sun.misc.LIFOQueueEnumerator;
+
+    // content handlers
+    include sun.net.www.content.audio.**,
+            sun.net.www.content.image.**;
+}
+
+/**************************************************************************/
+
+module deploy {
+    // For now, all plugin and JNLP
+    include com.sun.java.browser.**,
+            netscape.**,
+            sun.plugin.**,
+            sun.plugin2.**,,
+            com.sun.deploy.**,
+            com.sun.javaws.**,
+            javax.jnlp.*,
+            com.sun.jnlp.*,
+            sun.jkernel.*;
+
+    // Hook for http authentication
+    include sun.net.www.protocol.http.AuthCacheBridge;
+}
+
+/**************************************************************************/
+
+module net-compat {
+    // NTLM authentication support
+    include sun.net.www.protocol.http.ntlm.*;
+
+    // ftp and mail clients
+    include sun.net.ftp.**, sun.net.smtp.**;
+
+    // Legacy protocol handlers
+    include sun.net.www.protocol.**;
+
+    // Legacy content handlers
+    include sun.net.www.content.**;
+
+    include sun.net.Telnet*,
+            sun.net.TransferProtocolClient;
+}
+
+/**************************************************************************/
+
+// jar-tool and security-tools are JRE tools
+module jar-tool {
+    include sun.tools.jar.**;
+}
+
+module security-tools {
+    include sun.security.tools.**;
+
+    // Used by security tools
+    include sun.security.util.PathList, sun.security.x509.CertAndKeyGen;
+
+    exclude sun.security.tools.JarBASE64Encoder,
+            sun.security.tools.JarSigner,
+            sun.security.tools.JarSignerParameters,
+            sun.security.tools.JarSignerResources*,
+            sun.security.tools.SignatureFile,
+            sun.security.tools.TimestampedSigner;
+}
+
+module jconsole {
+    include sun.tools.jconsole.**,
+            com.sun.tools.jconsole.*;
+}
+
+module serialver {
+    include sun.tools.serialver.**;
+}
+
+module gui-tools {
+    include jconsole,
+            serialver;
+
+    include com.sun.tools.example.debug.bdi.**,
+            com.sun.tools.example.debug.gui.**,
+            com.sun.tools.internal.xjc.**;
+}
+
+module attach {
+    include com.sun.tools.attach.**,
+            sun.tools.attach.**;
+}
+
+module debugging {
+    include com.sun.jdi.**, com.sun.tools.jdi.**;
+}
+
+module jdb {
+    include com.sun.tools.example.debug.**;
+}
+
+module sajdi {
+    include sun.jvm.hotspot.**,
+            com.sun.java.swing.ui.**,
+            com.sun.java.swing.action.**;
+
+    include toolbarButtonGraphics/**;
+    include sa.properties;
+}
+
+module tools {
+    include attach,
+            debugging,
+            jaxws-tools,
+            jdb,
+            sajdi;
+
+    // include gui-tools in tools module unless the tool binaries
+    // are modified to load the new gui-tools.jar
+    include gui-tools;
+
+    include com.sun.tools.**, sun.tools.**, sun.security.tools.**,
+            com.sun.jarsigner.**,
+            com.sun.javac.**,
+            com.sun.javadoc.**, com.sun.source.**,
+            sun.jvmstat.**,
+            sun.rmi.rmic.**;
+}
+
+/**************************************************************************/
+
+module servicetag {
+    include com.sun.servicetag.**;
+}
+
+/**************************************************************************/
+
+// these classes will be removed from JRE - see 6909002
+module inputmethods-ext {
+    include com.sun.inputmethods.internal.**;
+}
+
+/**************************************************************************/
+
+module other {
+    include **;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/modules.group	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * Example:
+ *    module jdbc {
+ *        include jdbc-base, jdbc-enterprise, jdbc-odbc;
+ *    }
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/optional.depconfig	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,124 @@
+# public final java.nio.channels.SocketChannel getChannel()
+@Optional
+  sun.security.ssl.BaseSSLSocketImpl -> java.nio.channels.SocketChannel
+
+# public XMLDecoder(java.io.InputStream)
+# public XMLDecoder(java.io.InputStream, java.lang.Object)
+# public XMLDecoder(java.io.InputStream, java.lang.Object, java.beans.ExceptionListener)
+# public XMLDecoder(java.io.InputStream, java.lang.Object, java.beans.ExceptionListener, java.lang.ClassLoader)
+# public XMLDecoder(org.xml.sax.InputSource)
+@Optional
+  java.beans.XMLDecoder -> com.sun.beans.decoder.DocumentHandler
+  java.beans.XMLDecoder -> org.xml.sax.InputSource
+
+# public static org.xml.sax.helpers.DefaultHandler createHandler(java.lang.Object, java.beans.ExceptionListener, java.lang.ClassLoader)
+@Optional
+  java.beans.XMLDecoder -> com.sun.beans.decoder.DocumentHandler
+  java.beans.XMLDecoder -> org.xml.sax.helpers.DefaultHandler
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.net.SocketInputStream -> java.nio.channels.FileChannel
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.net.SocketOutputStream -> java.nio.channels.FileChannel
+
+# public Scanner(java.io.File)
+# public Scanner(java.io.File, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.channels.ReadableByteChannel
+  java.util.Scanner -> java.nio.channels.Channels
+
+# public Scanner(java.nio.file.FileRef)
+# public Scanner(java.nio.file.FileRef, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.file.FileRef
+  java.util.Scanner -> java.nio.file.OpenOption
+
+# public Scanner(java.nio.channels.ReadableByteChannel)
+# public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.channels.ReadableByteChannel
+  java.util.Scanner -> java.nio.channels.Channels
+
+# private static void loadSnmpAgent(java.lang.String, java.util.Properties)
+@Optional
+  sun.management.Agent -> sun.management.snmp.AdaptorBootstrap
+
+# public void connect()
+@Optional
+  sun.net.www.protocol.http.HttpURLConnection -> java.net.SecureCacheResponse
+
+# private static sun.security.util.PermissionFactory<?> permissionFactory()
+@Optional
+  sun.security.util.SecurityConstants$AWT -> sun.awt.AWTPermissionFactory
+
+# sun.util.logging.LoggingSupport
+@Optional
+  sun.util.logging.LoggingSupport -> java.util.logging.LoggingProxyImpl
+
+# public java.nio.channels.DatagramChannel getChannel()
+@Optional
+  java.net.DatagramSocket -> java.nio.channels.DatagramChannel
+
+# public java.nio.channels.SocketChannel getChannel()
+@Optional
+  java.net.Socket -> java.nio.channels.SocketChannel
+
+# public java.nio.channels.ServerSocketChannel getChannel()
+@Optional
+  java.net.ServerSocket -> java.nio.channels.ServerSocketChannel
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.RandomAccessFile -> java.nio.channels.FileChannel
+  java.io.RandomAccessFile -> sun.nio.ch.FileChannelImpl
+
+# public static sun.nio.cs.StreamDecoder forDecoder(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.ReadableByteChannel
+
+# private static java.nio.channels.FileChannel getChannel(java.io.FileInputStream)
+# StreamDecoder(java.io.InputStream, java.lang.Object, java.nio.charset.CharsetDecoder)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.FileChannel
+
+# StreamDecoder(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.ReadableByteChannel
+
+# public static java.io.File createTemporaryFile(java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>[])
+@Optional
+  java.io.File -> java.io.TempFileHelper
+  java.io.File -> java.nio.file.attribute.FileAttribute
+
+# public java.nio.file.Path toPath()
+@Optional
+  java.io.File -> java.nio.file.Paths
+  java.io.File -> java.nio.file.Path
+
+# public static sun.nio.cs.StreamEncoder forEncoder(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int)
+# private StreamEncoder(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int)
+@Optional
+  sun.nio.cs.StreamEncoder -> java.nio.channels.WritableByteChannel
+
+# public java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.FileOutputStream -> java.nio.channels.FileChannel
+  java.io.FileOutputStream -> sun.nio.ch.FileChannelImpl
+
+# public java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.FileInputStream -> java.nio.channels.FileChannel
+  java.io.FileInputStream -> sun.nio.ch.FileChannelImpl
+
+# public void loadFromXML(java.io.InputStream)
+# public void storeToXML(java.io.OutputStream, java.lang.String, java.lang.String)
+@Optional
+  java.util.Properties -> java.util.XMLUtils
+
+# public static java.nio.channels.Channel inheritedChannel()
+@Optional
+  java.lang.System -> java.nio.channels.Channel
+  java.lang.System -> java.nio.channels.spi.SelectorProvider
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/Makefile	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,85 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Makefile for building the classanalyzer tool
+#
+
+BUILDDIR = ../..
+PACKAGE = com.sun.classanalyzer
+PRODUCT = tools
+PROGRAM = classanalyzer
+include $(BUILDDIR)/common/Defs.gmk
+
+BUILDTOOL_SOURCE_ROOT = src
+BUILDTOOL_MAIN        = $(PKGDIR)/ClassAnalyzer.java
+BUILTTOOL_MAINCLASS   = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
+
+BUILDTOOL_MAIN_SOURCE_FILE = $(BUILDTOOL_SOURCE_ROOT)/$(BUILDTOOL_MAIN)
+BUILDTOOL_MANIFEST_FILE    = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
+BUILDTOOL_JAR_FILE         = $(BUILDTOOLJARDIR)/$(PROGRAM).jar
+
+FILES_java := $(shell $(CD) $(BUILDTOOL_SOURCE_ROOT) \
+    && $(FIND) $(PKGDIR) $(SCM_DIRS_prune) -o -type f -print)
+FILES_class = $(FILES_java:%.java=$(BUILDTOOLCLASSDIR)/%.class)
+
+all build: $(BUILDTOOL_JAR_FILE) tool_info
+
+$(BUILDTOOL_MANIFEST_FILE): $(BUILDTOOL_MAIN_SOURCE_FILE)
+	@$(prep-target)
+	$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
+
+$(BUILDTOOLCLASSDIR)/%.class : $(BUILDTOOL_SOURCE_ROOT)/%.java
+	@$(prep-target)
+	$(JAVAC_CMD) \
+            -sourcepath $(BUILDTOOL_SOURCE_ROOT) \
+            -d $(BUILDTOOLCLASSDIR) $<
+
+$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(FILES_class)
+	@$(prep-target)
+	$(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \
+	    -C $(BUILDTOOLCLASSDIR) $(PKGDIR) \
+	    $(BOOT_JAR_JFLAGS) || $(RM) $@
+	$(java-vm-cleanup)
+
+# Printing out a build tool information line
+define printBuildToolSetting
+if [ "$2" != "" ] ; then $(PRINTF) "%-25s %s\n" "$1:" "$2"; fi
+endef
+
+# Print out the build tool information
+tool_info:
+	@$(ECHO) "========================================================="
+	@$(call printBuildToolSetting,BUILDTOOL,$(PROGRAM))
+	@$(call printBuildToolSetting,PACKAGE,$(PACKAGE))
+	@$(call printBuildToolSetting,BUILDTOOL_SOURCE_ROOT,$(BUILDTOOL_SOURCE_ROOT))
+	@$(call printBuildToolSetting,BUILTTOOL_MAINCLASS,$(BUILTTOOL_MAINCLASS))
+	@$(call printBuildToolSetting,BUILDTOOL_JAR_FILE,$(BUILDTOOL_JAR_FILE))
+	@$(ECHO) "========================================================="
+
+clean clobber::
+	@$(RM) -rf $(BUILDTOOLCLASSDIR)/$(PKGDIR)
+	@$(RM) $(BUILDTOOL_MANIFEST_FILE)
+	@$(RM) $(BUILDTOOL_JAR_FILE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/build.xml	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,33 @@
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project name="classanalyzer" default="build" basedir=".">
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/nbproject/project.properties	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,92 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   - Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#
+#   - Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+#   - Neither the name of Sun Microsystems nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+application.title=classanalyzer
+application.vendor=mchung
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+
+cp.extra=${tools.jar} 
+
+debug.classpath=\
+    ${run.classpath}
+debug.test.classpath=\
+    ${run.test.classpath}
+
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/classanalyzer.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+
+excludes=
+
+file.reference.tools.jar=${jdk.home}/lib/tools.jar
+file.reference.tools-src=src
+includes=**
+jar.compress=false
+javac.classpath=\
+    ${file.reference.tools.jar}
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=
+javadoc.author=false
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=false
+javadoc.use=false
+javadoc.version=false
+main.class=com.sun.classanalyzer.ClassAnalyzer
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=JDK_1.6
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=-Xmx256m
+run.test.classpath=
+source.encoding=UTF-8
+src.dir=${file.reference.tools-src}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/nbproject/project.xml	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,45 @@
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.java.j2seproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+            <name>classanalyzer</name>
+            <explicit-platform explicit-source-supported="true"/>
+            <source-roots>
+                <root id="src.dir"/>
+            </source-roots>
+            <test-roots/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotatedDependency.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Map;
+
+import com.sun.classanalyzer.Module.Reference;
+import java.util.LinkedList;
+import java.util.TreeMap;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public abstract class AnnotatedDependency implements Comparable<AnnotatedDependency> {
+
+    final Klass from;
+    final List<String> classes;
+    protected boolean optional;
+    String description;
+    Klass.Method method;
+    private List<Filter> filters = null;
+
+    public AnnotatedDependency(Klass klass) {
+        this(klass, false);
+    }
+
+    public AnnotatedDependency(Klass klass, boolean optional) {
+        this.from = klass;
+        this.classes = new ArrayList<String>();
+        this.optional = optional;
+    }
+
+    abstract String getTag();
+
+    abstract boolean isDynamic();
+
+    void setMethod(Klass.Method m) {
+        this.method = m;
+    }
+
+    void addElement(String element, List<String> value) {
+        if (element.equals("value")) {
+            addValue(value);
+        } else if (element.equals("description")) {
+            description = value.get(0);
+        } else if (element.equals("optional")) {
+            optional = value.get(0).equals("1") || Boolean.parseBoolean(value.get(0));
+        }
+    }
+
+    void addValue(List<String> value) {
+        for (String s : value) {
+            if ((s = s.trim()).length() > 0) {
+                classes.add(s);
+            }
+        }
+    }
+
+    List<String> getValue() {
+        return classes;
+    }
+
+    boolean isOptional() {
+        return optional;
+    }
+
+    boolean isEmpty() {
+        return classes.isEmpty();
+    }
+
+    boolean matches(String classname) {
+        synchronized (this) {
+            // initialize filters
+            if (filters == null) {
+                filters = new ArrayList<Filter>();
+                for (String pattern : classes) {
+                    filters.add(new Filter(pattern));
+                }
+
+            }
+        }
+
+        for (Filter f : filters) {
+            if (f.matches(classname)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (String v : getValue()) {
+            if (sb.length() == 0) {
+                sb.append(getTag());
+                sb.append("\n");
+            } else {
+                sb.append("\n");
+            }
+            sb.append("  ");
+            sb.append(from.getClassName()).append(" -> ");
+            sb.append(v);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public int compareTo(AnnotatedDependency o) {
+        if (from == o.from) {
+            if (this.getClass().getName().equals(o.getClass().getName())) {
+                String s1 = classes.isEmpty() ? "" : classes.get(0);
+                String s2 = o.classes.isEmpty() ? "" : o.classes.get(0);
+                return s1.compareTo(s2);
+            } else {
+                return this.getClass().getName().compareTo(o.getClass().getName());
+            }
+
+        } else {
+            return from.compareTo(o.from);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int hashcode = 7 + 73 * from.hashCode();
+        for (String s : classes) {
+            hashcode ^= s.hashCode();
+        }
+        return hashcode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AnnotatedDependency)) {
+            return false;
+        }
+        AnnotatedDependency other = (AnnotatedDependency) obj;
+        boolean ret = this.from.equals(other.from) && this.classes.size() == other.classes.size();
+        if (ret == true) {
+            for (int i = 0; i < this.classes.size(); i++) {
+                ret = ret && this.classes.get(i).equals(other.classes.get(i));
+            }
+        }
+        return ret;
+    }
+
+    static class ClassForName extends AnnotatedDependency {
+
+        public ClassForName(Klass klass, boolean optional) {
+            super(klass, optional);
+        }
+
+        @Override
+        String getTag() {
+            if (this.optional) {
+                return TAG + "(optional)";
+            } else {
+                return TAG;
+            }
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+        static final String TYPE = "sun.annotation.ClassForName";
+        static final String TAG = "@ClassForName";
+    }
+
+    static class NativeFindClass extends AnnotatedDependency {
+
+        public NativeFindClass(Klass klass, boolean optional) {
+            super(klass, optional);
+        }
+
+        @Override
+        String getTag() {
+            if (this.optional) {
+                return TAG + "(optional)";
+            } else {
+                return TAG;
+            }
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+        static final String TYPE = "sun.annotation.NativeFindClass";
+        static final String TAG = "@NativeFindClass";
+    }
+
+    static class Provider extends AnnotatedDependency {
+
+        private List<String> services = new ArrayList<String>();
+
+        Provider(Klass klass) {
+            super(klass, true);
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+
+        public List<String> services() {
+            return services;
+        }
+
+        @Override
+        void addElement(String element, List<String> value) {
+            if (element.equals("service")) {
+                List<String> configFiles = new ArrayList<String>();
+                for (String s : value) {
+                    if ((s = s.trim()).length() > 0) {
+                        configFiles.add(metaInfPath + s);
+                    }
+                }
+                addValue(configFiles);
+            }
+        }
+
+        @Override
+        void addValue(List<String> value) {
+            for (String s : value) {
+                if ((s = s.trim()).length() > 0) {
+                    if (s.startsWith("META-INF")) {
+                        services.add(s);
+                        readServiceConfiguration(s, classes);
+                    } else {
+                        throw new RuntimeException("invalid value" + s);
+                    }
+                }
+            }
+        }
+
+        boolean isEmpty() {
+            return services.isEmpty();
+        }
+        static final String metaInfPath =
+                "META-INF" + File.separator + "services" + File.separator;
+
+        static void readServiceConfiguration(String config, List<String> names) {
+            BufferedReader br = null;
+            try {
+                InputStream is = ClassPath.open(config);
+                if (is != null) {
+                    // Properties doesn't perserve the order of the input file
+                    br = new BufferedReader(new InputStreamReader(is, "utf-8"));
+                    int lc = 1;
+                    while ((lc = parseLine(br, lc, names)) >= 0);
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (br != null) {
+                    try {
+                        br.close();
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        }
+
+        // Parse a single line from the given configuration file, adding the name
+        // on the line to the names list.
+        //
+        private static int parseLine(BufferedReader r, int lc, List<String> names) throws IOException {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) {
+                ln = ln.substring(0, ci);
+            }
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
+                    throw new RuntimeException("Illegal configuration-file syntax");
+                }
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp)) {
+                    throw new RuntimeException("Illegal provider-class name: " + ln);
+                }
+                for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
+                        throw new RuntimeException("Illegal provider-class name: " + ln);
+                    }
+                }
+                if (!names.contains(ln)) {
+                    names.add(ln);
+                }
+            }
+            return lc + 1;
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AnnotatedDependency)) {
+                return false;
+            }
+            Provider other = (Provider) obj;
+            boolean ret = this.from.equals(other.from) &&
+                    this.services.size() == other.services.size();
+            if (ret == true) {
+                for (int i = 0; i < this.services.size(); i++) {
+                    ret = ret && this.services.get(i).equals(other.services.get(i));
+                }
+            }
+            return ret;
+        }
+
+        @Override
+        public int hashCode() {
+            int hashcode = 7 + 73 * from.hashCode();
+            for (String s : services) {
+                hashcode ^= s.hashCode();
+            }
+            return hashcode;
+        }
+
+        @Override
+        public List<String> getValue() {
+            List<String> result = new ArrayList<String>();
+            result.addAll(services);
+            return result;
+        }
+        static final String TYPE = "sun.annotation.Provider";
+        static final String TAG = "@Provider";
+    }
+
+    static class OptionalDependency extends AnnotatedDependency {
+
+        static boolean isOptional(Klass from, Klass to) {
+            synchronized (OptionalDependency.class) {
+                if (optionalDepsMap == null) {
+                    // Build a map of classes to its optional dependencies
+                    initDependencies();
+                }
+            }
+            for (Reference ref : optionalDepsMap.keySet()) {
+                if (ref.referrer() == from && ref.referree() == to) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        OptionalDependency(Klass klass) {
+            super(klass, true);
+        }
+
+        @Override
+        boolean isDynamic() {
+            return false;
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+        static final String TYPE = "sun.annotation.Optional";
+        static final String TAG = "@Optional";
+    }
+
+    static class CompilerInline extends AnnotatedDependency {
+
+        public CompilerInline(Klass klass) {
+            super(klass);
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+
+        @Override
+        boolean isDynamic() {
+            return false;
+        }
+        static final String TYPE = "sun.annotation.Inline";
+        static final String TAG = "@Inline";
+    }
+
+    static class Filter {
+
+        final String pattern;
+        final String regex;
+
+        Filter(String pattern) {
+            this.pattern = pattern;
+
+            boolean isRegex = false;
+            for (int i = 0; i < pattern.length(); i++) {
+                char p = pattern.charAt(i);
+                if (p == '*' || p == '[' || p == ']') {
+                    isRegex = true;
+                    break;
+                }
+            }
+
+            if (isRegex) {
+                this.regex = convertToRegex(pattern);
+            } else {
+                this.regex = null;
+            }
+        }
+
+        private String convertToRegex(String pattern) {
+            StringBuilder sb = new StringBuilder();
+            int i = 0;
+            int index = 0;
+            int plen = pattern.length();
+            while (i < plen) {
+                char p = pattern.charAt(i);
+                if (p == '*') {
+                    sb.append("(").append(pattern.substring(index, i)).append(")");
+                    if (i + 1 < plen && pattern.charAt(i + 1) == '*') {
+                        sb.append(".*");
+                        index = i + 2;
+                    } else {
+                        sb.append("[^\\.]*");
+                        index = i + 1;
+                    }
+                } else if (p == '[') {
+                    int j = i + 1;
+                    while (j < plen) {
+                        if (pattern.charAt(j) == ']') {
+                            break;
+                        }
+                        j++;
+                    }
+                    if (j >= plen || pattern.charAt(j) != ']') {
+                        throw new RuntimeException("Malformed pattern " + pattern);
+                    }
+                    sb.append("(").append(pattern.substring(index, i)).append(")");
+                    sb.append(pattern.substring(i, j + 1));
+                    index = j + 1;
+                    i = j;
+                }
+                i++;
+            }
+            if (index < plen) {
+                sb.append("(").append(pattern.substring(index, plen)).append(")");
+            }
+            return sb.toString();
+        }
+
+        boolean matches(String name) {
+            if (regex == null) {
+                // the pattern is not a regex
+                return name.equals(pattern);
+            } else {
+                return name.matches(regex);
+            }
+        }
+    }
+
+    static boolean isValidType(String type) {
+        if (type.endsWith("(optional)")) {
+            int len = type.length() - "(optional)".length();
+            type = type.substring(0, len);
+        }
+        return type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG) ||
+                type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG) ||
+                type.equals(Provider.TYPE) || type.equals(Provider.TAG) ||
+                type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG) ||
+                type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG);
+    }
+
+    static AnnotatedDependency newAnnotatedDependency(String tag, String value, Klass klass) {
+        AnnotatedDependency dep = newAnnotatedDependency(tag, klass);
+        if (dep != null) {
+            dep.addValue(Collections.singletonList(value));
+        }
+        return dep;
+    }
+    static List<AnnotatedDependency> annotatedDependencies = new LinkedList<AnnotatedDependency>();
+    static List<AnnotatedDependency> optionalDependencies = new LinkedList<AnnotatedDependency>();
+
+    static AnnotatedDependency newAnnotatedDependency(String type, Klass klass) {
+        boolean optional = false;
+        if (type.endsWith("(optional)")) {
+            optional = true;
+            int len = type.length() - "(optional)".length();
+            type = type.substring(0, len);
+        }
+
+        if (type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG)) {
+            return newOptionalDependency(klass);
+        }
+
+        AnnotatedDependency dep;
+        if (type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG)) {
+            dep = new ClassForName(klass, optional);
+        } else if (type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG)) {
+            dep = new NativeFindClass(klass, optional);
+        } else if (type.equals(Provider.TYPE) || type.equals(Provider.TAG)) {
+            dep = new Provider(klass);
+        } else if (type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG)) {
+            dep = new CompilerInline(klass);
+        } else {
+            return null;
+        }
+        klass.addAnnotatedDep(dep);
+        annotatedDependencies.add(dep);
+        return dep;
+    }
+
+    static OptionalDependency newOptionalDependency(Klass klass) {
+        OptionalDependency dep = new OptionalDependency(klass);
+        optionalDependencies.add(dep);
+        return dep;
+    }
+    static Map<Reference, Set<AnnotatedDependency>> annotatedDepsMap = null;
+    static Map<Reference, Set<AnnotatedDependency>> optionalDepsMap = null;
+
+    static Map<Reference, Set<AnnotatedDependency>> getReferences(Module m) {
+        // ensure it's initialized
+        initDependencies();
+
+        Map<Reference, Set<AnnotatedDependency>> result = new TreeMap<Reference, Set<AnnotatedDependency>>();
+        for (Reference ref : annotatedDepsMap.keySet()) {
+            if (m.contains(ref.referrer()) && m.isModuleDependence(ref.referree())) {
+                result.put(ref, annotatedDepsMap.get(ref));
+            }
+        }
+        return result;
+    }
+
+    static Set<Module.Dependency> getDependencies(Module m) {
+        // ensure it's initialized
+        initDependencies();
+
+        Set<Module.Dependency> deps = new TreeSet<Module.Dependency>();
+        for (Reference ref : annotatedDepsMap.keySet()) {
+            if (m.contains(ref.referrer())) {
+                Module other = m.getModuleDependence(ref.referree());
+                if (other != null) {
+                    for (AnnotatedDependency ad : annotatedDepsMap.get(ref)) {
+                        Module.Dependency d = new Module.Dependency(other, ad.isOptional(), ad.isDynamic());
+                        deps.add(d);
+                    }
+                }
+            }
+        }
+        return deps;
+    }
+
+    synchronized static void initDependencies() {
+        if (annotatedDepsMap != null) {
+            return;
+        }
+
+        // Build a map of references to its dependencies
+        annotatedDepsMap = new TreeMap<Reference, Set<AnnotatedDependency>>();
+        optionalDepsMap = new TreeMap<Reference, Set<AnnotatedDependency>>();
+
+        for (Klass k : Klass.getAllClasses()) {
+            for (AnnotatedDependency ad : annotatedDependencies) {
+                if (ad.matches(k.getClassName())) {
+                    Reference ref = new Reference(ad.from, k);
+                    Set<AnnotatedDependency> set = annotatedDepsMap.get(ref);
+                    if (set == null) {
+                        set = new TreeSet<AnnotatedDependency>();
+                        annotatedDepsMap.put(ref, set);
+                    }
+                    set.add(ad);
+                }
+            }
+
+            for (AnnotatedDependency ad : optionalDependencies) {
+                if (ad.matches(k.getClassName())) {
+                    Reference ref = new Reference(ad.from, k);
+                    Set<AnnotatedDependency> set = optionalDepsMap.get(ref);
+                    if (set == null) {
+                        set = new TreeSet<AnnotatedDependency>();
+                        optionalDepsMap.put(ref, set);
+                    }
+                    set.add(ad);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotationParser.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Annotation;
+import com.sun.tools.classfile.ExtendedAnnotation;
+import com.sun.tools.classfile.Annotation.Annotation_element_value;
+import com.sun.tools.classfile.Annotation.Array_element_value;
+import com.sun.tools.classfile.Annotation.Class_element_value;
+import com.sun.tools.classfile.Annotation.Enum_element_value;
+import com.sun.tools.classfile.Annotation.Primitive_element_value;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Descriptor;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sun.classanalyzer.AnnotatedDependency.*;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class AnnotationParser {
+
+    static boolean parseAnnotation = false;
+    static void setParseAnnotation(boolean newValue) {
+        parseAnnotation = newValue;
+    }
+
+    private final ClassFileParser cfparser;
+    public AnnotationParser(ClassFileParser cfparser) {
+        this.cfparser = cfparser;
+    }
+
+    private AnnotatedDependency addAnnotation(Annotation annot, Klass.Method method) {
+        String type = getType(annot.type_index);
+        AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, cfparser.this_klass);
+        if (dep != null) {
+            for (int i = 0; i < annot.num_element_value_pairs; i++) {
+                Element element = getElement(annot.element_value_pairs[i]);
+                dep.addElement(element.name, element.value);
+            }
+            dep.setMethod(method);
+        }
+        return dep;
+    }
+
+    private AnnotatedDependency addAnnotation(ExtendedAnnotation annot, Klass.Method method) {
+        return addAnnotation(annot.annotation, method);
+    }
+
+    class Element {
+
+        String name;
+        List<String> value;
+
+        Element(String name) {
+            this.name = name;
+            this.value = new ArrayList<String>();
+        }
+
+        void add(String v) {
+            value.add(v);
+        }
+    }
+
+    Element getElement(Annotation.element_value_pair pair) {
+        Element element = new Element(getName(pair.element_name_index));
+        evp.parse(pair.value, element);
+        return element;
+    }
+
+    private String getType(int index) {
+        try {
+            Descriptor d = new Descriptor(index);
+            return d.getFieldType(cfparser.classfile.constant_pool);
+        } catch (ConstantPoolException ignore) {
+        } catch (InvalidDescriptor ignore) {
+        }
+        return "Unknown";
+    }
+
+    private String getName(int index) {
+        return cfparser.constantPoolParser.stringValue(index);
+    }
+    element_value_Parser evp = new element_value_Parser();
+
+    class element_value_Parser implements Annotation.element_value.Visitor<Void, Element> {
+
+        public Void parse(Annotation.element_value value, Element element) {
+            value.accept(this, element);
+            return null;
+        }
+
+        public Void visitPrimitive(Primitive_element_value ev, Element element) {
+            String value = getName(ev.const_value_index);
+            element.add(value);
+            return null;
+        }
+
+        public Void visitEnum(Enum_element_value ev, Element element) {
+            String value = getName(ev.type_name_index) + "." + getName(ev.const_name_index);
+            element.add(value);
+            return null;
+        }
+
+        public Void visitClass(Class_element_value ev, Element element) {
+            String value = getName(ev.class_info_index) + ".class";
+            element.add(value);
+            return null;
+        }
+
+        public Void visitAnnotation(Annotation_element_value ev, Element element) {
+            // AnnotationParser.this.addAnnotation(ev.annotation_value);
+            throw new UnsupportedOperationException("Not supported: " + ev);
+        }
+
+        public Void visitArray(Array_element_value ev, Element element) {
+            for (int i = 0; i < ev.num_values; i++) {
+                parse(ev.values[i], element);
+            }
+            return null;
+        }
+    }
+
+    void parseAttributes(Attributes attributes, Klass.Method method) {
+        if (!parseAnnotation) {
+            return;
+        }
+
+        visitRuntimeAnnotations((RuntimeVisibleAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleAnnotations), method);
+        visitRuntimeAnnotations((RuntimeInvisibleAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleAnnotations), method);
+        visitRuntimeTypeAnnotations((RuntimeVisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleTypeAnnotations), method);
+        visitRuntimeTypeAnnotations((RuntimeInvisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleTypeAnnotations), method);
+        visitRuntimeParameterAnnotations((RuntimeVisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleParameterAnnotations), method);
+        visitRuntimeParameterAnnotations((RuntimeInvisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleParameterAnnotations), method);
+    }
+
+    public void visitRuntimeAnnotations(RuntimeAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int i = 0; i < attr.annotations.length; i++) {
+            addAnnotation(attr.annotations[i], method);
+        }
+    }
+
+    public void visitRuntimeTypeAnnotations(RuntimeTypeAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int i = 0; i < attr.annotations.length; i++) {
+            addAnnotation(attr.annotations[i], method);
+        }
+    }
+
+    public void visitRuntimeParameterAnnotations(RuntimeParameterAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int param = 0; param < attr.parameter_annotations.length; param++) {
+            for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
+                addAnnotation(attr.parameter_annotations[param][i], method);
+            }
+        }
+    }
+
+    void parseAttributes(Attributes attributes) {
+        parseAttributes(attributes, null);
+    }
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String output = ".";
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-output")) {
+                output = args[i++];
+            } else {
+                usage();
+            }
+        }
+        if (jdkhome == null) {
+            usage();
+        }
+
+        // parse annotation and code attribute to find all references
+        // to Class.forName etc
+        CodeAttributeParser.setParseCodeAttribute(true);
+        AnnotationParser.setParseAnnotation(true);
+
+        ClassPath.setJDKHome(jdkhome);
+        ClassPath.parseAllClassFiles();
+
+        PrintWriter writer = new PrintWriter(new File(output, "jdk7.depconfig"));
+
+        try {
+            for (Klass k : Klass.getAllClasses()) {
+                for (AnnotatedDependency dep : k.getAnnotatedDeps()) {
+                    if (dep.isEmpty()) {
+                        continue;
+                    }
+                    writer.format("# %s \n", dep.method == null ? dep.from : dep.method);
+                    writer.format("%s\n\n", dep);
+                }
+            }
+        } finally {
+            writer.close();
+        }
+
+        writer = new PrintWriter(new File(output, "optional.depconfig"));
+        try {
+            AnnotatedDependency prev = null;
+            for (AnnotatedDependency dep : AnnotatedDependency.optionalDependencies) {
+                if (prev != null && !dep.equals(prev)) {
+                    writer.format("%s\n\n", prev);
+                }
+                writer.format("# %s \n", dep.method == null ? dep.from : dep.method);
+                prev = dep;
+            }
+            if (prev != null) {
+                writer.format("%s\n\n", prev);
+            }
+        } finally {
+            writer.close();
+        }
+
+        writer = new PrintWriter(new File(output, "runtime.references"));
+        try {
+            for (Map.Entry<String, Set<Klass.Method>> entry : CodeAttributeParser.runtimeReferences.entrySet()) {
+                writer.format("References to %s\n", entry.getKey());
+                Klass prev = null;
+                for (Klass.Method m : entry.getValue()) {
+                    if (prev == null || prev != m.getKlass()) {
+                        writer.format("  %-50s # %s\n", m.getKlass(), m);
+                    } else if (prev == m.getKlass()) {
+                        writer.format("  %-50s # %s\n", "", m);
+                    }
+                    prev = m.getKlass();
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void usage() {
+        System.out.println("Usage: AnnotationParser <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-depconfig <output file for annotated dependencies>");
+        System.out.println("\t-optional <output file for optional dependencies>");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/BootAnalyzer.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,819 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.File;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Instruction.TypeKind;
+import com.sun.tools.classfile.Type.*;
+
+/**
+ * Generate the module config for the boot module with
+ * a given set of roots (classes or methods) and exclude list.
+ *
+ * This tool does method-level dependency analysis starting
+ * from the root set and follows references transitively as follows:
+ * <ul>
+ * <li>For a given class, it will parse the ClassFile to
+ *     find its superclass and superinterfaces and also
+ *     its static initializer &lt;clinit&gt;.</li>
+ * <li>For each method, it will parse its Code attribute
+ *     to look for a Methodref, Fieldref, and InterfaceMethodref.
+ *     </li>
+ * <li>For each Fieldref, it will include the type of
+ *     the field in the dependency.</li>
+ * <li>For each MethodRef, it will follow all references in
+ *     that method.</li>
+ * <li>For each InterfaceMethodref, it will follow all references in
+ *     that method defined its implementation classes in
+ *     the resulting dependency list.</li>
+ * </ul>
+ *
+ * Limitation:
+ * <ul>
+ * <li>For each Methodref, it only parses the method of
+ *     the specified type.  It doesn't analyze the class hierarchy
+ *     and follow references of its subclasses since it ends up
+ *     pulls in many unnecessary dependencies.  For now,
+ *     the list of subclasses and methods need to be listed in
+ *     the root set.</li>
+ * </ul>
+ *
+ * @author Mandy Chung
+ */
+public class BootAnalyzer {
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String config = null;
+        String output = ".";
+        boolean printClassList = false;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-config")) {
+                config = args[i++];
+            } else if (arg.equals("-output")) {
+                output = args[i++];
+            } else if (arg.equals("-classlist")) {
+                printClassList = true;
+            } else {
+                usage();
+            }
+        }
+
+
+
+        if (jdkhome == null || config == null) {
+            usage();
+        }
+
+        File jre = new File(jdkhome, "jre");
+        if (jre.exists()) {
+            ClassPath.setJDKHome(jdkhome);
+        } else {
+            File classes = new File(jdkhome, "classes");
+            if (classes.exists()) {
+                ClassPath.setClassPath(classes.getCanonicalPath());
+            } else {
+                throw new RuntimeException("Invalid jdkhome: " + jdkhome);
+            }
+        }
+
+        parseConfigFile(config);
+        followRoots();
+
+        // create output directory if it doesn't exist
+        File dir = new File(output);
+        if (!dir.isDirectory()) {
+            if (!dir.exists()) {
+                boolean created = dir.mkdir();
+                if (!created) {
+                    throw new RuntimeException("Unable to create `" + dir + "'");
+                }
+            }
+        }
+
+        String bootmodule = "boot";
+        String bootconfig = resolve(dir, bootmodule, "config");
+        printBootConfig(bootconfig, bootmodule);
+
+        List<ModuleConfig> list = ModuleConfig.readConfigurationFile(bootconfig);
+        Module module = Module.addModule(list.get(0));
+        for (Klass k : Klass.getAllClasses()) {
+            module.addKlass(k);
+        }
+        module.fixupDependencies();
+
+        if (printClassList) {
+            module.printClassListTo(resolve(dir, bootmodule, "classlist"));
+            module.printSummaryTo(resolve(dir, bootmodule, "summary"));
+        }
+    }
+
+    // print boot.config file as an input to the ClassAnalyzer
+    private static void printBootConfig(String output, String bootmodule) throws IOException {
+
+        File f = new File(output);
+        PrintWriter writer = new PrintWriter(f);
+        try {
+            int count = 0;
+            writer.format("module %s {%n", bootmodule);
+            for (Klass k : Klass.getAllClasses()) {
+                if (count++ == 0) {
+                    writer.format("%4s%7s %s", "", "include", k);
+                } else {
+                    writer.format(",%n");
+                    writer.format("%4s%7s %s", "", "", k);
+                }
+            }
+            writer.format(";%n}%n");
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static String resolve(File dir, String mname, String suffix) {
+        File f = new File(dir, mname + "." + suffix);
+        return f.toString();
+
+    }
+    static List<MethodDescriptor> methods = new LinkedList<MethodDescriptor>();
+    static Deque<MethodDescriptor> pending = new ArrayDeque<MethodDescriptor>();
+    static Deque<MethodDescriptor> interfaceMethodRefs = new ArrayDeque<MethodDescriptor>();
+    static Filter filter = new Filter();
+
+    private static void followRoots() throws IOException {
+        MethodDescriptor md = null;
+
+        while ((md = pending.poll()) != null) {
+            if (!methods.contains(md)) {
+                methods.add(md);
+                if (md.classname.isEmpty()) {
+                    trace("Warning: class missing %s%n", md);
+                    continue;
+                }
+
+                if (filter.isExcluded(md.classname)) {
+                    trace("excluded %s%n", md);
+                } else {
+                    KlassInfo kinfo = getKlassInfo(md.classname);
+                    if (kinfo.classname.contains("$")) {
+                        int pos = kinfo.classname.lastIndexOf('$');
+                        String outer = kinfo.classname.substring(0, pos);
+                        if (!cache.containsKey(outer)) {
+                            trace("  include outer class %s%n", outer);
+                            getKlassInfo(outer).ensureParse();
+                        }
+                    }
+
+                    kinfo.ensureParse();
+                    if (md.methodname.length() > 0) {
+                        if (filter.isExcluded(md.name)) {
+                            trace("excluded %s%n", md);
+                        } else {
+                            if (md.interfaceMethodRef) {
+                                trace("interface methodref %s%n", md);
+                                interfaceMethodRefs.add(md);
+                            } else {
+                                List<String> descriptors = kinfo.parse(md);
+                                if (descriptors.isEmpty()) {
+                                    if (kinfo.getSuperclass() != null) {
+                                        String sn = kinfo.getSuperclass().classname;
+                                        MethodDescriptor superMD = new MethodDescriptor(sn + "." + md.methodname, md.descriptor, false);
+                                        if (!methods.contains(superMD) && !pending.contains(superMD)) {
+                                            trace("  delegated %s to %s%n", md, superMD);
+                                            pending.add(superMD);
+                                        }
+                                    } else if (kinfo.isClass()) {
+                                        trace("  %s (not found)%n", md);
+                                    } else {
+                                        trace("  %s (interface)%n", md);
+                                    }
+                                } else {
+                                    if (md.descriptor.equals("*")) {
+                                        trace("  parsed %s : ", md.name);
+                                        for (String s : descriptors) {
+                                            trace(" %s", s);
+                                        }
+                                        trace("%n");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (pending.isEmpty()) {
+                for (Klass k : Klass.getAllClasses()) {
+                    if (k.getFileSize() == 0) {
+                        getKlassInfo(k.getClassName()).ensureParse();
+                    }
+                }
+                while ((md = interfaceMethodRefs.poll()) != null) {
+                    addSubClassMethods(md);
+                }
+            }
+        }
+    }
+
+    static void addSubClassMethods(MethodDescriptor md) throws IOException {
+        for (KlassInfo kinfo : getSubClasses(md.classname)) {
+            String methodname = kinfo.classname + "." + md.methodname;
+            MethodDescriptor other = new MethodDescriptor(methodname, md.descriptor, false);
+            if (!methods.contains(other) && !pending.contains(other)) {
+                trace("Warning: subclass from %s to %s%n", md.classname, other);
+                pending.add(other);
+            }
+        }
+    }
+    private final static String privilegedActionInterf = "java.security.PrivilegedAction";
+    private final static String privilegedExceptionActionInterf = "java.security.PrivilegedExceptionAction";
+
+    static boolean isPrivilegedAction(String classname) {
+        if (classname.isEmpty()) {
+            return false;
+        }
+        KlassInfo kinfo = getKlassInfo(classname);
+        for (KlassInfo ki : kinfo.getInterfaces()) {
+            String interf = ki.classname;
+            if (interf.equals(privilegedActionInterf) ||
+                    interf.equals(privilegedExceptionActionInterf)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    static Map<String, KlassInfo> cache = new HashMap<String, KlassInfo>();
+
+    static KlassInfo getKlassInfo(String classname) {
+        classname = classname.replace('/', '.');
+
+        KlassInfo kinfo = cache.get(classname);
+        if (kinfo == null) {
+            kinfo = new KlassInfo(classname);
+            cache.put(classname, kinfo);
+        }
+        return kinfo;
+    }
+
+    static class KlassInfo {
+
+        final String classname;
+        private ClassFileParser parser;
+        private KlassInfo superclass;
+        private List<KlassInfo> interfaces = new LinkedList<KlassInfo>();
+
+        KlassInfo(String classname) {
+            this.classname = classname;
+        }
+
+        boolean isClass() {
+            ensureParse();
+            return parser.classfile.isClass();
+        }
+
+        KlassInfo getSuperclass() {
+            ensureParse();
+            return superclass;
+        }
+
+        List<KlassInfo> getInterfaces() {
+            ensureParse();
+            return java.util.Collections.unmodifiableList(interfaces);
+        }
+
+        void ensureParse() {
+            try {
+                getClassFileParser();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        synchronized ClassFileParser getClassFileParser() throws IOException {
+            if (parser == null) {
+                parser = ClassPath.parserForClass(classname);
+                if (parser != null) {
+                    parseClassFile();
+                    List<String> descriptors = parse(new MethodDescriptor(classname + ".<clinit>", "()V", false));
+                }
+            }
+            return parser;
+        }
+
+        List<String> parse(MethodDescriptor md) {
+            ensureParse();
+            try {
+                List<String> descriptors = new LinkedList<String>();
+                for (Method m : parser.classfile.methods) {
+                    String name = m.getName(parser.classfile.constant_pool);
+                    String desc = parser.constantPoolParser.getDescriptor(m.descriptor.index);
+                    if (name.equals(md.methodname)) {
+                        if (md.descriptor.equals("*") || md.descriptor.equals(desc)) {
+                            parseMethod(parser, m);
+                            descriptors.add(desc);
+                        }
+                    }
+                }
+                return descriptors;
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        private void parseClassFile() throws IOException {
+            parser.parseClassInfo();
+
+            ClassFile classfile = parser.classfile;
+            try {
+                if (classfile.super_class > 0) {
+                    superclass = getKlassInfo(classfile.getSuperclassName());
+                }
+                if (classfile.interfaces != null) {
+                    for (int i = 0; i < classfile.interfaces.length; i++) {
+                        interfaces.add(getKlassInfo(classfile.getInterfaceName(i)));
+                    }
+                }
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    static List<KlassInfo> getSubClasses(String classname) throws IOException {
+        List<KlassInfo> result = new LinkedList<KlassInfo>();
+        List<KlassInfo> list = new LinkedList<KlassInfo>();
+        list.addAll(cache.values());
+        for (KlassInfo kinfo : list) {
+            if (kinfo.getSuperclass() != null && classname.equals(kinfo.getSuperclass().classname)) {
+                result.add(kinfo);
+            }
+            for (KlassInfo interf : kinfo.getInterfaces()) {
+                if (classname.equals(interf.classname)) {
+                    result.add(kinfo);
+                }
+            }
+        }
+        return result;
+    }
+
+    private static void parseConfigFile(String config) throws IOException {
+        FileInputStream in = new FileInputStream(config);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            int lineNumber = 0;
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+                if ((line = line.trim()).length() > 0) {
+                    if (line.startsWith("#")) {
+                        continue;
+                    }
+
+                    String[] s = line.split("\\s+");
+                    if ("exclude".equals(s[0])) {
+                        filter.exclude(s[1]);
+                    } else {
+                        String name = s[0].replace('/', '.');
+                        if (name.length() > 0) {
+                            String classname = name.replace('/', '.');
+                            if (s.length == 2) {
+                                // method name
+                                int pos = classname.lastIndexOf('.');
+                                classname = classname.substring(0, pos);
+                            }
+
+                            KlassInfo kinfo = getKlassInfo(classname);
+                            if (kinfo.getClassFileParser() != null) {
+                                // class exists
+                                MethodDescriptor md = (s.length == 1) ? new MethodDescriptor(name) : new MethodDescriptor(name, s[1], false);
+                                if (!pending.contains(md)) {
+                                    pending.add(md);
+                                }
+                            } else {
+                                // class not found
+                                trace("Class %s not found%n", classname);
+                            }
+                        }
+                    }
+                }
+            }
+
+        } finally {
+            in.close();
+        }
+    }
+
+    private static void parseMethod(ClassFileParser cfparser, Method m) {
+        Klass.Method kmethod = cfparser.parseMethod(m);
+        Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
+        if (c_attr != null) {
+            LineNumberTable_attribute lineNumTable =
+                    (LineNumberTable_attribute) c_attr.attributes.get(Attribute.LineNumberTable);
+            InstructorVisitor visitor = new InstructorVisitor(cfparser, lineNumTable);
+            trace("parseMethod %s %s %n", cfparser.this_klass, kmethod);
+            for (Instruction instr : c_attr.getInstructions()) {
+                try {
+                    instr.accept(visitor, kmethod);
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new RuntimeException("error at or after byte " + instr.getPC());
+                }
+
+            }
+
+            if (c_attr.exception_table_langth > 0) {
+                for (int i = 0; i <
+                        c_attr.exception_table.length; i++) {
+                    Code_attribute.Exception_data handler = c_attr.exception_table[i];
+                    int catch_type = handler.catch_type;
+                    if (catch_type > 0) {
+                        visitor.addConstantPoolRef(catch_type, kmethod, handler.start_pc);
+                    }
+
+                }
+            }
+        }
+    }
+
+    static class MethodDescriptor {
+
+        final String name;
+        final String classname;
+        final String methodname;
+        final String descriptor;
+        final boolean interfaceMethodRef;
+
+        MethodDescriptor(String classname) {
+            this.classname = classname.replace('/', '.');
+            this.name = this.classname;
+            this.methodname = "";
+            this.descriptor = "";
+            this.interfaceMethodRef = false;
+            if (this.classname.length() == 1) {
+                throw new RuntimeException("invalid " + this);
+            }
+        }
+
+        MethodDescriptor(String name, String descriptor, boolean interfaceMethodRef) {
+            name = name.replace('/', '.');
+            this.name = name;
+            int pos = name.lastIndexOf('.');
+            this.classname = name.substring(0, pos);
+            this.methodname = name.substring(pos + 1, name.length());
+            this.descriptor = descriptor;
+            this.interfaceMethodRef = interfaceMethodRef;
+            if (this.classname.length() == 1) {
+                throw new RuntimeException("invalid " + this);
+            }
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            MethodDescriptor m = (MethodDescriptor) obj;
+
+            return this.name.equals(m.name) &&
+                    this.descriptor.equals(m.descriptor);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
+            hash = 97 * hash + (this.descriptor != null ? this.descriptor.hashCode() : 0);
+            return hash;
+        }
+
+        public String toString() {
+            if (descriptor.isEmpty()) {
+                return name;
+            } else {
+                return name + " : " + descriptor;
+            }
+        }
+    }
+
+    static class Filter {
+
+        private Set<String> excludes = new TreeSet<String>();
+
+        Filter exclude(String pattern) {
+            excludes.add(pattern);
+            return this;
+        }
+
+        boolean isExcluded(String klass) {
+            for (String pattern : excludes) {
+                if (matches(klass, pattern)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean matches(String klass, String pattern) {
+            int pos = klass.lastIndexOf('.');
+            String packageName = pos > 0 ? klass.substring(0, pos) : "<unnamed>";
+            if (pattern.endsWith("**")) {
+                String p = pattern.substring(0, pattern.length() - 2);
+                return klass.startsWith(p);
+            } else if (pattern.endsWith("*")) {
+                pos = pattern.lastIndexOf('.');
+                String pkg = pos > 0 ? pattern.substring(0, pos) : "<unnamed>";
+                if (packageName.equals(pkg)) {
+                    // package name has to be exact match
+                    String p = pattern.substring(0, pattern.length() - 1);
+                    return klass.startsWith(p);
+                } else {
+                    return false;
+                }
+            } else {
+                // exact match or inner class
+                return klass.equals(pattern) || klass.startsWith(pattern + "$");
+            }
+        }
+    }
+
+    static class InstructorVisitor implements Instruction.KindVisitor<Void, Klass.Method> {
+
+        private final ClassFileParser parser;
+        private final LineNumberTable_attribute lineNumTable;
+
+        InstructorVisitor(ClassFileParser parser, LineNumberTable_attribute lineNumTable) {
+            this.parser = parser;
+            this.lineNumTable = lineNumTable;
+        }
+
+        int getLineNumber(int pc) {
+            if (lineNumTable != null) {
+                int start_pc = 0;
+                int lineno = 0;
+                for (int i = 0; i < lineNumTable.line_number_table_length; i++) {
+                    int cur_start_pc = lineNumTable.line_number_table[i].start_pc;
+                    if (pc == 0 && cur_start_pc == 0) {
+                        return lineNumTable.line_number_table[i].line_number;
+                    } else if (pc >= start_pc && pc < cur_start_pc) {
+                        return lineno;
+                    }
+                    start_pc = cur_start_pc;
+                    lineno = lineNumTable.line_number_table[i].line_number;
+                }
+            }
+            return 0;
+        }
+
+        void addConstantPoolRef(int index, Klass.Method m, int pc) {
+            try {
+                CPInfo cpInfo = parser.classfile.constant_pool.get(index);
+                String name = cpInfo.accept(typeFinder, null);
+                if (name != null) {
+                    trace("   %s %s at line %d%n", parser.constantPoolParser.tagName(index), name, getLineNumber(pc));
+                }
+            } catch (InvalidIndex ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        public Void visitNoOperands(Instruction instr, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitBranch(Instruction instr, int offset, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) {
+            addConstantPoolRef(index, m, instr.getPC());
+            return null;
+        }
+
+        public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) {
+            addConstantPoolRef(index, m, instr.getPC());
+            return null;
+        }
+
+        public Void visitLocal(Instruction instr, int index, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitValue(Instruction instr, int value, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitUnknown(Instruction instr, Klass.Method m) {
+            return null;
+        }
+        private ConstantPool.Visitor<String, Void> typeFinder = new ConstantPool.Visitor<String, Void>() {
+
+            String getClassName(CPRefInfo info, Void p) {
+                try {
+                    return parser.checkClassName(info.getClassName()).replace('/', '.');
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+
+            boolean addReferencedClass(String name) {
+                if (Klass.findKlass(name) == null) {
+                    MethodDescriptor md = new MethodDescriptor(name);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        pending.add(md);
+                    }
+                    return true;
+                }
+                return false;
+            }
+            private String privilegedActionClass = "";
+
+            void cachePrivilegedAction(String classname) {
+                trace("   found PrivilegedAction %s%n", classname);
+                privilegedActionClass = classname;
+            }
+
+            void doPrivilegedCall(String method) {
+                if (privilegedActionClass.length() > 0) {
+                    MethodDescriptor md = new MethodDescriptor(privilegedActionClass + ".run", "*", false);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        trace("   doPrivileged %s%n", md);
+                        pending.add(md);
+                    }
+                }
+            }
+
+            private String addMethodDescriptor(CPRefInfo info, Void p) {
+                try {
+                    String classname = getClassName(info, null);
+                    String method = classname + "." + info.getNameAndTypeInfo().getName();
+                    String descriptor = info.getNameAndTypeInfo().getType();
+
+                    if (method.endsWith(".<init>") && isPrivilegedAction(classname)) {
+                        cachePrivilegedAction(classname);
+                    }
+                    if (method.equals("java.security.AccessController.doPrivileged")) {
+                        doPrivilegedCall(method);
+                        return method;
+                    }
+
+                    boolean interfaceMethodRef = info instanceof CONSTANT_InterfaceMethodref_info;
+                    MethodDescriptor md = new MethodDescriptor(method, descriptor, interfaceMethodRef);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        pending.add(md);
+                    }
+                    return method;
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            public String visitClass(CONSTANT_Class_info info, Void p) {
+                try {
+                    String classname = parser.checkClassName(info.getName()).replace('/', '.');
+                    if (classname.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+                    return classname;
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+
+            public String visitDouble(CONSTANT_Double_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+                try {
+                    String classname = getClassName(info, p);
+                    if (classname.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+
+                    String type = info.getNameAndTypeInfo().getType();
+                    String fieldType = parser.checkClassName(type).replace('/', '.');
+                    if (fieldType.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+                    return parser.constantPoolParser.stringValue(info);
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            public String visitFloat(CONSTANT_Float_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitInteger(CONSTANT_Integer_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+                return addMethodDescriptor(info, p);
+            }
+
+            public String visitLong(CONSTANT_Long_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
+                return addMethodDescriptor(info, p);
+            }
+
+            public String visitString(CONSTANT_String_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
+                return null;
+            }
+        };
+    }
+    static boolean traceOn = System.getProperty("classanalyzer.debug") != null;
+
+    private static void trace(String format, Object... args) {
+        if (traceOn) {
+            System.out.format(format, args);
+        }
+    }
+
+    private static void usage() {
+        System.out.println("Usage: BootAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-config  <roots for the boot module>");
+        System.out.println("\t-output  <output dir>");
+        System.out.println("\t-classlist print class list and summary");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CheckDeps.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * A simple tool to check module dependencies against a known list of
+ * dependencies. The tool fails (by throwing a RuntimeException) is an
+ * unexpected dependency is detected.
+ */
+
+public class CheckDeps {
+
+    /**
+     * Represents a dependency from one module to another module. The dependency
+     * may be optional.
+     */
+    static class Dependency {
+        private final String module;
+        private final String other;
+        private final boolean optional;
+
+        private Dependency(String module, String other, boolean optional) {
+            this.module = module;
+            this.other = other;
+            this.optional = optional;
+        }
+
+        String module()      { return module; }
+        String other()       { return other; }
+        boolean isOptional() { return optional; }
+
+        /**
+         * Parses a dependency in one of the following forms:
+         *   a -> b
+         *   [optional] a -> b
+         */
+        static Dependency fromString(String s) {
+            String[] components = s.split(" ");
+            int count = components.length;
+            if (count != 3 && count != 4)
+                throw new IllegalArgumentException(s);
+            boolean optional = (count == 4);
+            if (optional && !components[0].equals("[optional]"))
+                throw new IllegalArgumentException(s);
+            String arrow = optional ? components[2] : components[1];
+            if (!arrow.equals("->"))
+                throw new IllegalArgumentException(s);
+            String module = optional ? components[1] : components[0];
+            String other = optional ? components[3] : components[2];
+            return new Dependency(module, other, optional);
+        }
+
+        @Override public String toString() {
+            StringBuilder sb = new StringBuilder();
+            if (optional)
+                sb.append("[optional] ");
+            sb.append(module);
+            sb.append(" -> ");
+            sb.append(other);
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Represents the "tail"
+     */
+    static class DependencyTail {
+        private final String module;
+        private final boolean optional;
+
+        DependencyTail(String module, boolean optional) {
+            this.module = module;
+            this.optional = optional;
+        }
+        String module()      { return module; }
+        boolean isOptional() { return optional; }
+    }
+
+    static void usage() {
+        System.out.println("java CheckDeps file1 file2");
+        System.out.println("  where file1 is the expected dependencies and file2 is");
+        System.out.println("  the actual dependencies. Both files are assumed to be");
+        System.out.println("  in modules.summary format (see ClassAnalyzer tool).");
+        System.out.println();
+        System.out.println("Example usages:");
+        System.out.println("  java CheckDeps make/modules/modules.summary " +
+            "$(OUTPUTDIR)/modules.summary");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (args.length != 2)
+            usage();
+
+        // maps a module to the list of modules that it depends on
+        Map<String,List<DependencyTail>> expected =
+            new HashMap<String,List<DependencyTail>>();
+
+        // parse the expected dependencies file
+        Scanner s;
+        s = new Scanner(new FileInputStream(args[0]));
+        try {
+            while (s.hasNextLine()) {
+                Dependency ref = Dependency.fromString(s.nextLine());
+                if (ref != null) {
+                    String module = ref.module();
+                    List<DependencyTail> list = expected.get(module);
+                    if (list == null) {
+                        list = new ArrayList<DependencyTail>();
+                        expected.put(module, list);
+                    }
+                    list.add(new DependencyTail(ref.other(), ref.isOptional()));
+                }
+            }
+        } finally {
+            s.close();
+        }
+
+        // parse the actual dependencies file, checking each dependency
+        // against the expected list.
+        boolean fail = false;
+        s = new Scanner(new FileInputStream(args[1]));
+        try {
+            while (s.hasNextLine()) {
+                Dependency dep = Dependency.fromString(s.nextLine());
+
+                // check if this dependency is expected
+                List<DependencyTail> list = expected.get(dep.module());
+                DependencyTail tail = null;
+                if (list != null) {
+                    for (DependencyTail t: list) {
+                        if (t.module().equals(dep.other())) {
+                            tail = t;
+                            break;
+                        }
+                    }
+                }
+                if (tail == null) {
+                    System.err.println("Unexpected dependency: " + dep);
+                    fail = true;
+                } else {
+                    // hard dependency when optional dependency is expected
+                    if (tail.isOptional() != dep.isOptional()) {
+                        if (tail.isOptional()) {
+                            System.err.println("Unexpected dependency: " + dep);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        } finally {
+            s.close();
+        }
+
+        if (fail)
+            throw new RuntimeException("Unexpected dependencies found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassAnalyzer.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.classanalyzer.AnnotatedDependency.*;
+import com.sun.classanalyzer.Module.Dependency;
+import com.sun.classanalyzer.Module.PackageInfo;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ClassAnalyzer {
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String cpath = null;
+        List<String> configs = new ArrayList<String>();
+        List<String> depconfigs = new ArrayList<String>();
+        String output = ".";
+        boolean mergeModules = true;
+        boolean showDynamic = false;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-cpath")) {
+                if (i < args.length) {
+                    cpath = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-config")) {
+                if (i < args.length) {
+                    configs.add(args[i++]);
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-depconfig")) {
+                if (i < args.length) {
+                    depconfigs.add(args[i++]);
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-output")) {
+                if (i < args.length) {
+                    output = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-base")) {
+                ModuleConfig.setBaseModule(args[i++]);
+            } else if (arg.equals("-nomerge")) {
+                // analyze the fine-grained module dependencies
+                mergeModules = false;
+            } else if (arg.equals("-showdynamic")) {
+                showDynamic = true;
+            } else {
+                System.err.println("Invalid option: " + arg);
+                usage();
+            }
+        }
+
+        if ((jdkhome == null && cpath == null) || (jdkhome != null && cpath != null)) {
+            usage();
+        }
+        if (configs.isEmpty()) {
+            usage();
+        }
+
+        if (jdkhome != null) {
+            ClassPath.setJDKHome(jdkhome);
+        } else if (cpath != null) {
+            ClassPath.setClassPath(cpath);
+        }
+
+        // create output directory if it doesn't exist
+        File dir = new File(output);
+        if (!dir.isDirectory()) {
+            if (!dir.exists()) {
+                boolean created = dir.mkdir();
+                if (!created) {
+                    throw new RuntimeException("Unable to create `" + dir + "'");
+                }
+            }
+        }
+
+        buildModules(configs, depconfigs, mergeModules);
+
+        // generate output files
+        for (Module m : modules) {
+            // only generate reports for top-level modules
+            if (m.group() == m) {
+                m.printClassListTo(resolve(dir, m.name(), "classlist"));
+                m.printResourceListTo(resolve(dir, m.name(), "resources"));
+                m.printSummaryTo(resolve(dir, m.name(), "summary"));
+                m.printDependenciesTo(resolve(dir, m.name(), "dependencies"), showDynamic);
+            }
+        }
+
+        // Generate other summary reports
+        printModulesSummary(dir, showDynamic);
+        printModulesDot(dir, showDynamic);
+        printModulesList(dir);
+        printPackagesSummary(dir);
+    }
+    private static List<Module> modules = new ArrayList<Module>();
+
+    static void buildModules(List<String> configs,
+            List<String> depconfigs,
+            boolean mergeModules) throws IOException {
+        // create modules based on the input config files
+        for (String file : configs) {
+            for (ModuleConfig mconfig : ModuleConfig.readConfigurationFile(file)) {
+                modules.add(Module.addModule(mconfig));
+            }
+        }
+
+        // parse class files
+        ClassPath.parseAllClassFiles();
+
+        // Add additional dependencies if specified
+        if (depconfigs != null && depconfigs.size() > 0) {
+            DependencyConfig.parse(depconfigs);
+        }
+
+        // process the roots and dependencies to get the classes for each module
+        for (Module m : modules) {
+            m.processRootsAndReferences();
+        }
+
+        // update the dependencies for classes that were subsequently allocated
+        // to modules
+        for (Module m : modules) {
+            m.fixupDependencies();
+        }
+
+        if (mergeModules) {
+            Module.buildModuleMembers();
+        }
+    }
+
+    private static void printModulesSummary(File dir, boolean showDynamic) throws IOException {
+        // print summary of dependencies
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.summary"));
+        try {
+            for (Module m : modules) {
+                // only show top-level module dependencies
+                if (m.group() == m) {
+                    for (Dependency dep : m.dependents()) {
+                        if (!showDynamic && dep.dynamic && dep.optional) {
+                            continue;
+                        }
+                        if (dep.module == null || !dep.module.isBase()) {
+
+                            String prefix = "";
+                            if (dep.optional) {
+                                if (dep.dynamic) {
+                                    prefix = "[dynamic] ";
+                                } else {
+                                    prefix = "[optional] ";
+                                }
+                            }
+
+                            Module other = dep != null ? dep.module : null;
+                            writer.format("%s%s -> %s%n", prefix, m, other);
+                        }
+                    }
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printModulesDot(File dir, boolean showDynamic) throws IOException {
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.dot"));
+        try {
+            writer.println("digraph jdk {");
+            for (Module m : modules) {
+                if (m.group() == m) {
+                    for (Dependency dep : m.dependents()) {
+                        if (!showDynamic && dep.dynamic && dep.optional) {
+                            continue;
+                        }
+                        if (dep.module == null || !dep.module.isBase()) {
+                            String style = "";
+                            String color = "";
+                            String property = "";
+                            if (dep.optional) {
+                                style = "style=dotted";
+                            }
+                            if (dep.dynamic) {
+                                color = "color=red";
+                            }
+                            if (style.length() > 0 || color.length() > 0) {
+                                String comma = "";
+                                if (style.length() > 0 && color.length() > 0) {
+                                    comma = ", ";
+                                }
+                                property = String.format(" [%s%s%s]", style, comma, color);
+                            }
+                            Module other = dep != null ? dep.module : null;
+                            writer.format("    \"%s\" -> \"%s\"%s;%n", m, other, property);
+                        }
+                    }
+                }
+            }
+            writer.println("}");
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printMembers(Module m, PrintWriter writer) {
+        for (Module member : m.members()) {
+            if (!member.isEmpty()) {
+                writer.format("%s ", member);
+                printMembers(member, writer);
+            }
+        }
+    }
+
+    private static void printModulesList(File dir) throws IOException {
+        // print module group / members relationship
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.list"));
+        try {
+            for (Module m : modules) {
+                if (m.group() == m && !m.isEmpty()) {
+                    writer.format("%s ", m);
+                    printMembers(m, writer);
+                    writer.println();
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printPackagesSummary(File dir) throws IOException {
+        // print package / module relationship
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.pkginfo"));
+        try {
+            Map<String, Set<Module>> packages = new TreeMap<String, Set<Module>>();
+            Set<String> splitPackages = new TreeSet<String>();
+
+            for (Module m : modules) {
+                if (m.group() == m) {
+                    for (PackageInfo info : m.getPackageInfos()) {
+                        Set<Module> value = packages.get(info.pkgName);
+                        if (value == null) {
+                            value = new TreeSet<Module>();
+                            packages.put(info.pkgName, value);
+                        } else {
+                            // package in more than one module
+                            splitPackages.add(info.pkgName);
+                        }
+                        value.add(m);
+                    }
+                }
+            }
+
+            // packages that are splitted among multiple modules
+            writer.println("Packages splitted across modules:-\n");
+            writer.format("%-60s  %s\n", "Package", "Module");
+
+            for (String pkgname : splitPackages) {
+                writer.format("%-60s", pkgname);
+                for (Module m : packages.get(pkgname)) {
+                    writer.format("  %s", m);
+                }
+                writer.println();
+            }
+
+            writer.println("\nPackage-private dependencies:-");
+            for (String pkgname : splitPackages) {
+                for (Klass k : Klass.getAllClasses()) {
+                    if (k.getPackageName().equals(pkgname)) {
+                        Module m = k.getModule();
+                        // check if this klass references a package-private
+                        // class that is in a different module
+                        for (Klass other : k.getReferencedClasses()) {
+                            if (other.getModule() != m &&
+                                    !other.isPublic() &&
+                                    other.getPackageName().equals(pkgname)) {
+                                String from = k.getClassName() + " (" + m + ")";
+                                writer.format("%-60s -> %s (%s)\n", from, other, other.getModule());
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            writer.close();
+        }
+
+    }
+
+    private static String resolve(File dir, String mname, String suffix) {
+        File f = new File(dir, mname + "." + suffix);
+        return f.toString();
+
+    }
+
+    private static void usage() {
+        System.out.println("Usage: ClassAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-cpath   <classpath> where classes and jars will be parsed");
+        System.out.println("\t         Either -jdkhome or -cpath option can be used.");
+        System.out.println("\t-config  <module config file>");
+        System.out.println("\t         This option can be repeated for multiple module config files");
+        System.out.println("\t-output  <output dir>");
+        System.out.println("\t-nomerge specify not to merge modules");
+        System.out.println("\t-showdynamic show dynamic dependencies in the reports");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassFileParser.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,629 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Type.*;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import static com.sun.tools.classfile.AccessFlags.*;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ClassFileParser {
+
+    final Klass this_klass;
+    final ClassFile classfile;
+    final ConstantPoolParser constantPoolParser;
+    final AnnotationParser annotationParser;
+    final CodeAttributeParser codeAttributeParser;
+    private final boolean buildDeps;
+
+    protected ClassFileParser(InputStream in, long size, boolean buildDeps) throws IOException {
+        try {
+            this.classfile = ClassFile.read(in);
+            this.this_klass = getKlass(this.classfile);
+            this.buildDeps = buildDeps;
+            this.constantPoolParser = new ConstantPoolParser(this);
+            this.annotationParser = new AnnotationParser(this);
+            this.codeAttributeParser = new CodeAttributeParser(this);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private Klass getKlass(ClassFile cf) throws ConstantPoolException {
+        Klass k = Klass.getKlass(cf.getName());
+        k.setAccessFlags(cf.access_flags.flags);
+        k.setFileSize(cf.byteLength());
+        return k;
+    }
+
+    public static ClassFileParser newParser(InputStream in, long size, boolean buildDeps) throws IOException {
+        return new ClassFileParser(in, size, buildDeps);
+    }
+
+    public static ClassFileParser newParser(String classPathname, boolean buildDeps) throws IOException {
+        return newParser(new File(classPathname), buildDeps);
+    }
+
+    public static ClassFileParser newParser(File f, boolean buildDeps) throws IOException {
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
+        try {
+            return newParser(in, f.length(), buildDeps);
+        } finally {
+            in.close();
+        }
+    }
+
+    public void parseDependency(boolean publicAPIs) throws IOException {
+        if (publicAPIs && !classfile.access_flags.is(ACC_PUBLIC)) {
+            // process public APIs only
+            return;
+        }
+
+        parseClassInfo();
+        if (!publicAPIs) {
+            // parse all references in the classfile
+            constantPoolParser.parseDependency();
+        }
+        parseMethods(publicAPIs);
+        parseFields(publicAPIs);
+    }
+
+    void parseClassInfo() throws IOException {
+        ConstantPool cpool = classfile.constant_pool;
+        try {
+            Signature_attribute sigAttr = (Signature_attribute) classfile.attributes.get(Attribute.Signature);
+            if (sigAttr == null) {
+                // use info from class file header
+                if (classfile.isClass() && classfile.super_class != 0) {
+                    String sn = classfile.getSuperclassName();
+                    addExtends(sn);
+                }
+                for (int i = 0; i < classfile.interfaces.length; i++) {
+                    String interf = classfile.getInterfaceName(i);
+                    if (classfile.isClass()) {
+                        addImplements(interf);
+                    } else {
+                        addExtends(interf);
+                    }
+                }
+            } else {
+                Type t = sigAttr.getParsedSignature().getType(cpool);
+                // The signature parser cannot disambiguate between a
+                // FieldType and a ClassSignatureType that only contains a superclass type.
+                if (t instanceof Type.ClassSigType) {
+                    Type.ClassSigType cst = Type.ClassSigType.class.cast(t);
+                    if (cst.superclassType != null) {
+                        for (Klass k : getKlass(cst.superclassType)) {
+                            addExtends(k);
+                        }
+                    }
+                    if (cst.superinterfaceTypes != null) {
+                        for (Type t1 : cst.superinterfaceTypes) {
+                            for (Klass k : getKlass(t1)) {
+                                addImplements(k);
+                            }
+                        }
+                    }
+                } else {
+                    for (Klass k : getKlass(t)) {
+                        addExtends(k);
+                    }
+                }
+            }
+            // parse attributes
+            annotationParser.parseAttributes(classfile.attributes);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private void parseFields(boolean publicAPIs) throws IOException {
+        ConstantPool cpool = classfile.constant_pool;
+        for (Field f : classfile.fields) {
+            try {
+                AccessFlags flags = f.access_flags;
+                if (publicAPIs && !flags.is(ACC_PUBLIC) && !flags.is(ACC_PROTECTED)) {
+                    continue;
+                }
+                String fieldname = f.getName(cpool);
+                Signature_attribute sigAttr = (Signature_attribute) f.attributes.get(Attribute.Signature);
+
+                if (sigAttr == null) {
+                    Set<Klass> types = parseDescriptor(f.descriptor);
+                    String info = getFlag(flags) + " " + f.descriptor.getFieldType(cpool) + " " + fieldname;
+                    addFieldTypes(types, info, flags);
+                } else {
+                    Type t = sigAttr.getParsedSignature().getType(cpool);
+                    String info = getFlag(flags) + " " + t + " " + fieldname;
+                    addFieldTypes(getKlass(t), info, flags);
+                }
+                // parse attributes
+                annotationParser.parseAttributes(f.attributes);
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            } catch (InvalidDescriptor ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    private void parseMethods(boolean publicAPIs) {
+        for (Method m : classfile.methods) {
+            if (publicAPIs && !m.access_flags.is(ACC_PUBLIC) && !m.access_flags.is(ACC_PROTECTED)) {
+                // only interest in the API level
+                return;
+            }
+
+            parseMethod(m);
+        }
+    }
+
+    String checkClassName(String classname) {
+        int i = 0;
+        while (i < classname.length()) {
+            switch (classname.charAt(i)) {
+                case 'Z':
+                case 'B':
+                case 'C':
+                case 'S':
+                case 'I':
+                case 'J':
+                case 'F':
+                case 'D':
+                    return "";
+                case 'L':
+                    if (!classname.endsWith(";")) {
+                        throw new RuntimeException("Invalid classname " + classname);
+                    }
+                    return classname.substring(i + 1, classname.length() - 1);
+                case '[':
+                    i++;
+                    break;
+                default:
+                    if (classname.endsWith(";")) {
+                        throw new RuntimeException("Invalid classname " + classname);
+                    }
+                    return classname;
+
+            }
+        }
+        throw new RuntimeException("Invalid classname " + classname);
+    }
+
+    private void addExtends(String classname) throws IOException {
+        if (!buildDeps) {
+            return;
+        }
+
+        addExtends(Klass.getKlass(classname));
+    }
+
+    private void addExtends(Klass k) {
+        if (!buildDeps) {
+            return;
+        }
+
+        ResolutionInfo resInfo = ResolutionInfo.resolvedExtends(this_klass, k);
+        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));
+        this_klass.addDep(k, resInfo);
+        k.addReferrer(this_klass, resInfo);
+    }
+
+    private void addImplements(String classname) throws IOException {
+        if (!buildDeps) {
+            return;
+        }
+
+        addImplements(Klass.getKlass(classname));
+    }
+
+    private void addImplements(Klass k) {
+        if (!buildDeps) {
+            return;
+        }
+
+        ResolutionInfo resInfo = ResolutionInfo.resolvedImplements(this_klass, k);
+        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));
+
+        this_klass.addDep(k, resInfo);
+
+        k.addReferrer(this_klass, resInfo);
+    }
+
+    private Set<Klass> getKlass(Type type) throws IOException {
+        Set<Klass> refTypes = new TreeSet<Klass>();
+        if (!buildDeps) {
+            return refTypes;
+        }
+
+        type.accept(typevisitor, refTypes);
+        return refTypes;
+    }
+    private Type.Visitor<Void, Set<Klass>> typevisitor = new Type.Visitor<Void, Set<Klass>>() {
+
+        public Void visitSimpleType(SimpleType type, Set<Klass> klasses) {
+            // nop
+            return null;
+        }
+
+        public Void visitArrayType(ArrayType type, Set<Klass> klasses) {
+            try {
+                klasses.addAll(getKlass(type.elemType));
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+            return null;
+
+        }
+
+        public Void visitMethodType(MethodType type, Set<Klass> klasses) {
+            throw new InternalError("Unexpected type " + type);
+        }
+
+        public Void visitClassSigType(ClassSigType type, Set<Klass> klasses) {
+            try {
+                if (type.superclassType != null) {
+                    klasses.addAll(getKlass(type.superclassType));
+                }
+                if (type.superinterfaceTypes != null) {
+                    for (Type t : type.superinterfaceTypes) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+                if (type.typeParamTypes != null) {
+                    for (Type t : type.typeParamTypes) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+            return null;
+        }
+
+        public Void visitClassType(ClassType type, Set<Klass> klasses) {
+            klasses.add(Klass.getKlass(type.getBinaryName()));
+            if (type.typeArgs != null) {
+                for (Type t : type.typeArgs) {
+                    try {
+                        klasses.addAll(getKlass(t));
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+            return null;
+
+        }
+
+        public Void visitTypeParamType(TypeParamType type, Set<Klass> klasses) {
+            try {
+                if (type.classBound != null) {
+                    klasses.addAll(getKlass(type.classBound));
+                }
+                if (type.interfaceBounds != null) {
+                    for (Type t : type.interfaceBounds) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+
+            return null;
+
+        }
+
+        public Void visitWildcardType(WildcardType type, Set<Klass> klasses) {
+            if (type.boundType != null) {
+                try {
+                    klasses.addAll(getKlass(type.boundType));
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+            return null;
+
+        }
+    };
+
+    private void printMethod(Method m) {
+        try {
+            System.out.println("parsing " + m.getName(classfile.constant_pool) + "(" +
+                    m.descriptor.getParameterTypes(classfile.constant_pool) + ") return type " +
+                    m.descriptor.getReturnType(classfile.constant_pool));
+
+        } catch (ConstantPoolException ex) {
+        } catch (InvalidDescriptor ex) {
+        }
+    }
+
+    private static StringBuilder appendWord(StringBuilder sb, String word) {
+        if (sb.length() > 0) {
+            sb.append(" ");
+        }
+        sb.append(word);
+        return sb;
+    }
+
+    private static String getFlag(AccessFlags flags) {
+        StringBuilder modifier = new StringBuilder();
+        if (flags.is(ACC_PUBLIC)) {
+            modifier.append("public");
+        }
+        if (flags.is(ACC_PRIVATE)) {
+            modifier.append("private");
+        }
+        if (flags.is(ACC_PROTECTED)) {
+            modifier.append("protected");
+        }
+        if (flags.is(ACC_STATIC)) {
+            appendWord(modifier, "static");
+        }
+        if (flags.is(ACC_FINAL)) {
+            appendWord(modifier, "final");
+        }
+        if (flags.is(ACC_SYNCHRONIZED)) {
+            // return "synchronized";
+        }
+        if (flags.is(0x80)) {
+            // return (t == Type.Field ? "transient" : null);
+            // return "transient";
+        }
+        if (flags.is(ACC_VOLATILE)) {
+            // return "volatile";
+        }
+        if (flags.is(ACC_NATIVE)) {
+            // return "native";
+        }
+        if (flags.is(ACC_ABSTRACT)) {
+            appendWord(modifier, "abstract");
+        }
+        if (flags.is(ACC_STRICT)) {
+            // return "strictfp";
+        }
+        if (flags.is(ACC_MODULE)) {
+            appendWord(modifier, "module");
+        }
+        return modifier.toString();
+    }
+
+    private Klass.Method toKlassMethod(Method m, Descriptor d) {
+        try {
+            ConstantPool cpool = classfile.constant_pool;
+            String methodname = m.getName(cpool);
+            StringBuilder sb = new StringBuilder();
+            sb.append(getFlag(m.access_flags));
+            if (methodname.equals("<init>")) {
+                String s = this_klass.getBasename() + d.getParameterTypes(cpool);
+                appendWord(sb, s);
+            } else if (methodname.equals("<clinit>")) {
+                // <clinit>
+                appendWord(sb, methodname);
+            } else {
+                String s = d.getReturnType(cpool) + " " + methodname + d.getParameterTypes(cpool);
+                appendWord(sb, s);
+            }
+            String signature = sb.toString().replace('/', '.');
+            return this_klass.getMethod(methodname, signature);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        } catch (InvalidDescriptor ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    Klass.Method parseMethod(Method m) {
+        AccessFlags flags = m.access_flags;
+        Descriptor d;
+        List<? extends Type> methodExceptions = null;
+        try {
+            ConstantPool cpool = classfile.constant_pool;
+            Klass.Method kmethod;
+            Signature_attribute sigAttr = (Signature_attribute) m.attributes.get(Attribute.Signature);
+            if (sigAttr == null) {
+                d = m.descriptor;
+                Set<Klass> types = parseDescriptor(d);
+
+                kmethod = toKlassMethod(m, d);
+                addMethodTypes(types, kmethod, flags);
+            } else {
+                Type.MethodType methodType;
+                Signature methodSig = sigAttr.getParsedSignature();
+                d = methodSig;
+                try {
+                    kmethod = toKlassMethod(m, d);
+                    methodType = (Type.MethodType) methodSig.getType(cpool);
+                    addMethodTypes(getKlass(methodType.returnType), kmethod, flags);
+                    if (methodType.paramTypes != null) {
+                        for (Type t : methodType.paramTypes) {
+                            addMethodTypes(getKlass(t), kmethod, flags);
+                        }
+                    }
+                    if (methodType.typeParamTypes != null) {
+                        for (Type t : methodType.typeParamTypes) {
+                            addMethodTypes(getKlass(t), kmethod, flags);
+                        }
+                    }
+
+                    methodExceptions = methodType.throwsTypes;
+                    if (methodExceptions != null) {
+                        if (methodExceptions.size() == 0) {
+                            methodExceptions = null;
+                        } else {
+                            for (Type t : methodExceptions) {
+                                addCheckedExceptionTypes(getKlass(t), kmethod, flags);
+                            }
+                        }
+                    }
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            Attribute e_attr = m.attributes.get(Attribute.Exceptions);
+            if (e_attr != null && methodExceptions == null) {
+                // if there are generic exceptions, there must be erased exceptions
+                if (e_attr instanceof Exceptions_attribute) {
+                    Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
+                    for (int i = 0; i < exceptions.number_of_exceptions; i++) {
+                        String classname = checkClassName(exceptions.getException(i, classfile.constant_pool));
+                        if (classname.length() > 0 && buildDeps) {
+                            Klass to = Klass.getKlass(classname);
+                            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, kmethod);
+                            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+                            this_klass.addDep(to, resInfo);
+                            to.addReferrer(this_klass, resInfo);
+                        }
+                    }
+                } else {
+                    throw new RuntimeException("Invalid attribute: " + e_attr);
+                }
+            }
+
+            Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
+            if (c_attr != null) {
+                codeAttributeParser.parse(c_attr, kmethod);
+            }
+            kmethod.isAbstract = classfile.access_flags.is(ACC_ABSTRACT);
+            kmethod.setCodeLength(m.byteLength());
+
+            // parse annotation attributes
+            annotationParser.parseAttributes(m.attributes, kmethod);
+            return kmethod;
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private void addFieldTypes(Set<Klass> types, String info, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedField(this_klass, to, info);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private void addReferencedTypes(Method m, Descriptor d, AccessFlags flags) {
+        Set<Klass> types = parseDescriptor(d);
+
+        Klass.Method method = toKlassMethod(m, d);
+        addMethodTypes(types, method, flags);
+    }
+
+    private void addMethodTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedMethodSignature(this_klass, to, method);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private void addCheckedExceptionTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, method);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private Set<Klass> parseDescriptor(Descriptor d) {
+        Set<Klass> types = new TreeSet<Klass>();
+        try {
+            String desc = d.getValue(classfile.constant_pool);
+            int p = 0;
+            while (p < desc.length()) {
+                String type;
+                char ch;
+                switch (ch = desc.charAt(p++)) {
+                    case '(':
+                    case ')':
+                    case '[':
+                    case 'B':
+                    case 'C':
+                    case 'D':
+                    case 'F':
+                    case 'I':
+                    case 'J':
+                    case 'S':
+                    case 'Z':
+                    case 'V':
+                        continue;
+                    case 'L':
+                        int sep = desc.indexOf(';', p);
+                        if (sep == -1) {
+                            throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
+                        }
+                        type = checkClassName(desc.substring(p, sep));
+                        p = sep + 1;
+                        break;
+                    default:
+                        throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
+                }
+
+                if (!type.isEmpty() && buildDeps) {
+                    Klass to = Klass.getKlass(type);
+                    types.add(to);
+
+                }
+            }
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+        return types;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassPath.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ *
+ * @author mchung
+ */
+public class ClassPath {
+
+    public class FileInfo {
+
+        File file;
+        JarFile jarfile;
+        int classCount;
+        long filesize;
+
+        FileInfo(File f) throws IOException {
+            this.file = f;
+            this.classCount = 0;
+            if (file.getName().endsWith(".jar")) {
+                this.filesize = file.length();
+                jarfile = new JarFile(f);
+            }
+        }
+
+        File getFile() {
+            return file;
+        }
+
+        JarFile getJarFile() {
+            return jarfile;
+        }
+
+        String getName() throws IOException {
+            return file.getCanonicalPath();
+        }
+    }
+    private List<FileInfo> fileList = new ArrayList<FileInfo>();
+    private static ClassPath instance = new ClassPath();
+
+    static List<FileInfo> getFileInfos() {
+        return instance.fileList;
+    }
+
+    static ClassPath setJDKHome(String jdkhome) throws IOException {
+        List<File> files = new ArrayList<File>();
+        File jre = new File(jdkhome, "jre");
+        File lib = new File(jdkhome, "lib");
+        if (jre.exists() && jre.isDirectory()) {
+            listFiles(new File(jre, "lib"), ".jar", files);
+        } else if (lib.exists() && lib.isDirectory()) {
+            // either a JRE or a jdk build image
+            listFiles(lib, ".jar", files);
+
+            File classes = new File(jdkhome, "classes");
+            if (classes.exists() && classes.isDirectory()) {
+                // jdk build outputdir
+                instance.add(classes);
+            }
+        } else {
+            throw new RuntimeException("\"" + jdkhome + "\" not a JDK home");
+        }
+
+        for (File f : files) {
+            instance.add(f);
+        }
+        return instance;
+    }
+
+    static ClassPath setClassPath(String path) throws IOException {
+        if (path.endsWith(".class")) {
+            // one class file
+            File f = new File(path);
+            if (!f.exists()) {
+                throw new RuntimeException("Classfile \"" + f + "\" doesn't exist");
+            }
+
+            instance.add(f);
+        } else {
+            List<File> jarFiles = new ArrayList<File>();
+            String[] locs = path.split(File.pathSeparator);
+            for (String p : locs) {
+                File f = new File(p);
+                if (!f.exists()) {
+                    throw new RuntimeException("\"" + f + "\" doesn't exist");
+                }
+
+                if (f.isDirectory()) {
+                    instance.add(f);  // add the directory to look up .class files
+                    listFiles(f, ".jar", jarFiles);
+                } else if (p.endsWith(".jar")) {
+                    // jar files
+                    jarFiles.add(f);
+                } else {
+                    throw new RuntimeException("Invalid file \"" + f);
+                }
+            }
+            // add jarFiles if any
+            for (File f : jarFiles) {
+                instance.add(f);
+            }
+        }
+
+        return instance;
+    }
+
+    private void add(File f) throws IOException {
+        fileList.add(new FileInfo(f));
+    }
+
+    public static InputStream open(String pathname) throws IOException {
+        for (FileInfo fi : instance.fileList) {
+            if (fi.getName().endsWith(".jar")) {
+                String path = pathname.replace(File.separatorChar, '/');
+                JarEntry e = fi.jarfile.getJarEntry(path);
+                if (e != null) {
+                    return fi.jarfile.getInputStream(e);
+                }
+            } else if (fi.getFile().isDirectory()) {
+                File f = new File(fi.getFile(), pathname);
+                if (f.exists()) {
+                    return new FileInputStream(f);
+                }
+            } else if (fi.file.isFile()) {
+                if (fi.getName().endsWith(File.separator + pathname)) {
+                    return new FileInputStream(fi.file);
+                }
+            }
+        }
+        return null;
+    }
+
+    static ClassFileParser parserForClass(String classname) throws IOException {
+        String pathname = classname.replace('.', File.separatorChar) + ".class";
+
+        ClassFileParser cfparser = null;
+        for (FileInfo fi : instance.fileList) {
+            if (fi.getName().endsWith(".class")) {
+                if (fi.getName().endsWith(File.separator + pathname)) {
+                    cfparser = ClassFileParser.newParser(fi.getFile(), true);
+                    break;
+                }
+            } else if (fi.getName().endsWith(".jar")) {
+                JarEntry e = fi.jarfile.getJarEntry(classname.replace('.', '/') + ".class");
+                if (e != null) {
+                    cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true);
+                    break;
+                }
+            } else if (fi.getFile().isDirectory()) {
+                File f = new File(fi.getFile(), pathname);
+                if (f.exists()) {
+                    cfparser = ClassFileParser.newParser(f, true);
+                    break;
+                }
+            }
+        }
+        return cfparser;
+    }
+
+    public static void parseAllClassFiles() throws IOException {
+        instance.parseFiles();
+    }
+
+    private void parseFiles() throws IOException {
+        Set<Klass> classes = new HashSet<Klass>();
+
+        int count = 0;
+        for (FileInfo fi : fileList) {
+            // filter out public generated classes (i.e. not public API)
+            // javax.management.remote.rmi._RMIConnectionImpl_Tie
+            // javax.management.remote.rmi._RMIServerImpl_Tie
+            if (fi.getName().endsWith(".class")) {
+                parseClass(fi);
+            } else if (fi.getName().endsWith(".jar")) {
+                Enumeration<JarEntry> entries = fi.jarfile.entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry e = entries.nextElement();
+                    if (e.getName().endsWith(".class")) {
+                        ClassFileParser cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true);
+                        cfparser.parseDependency(false);
+                        fi.classCount++;
+                    } else if (!e.isDirectory() && ResourceFile.isResource(e.getName())) {
+                        ResourceFile.addResource(e.getName(), fi.jarfile.getInputStream(e));
+                    }
+                }
+            } else if (fi.getFile().isDirectory()) {
+                List<File> files = new ArrayList<File>();
+                listFiles(fi.getFile(), "", files);
+                for (File f : files) {
+                    if (f.getName().endsWith(".class")) {
+                        parseClass(fi, f);
+                    } else if (!f.isDirectory() && ResourceFile.isResource(f.getCanonicalPath())) {
+                        String pathname = f.getCanonicalPath();
+                        String dir = fi.getName();
+                        if (!pathname.startsWith(dir)) {
+                            throw new RuntimeException("Incorrect pathname " + pathname);
+                        }
+                        String name = pathname.substring(dir.length() + 1, pathname.length());
+                        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
+                        try {
+                            ResourceFile.addResource(name, in);
+                        } finally {
+                            in.close();
+                        }
+                    }
+                }
+            } else {
+                // should not reach here
+                throw new RuntimeException("Unexpected class path: " + fi.getFile());
+            }
+        }
+    }
+
+    private void parseClass(FileInfo fi) throws IOException {
+        parseClass(fi, fi.getFile());
+    }
+
+    private void parseClass(FileInfo fi, File f) throws IOException {
+        ClassFileParser cfparser = ClassFileParser.newParser(f, true);
+        cfparser.parseDependency(false);
+        fi.classCount++;
+        // need to update the filesize for this directory
+        fi.filesize += fi.getFile().length();
+
+    }
+
+    public static void listFiles(File path, String suffix, List<File> result) {
+        if (path.isDirectory()) {
+            File[] children = path.listFiles();
+            for (File c : children) {
+                listFiles(c, suffix, result);
+            }
+
+        } else {
+            if (suffix.isEmpty() || path.getName().endsWith(suffix)) {
+                result.add(path);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CodeAttributeParser.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.classanalyzer.Klass.Method;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Instruction.*;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class CodeAttributeParser {
+    private final ClassFileParser cfparser;
+    private final ConstantPool cpool;
+    private final ConstantPoolParser constantPoolParser;
+
+
+    static final Map<String, Set<Method>> runtimeReferences =
+            new HashMap<String, Set<Method>>();
+
+
+    CodeAttributeParser(ClassFileParser parser) {
+        this.cfparser = parser;
+        this.cpool = cfparser.classfile.constant_pool;
+        this.constantPoolParser = cfparser.constantPoolParser;
+    }
+
+    static boolean parseCodeAttribute = false; // by default don't parse code attribute
+    static void setParseCodeAttribute(boolean newValue) {
+        parseCodeAttribute = newValue;
+    }
+
+    void parse(Code_attribute attr, Klass.Method method) {
+        if (!parseCodeAttribute) {
+            return;
+        }
+
+        for (Instruction instr : attr.getInstructions()) {
+            try {
+                instr.accept(instructionVisitor, method);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new RuntimeException("error at or after byte " + instr.getPC());
+            }
+
+        }
+
+        if (attr.exception_table_langth > 0) {
+            for (int i = 0; i <
+                    attr.exception_table.length; i++) {
+                Code_attribute.Exception_data handler = attr.exception_table[i];
+                int catch_type = handler.catch_type;
+                if (catch_type > 0) {
+                    addMethodReference(catch_type, method);
+                }
+
+            }
+        }
+
+    }
+
+
+    private void addMethodReference(int index, Klass.Method m) {
+        String method = constantPoolParser.getMethodName(index);
+
+        if (method != null &&
+               (method.equals("java.lang.Class.forName") ||
+                method.equals("java.lang.Class.loadClass") ||
+                method.startsWith("java.util.ServiceLoader.load") ||
+                method.equals("sun.misc.Service.providers"))) {
+            Set<Method> refs = runtimeReferences.get(method);
+            if (refs == null) {
+                refs = new TreeSet<Method>();
+                runtimeReferences.put(method, refs);
+            }
+            refs.add(m);
+        }
+    }
+
+    Instruction.KindVisitor<Void, Klass.Method> instructionVisitor =
+            new Instruction.KindVisitor<Void, Klass.Method>() {
+
+                public Void visitNoOperands(Instruction instr, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitBranch(Instruction instr, int offset, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) {
+                    addMethodReference(index, m);
+                    return null;
+                }
+
+                public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) {
+                    addMethodReference(index, m);
+                    return null;
+                }
+
+                public Void visitLocal(Instruction instr, int index, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitValue(Instruction instr, int value, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitUnknown(Instruction instr, Klass.Method m) {
+                    return null;
+                }
+            };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolAnalyzer.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ConstantPoolAnalyzer {
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            }
+        }
+        if (jdkhome == null) {
+            usage();
+        }
+        ClassPath.setJDKHome(jdkhome);
+        ClassPath.parseAllClassFiles();
+    }
+
+    private static void usage() {
+        System.out.println("Usage: ConstantPoolAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-cpath <classpath> where classes and jars will be parsed");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolParser.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ConstantPoolParser {
+
+    private final ClassFileParser cfparser;
+    private final StringValueVisitor visitor;
+    private final ConstantPool cpool;
+
+    ConstantPoolParser(ClassFileParser parser) {
+        this.cfparser = parser;
+        this.cpool = cfparser.classfile.constant_pool;
+        this.visitor = new StringValueVisitor();
+    }
+
+    public String stringValue(CPInfo cpInfo) {
+        return visitor.visit(cpInfo);
+    }
+
+    public String stringValue(int constant_pool_index) {
+        try {
+            return stringValue(cpool.get(constant_pool_index));
+        } catch (ConstantPool.InvalidIndex e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void parseDependency() {
+        ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer, Void>() {
+
+            public Integer visitClass(CONSTANT_Class_info info, Void p) {
+                try {
+                    String classname = cfparser.checkClassName(info.getName());
+                    if (classname.isEmpty()) {
+                        return 1;
+                    }
+
+                    Klass from = cfparser.this_klass;
+                    Klass to = Klass.getKlass(classname);
+                    ResolutionInfo resInfo = ResolutionInfo.resolvedConstantPool(from, to, info.name_index);
+
+                    from.addDep(to, resInfo);
+                    to.addReferrer(from, resInfo);
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+                return 1;
+            }
+
+            public Integer visitDouble(CONSTANT_Double_info info, Void p) {
+                // skip
+                return 2;
+            }
+
+            public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitFloat(CONSTANT_Float_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitLong(CONSTANT_Long_info info, Void p) {
+                // skip
+                return 2;
+            }
+
+            public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitString(CONSTANT_String_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
+                // skip
+                return 1;
+            }
+        };
+        int cpx = 1;
+        while (cpx < cpool.size()) {
+            try {
+                CPInfo cpInfo = cpool.get(cpx);
+                cpx += cpInfo.accept(v, null);
+            } catch (ConstantPool.InvalidIndex ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    int getTag(int index) {
+        try {
+            return cpool.get(index).getTag();
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    String getDescriptor(int index) {
+        CPInfo cpInfo;
+        try {
+            cpInfo = cpool.get(index);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        int tag = cpInfo.getTag();
+        switch (tag) {
+            case CONSTANT_Methodref:
+            case CONSTANT_InterfaceMethodref:
+            case CONSTANT_Fieldref:
+                // simplify references within this class
+                CPRefInfo ref = (CPRefInfo) cpInfo;
+                try {
+                    return ref.getNameAndTypeInfo().getType();
+                } catch (ConstantPoolException ex) {
+                }
+        }
+        return stringValue(cpInfo);
+    }
+
+    String getMethodName(int index) {
+        try {
+            CPInfo cpInfo = cpool.get(index);
+            if (cpInfo.getTag() == CONSTANT_Methodref ||
+                    cpInfo.getTag() == CONSTANT_InterfaceMethodref) {
+
+                // simplify references within this class
+                CPRefInfo ref = (CPRefInfo) cpInfo;
+                String classname;
+                if (ref.class_index == cfparser.classfile.this_class) {
+                    classname = cfparser.this_klass.getClassName();
+                } else {
+                    classname = cfparser.checkClassName(ref.getClassName()).replace('/', '.');
+                }
+                String methodname = ref.getNameAndTypeInfo().getName();
+                return classname + "." + methodname;
+            } else {
+                return null;
+            }
+        } catch (InvalidIndex ex) {
+            throw new RuntimeException(ex);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+
+    }
+
+    class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
+
+        public StringValueVisitor() {
+        }
+
+        public String visit(CPInfo info) {
+            return info.accept(this, null);
+        }
+
+        public String visitClass(CONSTANT_Class_info info, Void p) {
+            return getCheckedName(info);
+        }
+
+        String getCheckedName(CONSTANT_Class_info info) {
+            try {
+                return checkName(info.getName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitDouble(CONSTANT_Double_info info, Void p) {
+            return info.value + "d";
+        }
+
+        public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitFloat(CONSTANT_Float_info info, Void p) {
+            return info.value + "f";
+        }
+
+        public String visitInteger(CONSTANT_Integer_info info, Void p) {
+            return String.valueOf(info.value);
+        }
+
+        public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitLong(CONSTANT_Long_info info, Void p) {
+            return info.value + "l";
+        }
+
+        public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+            return getCheckedName(info) + ":" + getType(info);
+        }
+
+        String getCheckedName(CONSTANT_NameAndType_info info) {
+            try {
+                return checkName(info.getName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        String getType(CONSTANT_NameAndType_info info) {
+            try {
+                return info.getType();
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitString(CONSTANT_String_info info, Void p) {
+            try {
+                int string_index = info.string_index;
+                return cpool.getUTF8Info(string_index).accept(this, p);
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
+            String s = info.value;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.length(); i++) {
+                char c = s.charAt(i);
+                switch (c) {
+                    case '\t':
+                        sb.append('\\').append('t');
+                        break;
+                    case '\n':
+                        sb.append('\\').append('n');
+                        break;
+                    case '\r':
+                        sb.append('\\').append('r');
+                        break;
+                    case '\"':
+                        sb.append('\\').append('\"');
+                        break;
+                    default:
+                        sb.append(c);
+                }
+            }
+            return sb.toString();
+        }
+
+        String visitRef(CPRefInfo info, Void p) {
+            String cn = getCheckedClassName(info);
+            String nat;
+            try {
+                nat = info.getNameAndTypeInfo().accept(this, p);
+            } catch (ConstantPoolException e) {
+                nat = e.getMessage();
+            }
+            return cn + "." + nat;
+        }
+
+        String getCheckedClassName(CPRefInfo info) {
+            try {
+                return checkName(info.getClassName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+    /* If name is a valid binary name, return it; otherwise quote it. */
+
+    private static String checkName(String name) {
+        if (name == null) {
+            return "null";
+        }
+
+        int len = name.length();
+        if (len == 0) {
+            return "\"\"";
+        }
+
+        int cc = '/';
+        int cp;
+        for (int k = 0; k < len; k += Character.charCount(cp)) {
+            cp = name.codePointAt(k);
+            if ((cc == '/' && !Character.isJavaIdentifierStart(cp)) || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
+                return "\"" + name + "\"";
+            }
+            cc = cp;
+        }
+        return name;
+    }
+
+    String tagName(int index) {
+        try {
+            int tag = cpool.get(index).getTag();
+            switch (tag) {
+                case CONSTANT_Utf8:
+                    return "Utf8";
+                case CONSTANT_Integer:
+                    return "int";
+                case CONSTANT_Float:
+                    return "float";
+                case CONSTANT_Long:
+                    return "long";
+                case CONSTANT_Double:
+                    return "double";
+                case CONSTANT_Class:
+                    return "class";
+                case CONSTANT_String:
+                    return "String";
+                case CONSTANT_Fieldref:
+                    return "Field";
+                case CONSTANT_Methodref:
+                    return "Method";
+                case CONSTANT_InterfaceMethodref:
+                    return "InterfaceMethod";
+                case CONSTANT_NameAndType:
+                    return "NameAndType";
+                default:
+                    return "(unknown tag)";
+            }
+        } catch (InvalidIndex e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/DependencyConfig.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+
+/**
+ * Config file specifying additional dependency
+ * Each line consists of:
+ * <tag> <classname> -> <value>
+ * where <tag> can be:
+ *    @ClassForName and <value> is its dependency
+ *    @Provider and <value> is the service name
+ *    @Providers and <value> is the list of the service names
+ *
+ * @author Mandy Chung
+ */
+public class DependencyConfig {
+    private DependencyConfig() {
+    }
+
+    static void parse(List<String> configs) throws IOException {
+        for (String s : configs) {
+            parse(s);
+        }
+    }
+
+    private static void parse(String config) throws IOException {
+        // parse configuration file
+        FileInputStream in = new FileInputStream(config);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            int lineNumber = 0;
+            String type = null;
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+                line = line.trim();
+                if (line.length() == 0 || line.charAt(0) == '#') {
+                    continue;
+                }
+                if (line.charAt(0) == '@') {
+                    if (AnnotatedDependency.isValidType(line)) {
+                        type = line;
+                        continue;
+                    } else {
+                        throw new RuntimeException(config + ", line " +
+                            lineNumber + ", invalid annotation type.");
+                    }
+                }
+                String[] s = line.split("\\s+");
+                if (s.length < 3 || !s[1].equals("->")) {
+                    throw new RuntimeException(config + ", line " +
+                            lineNumber + ", is malformed");
+                }
+                String classname = s[0].trim();
+                String value = s[2].trim();
+
+                Klass k = Klass.findKlass(classname);
+                if (k == null) {
+                    // System.out.println("Warning: " + classname + " cannot be found");
+                    continue;
+                }
+                AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, value, k);
+                if (dep == null) {
+                    throw new RuntimeException(config + ", line " +
+                            lineNumber + ", is malformed. Fail to construct the dependency.");
+                }
+            }
+
+        } finally {
+            in.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Klass.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.sun.tools.classfile.AccessFlags;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class Klass implements Comparable<Klass> {
+    private final String classname;
+    private final String packagename;
+    private Module module;
+    private boolean isJavaLangObject;
+    private String[] paths;
+    private Map<String, Set<Method>> methods;
+    private AccessFlags accessFlags;
+    private long filesize;
+
+    private SortedMap<Klass, Set<ResolutionInfo>> deps;
+    private SortedMap<Klass, Set<ResolutionInfo>> referrers;
+    private List<AnnotatedDependency> annotatedDeps;
+    private Set<String> classForNameRefs;
+
+    private Klass(String classname) {
+        this.classname = classname;
+        this.paths = classname.replace('.', '/').split("/");
+        this.isJavaLangObject = classname.equals("java.lang.Object");
+        this.deps = new TreeMap<Klass, Set<ResolutionInfo>>();
+        this.referrers = new TreeMap<Klass, Set<ResolutionInfo>>();
+        this.methods = new HashMap<String, Set<Method>>();
+        this.annotatedDeps = new ArrayList<AnnotatedDependency>();
+        this.classForNameRefs = new TreeSet<String>();
+
+        int pos = classname.lastIndexOf('.');
+        this.packagename = (pos > 0) ? classname.substring(0, pos) : "<unnamed>";
+    }
+
+    String getBasename() {
+        return paths[paths.length - 1];
+    }
+
+    String getClassName() {
+        return classname;
+    }
+
+    String getPackageName() {
+        return packagename;
+    }
+
+    String getClassFilePathname() {
+        StringBuilder sb = new StringBuilder(paths[0]);
+        for (int i = 1; i < paths.length; i++) {
+            String p = paths[i];
+            sb.append(File.separator).append(p);
+        }
+        return sb.append(".class").toString();
+    }
+
+    boolean isPublic() {
+        return accessFlags == null || accessFlags.is(AccessFlags.ACC_PUBLIC);
+    }
+
+    Module getModule() {
+        return module;
+    }
+
+    void setModule(Module m) {
+        if (module != null) {
+            throw new RuntimeException("Module for " + this + " already set");
+        }
+        this.module = m;
+    }
+
+    Set<Klass> getReferencedClasses() {
+        return deps.keySet();
+    }
+
+    Set<Klass> getReferencingClasses() {
+        return referrers.keySet();
+    }
+
+    void setAccessFlags(int flags) {
+        this.accessFlags = new AccessFlags(flags);
+    }
+
+    void setFileSize(long size) {
+        this.filesize = size;
+    }
+
+    long getFileSize() {
+        return this.filesize;
+    }
+
+    boolean exists() {
+        return filesize > 0;
+    }
+
+    boolean skip(Klass k) {
+        // skip if either class is a root or same class
+        return k.isJavaLangObject || this == k || k.classname.equals(classname);
+    }
+
+    void addDep(Method callee, ResolutionInfo resInfo) {
+        addDep(callee.getKlass(), resInfo);
+    }
+
+    void addDep(Klass ref, ResolutionInfo ri) {
+        if (skip(ref)) {
+            return;
+        }
+        Set<ResolutionInfo> resInfos;
+        if (!deps.containsKey(ref)) {
+            resInfos = new TreeSet<ResolutionInfo>();
+            deps.put(ref, resInfos);
+        } else {
+            resInfos = deps.get(ref);
+        }
+        resInfos.add(ri);
+    }
+
+    void addReferrer(Method caller, ResolutionInfo resInfo) {
+        addReferrer(caller.getKlass(), resInfo);
+    }
+
+    void addReferrer(Klass k, ResolutionInfo ri) {
+        if (skip(k)) {
+            return;
+        }
+        Set<ResolutionInfo> resInfos;
+        if (!referrers.containsKey(k)) {
+            resInfos = new TreeSet<ResolutionInfo>();
+            referrers.put(k, resInfos);
+        } else {
+            resInfos = referrers.get(k);
+        }
+        resInfos.add(ri);
+    }
+
+    Method getMethod(String name) {
+        return getMethod(name, "");
+    }
+
+    Method getMethod(String name, String signature) {
+        Set<Method> set;
+        if (methods.containsKey(name)) {
+            set = methods.get(name);
+        } else {
+            set = new TreeSet<Method>();
+            methods.put(name, set);
+        }
+
+        for (Method m : set) {
+            if (m.getName().equals(name) && m.getSignature().equals(signature)) {
+                return m;
+            }
+        }
+        Method m = new Method(this, name, signature);
+        set.add(m);
+        return m;
+    }
+
+    @Override
+    public String toString() {
+        return classname;
+    }
+
+    @Override
+    public int compareTo(Klass o) {
+        return classname.compareTo(o.classname);
+    }
+
+    void addAnnotatedDep(AnnotatedDependency dep) {
+        annotatedDeps.add(dep);
+    }
+
+    void addClassForNameReference(String method) {
+        classForNameRefs.add(method);
+    }
+
+    List<AnnotatedDependency> getAnnotatedDeps() {
+        return annotatedDeps;
+    }
+
+    private static Map<String, Klass> classes = new TreeMap<String, Klass>();
+    static Set<Klass> getAllClasses() {
+        return new TreeSet<Klass>(classes.values());
+    }
+
+    static Klass findKlassFromPathname(String filename) {
+        String name = filename;
+        if (filename.endsWith(".class")) {
+            name = filename.substring(0, filename.length() - 6);
+        }
+
+        // trim ".class"
+        name = name.replace('/', '.');
+        for (Klass k : classes.values()) {
+            if (name.endsWith(k.getClassName())) {
+                return k;
+            }
+        }
+        return null;
+    }
+
+    static Klass findKlass(String classname) {
+        return classes.get(classname);
+    }
+
+    static Klass getKlass(String name) {
+        Klass k;
+        String classname = name.replace('/', '.');
+        if (classname.charAt(classname.length() - 1) == ';') {
+            classname = classname.substring(0, classname.length() - 1);
+        }
+        if (classes.containsKey(classname)) {
+            k = classes.get(classname);
+        } else {
+            k = new Klass(classname);
+            classes.put(classname, k);
+        }
+        return k;
+    }
+
+    public class Method implements Comparable<Method> {
+
+        private final Klass k;
+        private final String method;
+        private final String signature;
+        private long codeLength;
+        // non-primitive types only
+        private final List<Klass> argTypes;
+        private final Klass returnType;
+        boolean isAbstract = false;
+        boolean marked = false;
+
+        public Method(Klass k, String method, String signature) {
+            this(k, method, signature, null, null);
+        }
+
+        public Method(Klass k, String method, String signature, Klass returnType, List<Klass> argTypes) {
+            this.k = k;
+            this.method = method;
+            this.signature = signature;
+            this.argTypes = argTypes;
+            this.returnType = returnType;
+            this.codeLength = 0;
+        }
+
+        public Klass getKlass() {
+            return k;
+        }
+
+        public String getName() {
+            return method;
+        }
+
+        public String getSignature() {
+            return signature;
+        }
+
+        public Klass getReturnType() {
+            return returnType;
+        }
+
+        public List<Klass> argTypes() {
+            return argTypes;
+        }
+
+        public void setCodeLength(long len) {
+            this.codeLength = len;
+        }
+
+        public long getCodeLength() {
+            return codeLength;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof Method) {
+                return compareTo((Method) o) == 0;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 71 * hash + (this.k != null ? this.k.hashCode() : 0);
+            hash = 71 * hash + (this.method != null ? this.method.hashCode() : 0);
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            if (signature.isEmpty()) {
+                return k.classname + "." + method;
+            } else {
+                return signature;
+            }
+        }
+
+        public String toHtmlString() {
+            return toString().replace("<", "&lt;").replace(">", "&gt;");
+        }
+
+        boolean isClinit() {
+            return method.equals("<clinit>");
+        }
+
+        public int compareTo(Method m) {
+            if (k == m.getKlass()) {
+                if (method.equals(m.method)) {
+                    return signature.compareTo(m.signature);
+                } else {
+                    return method.compareTo(m.method);
+                }
+            } else {
+                return k.compareTo(m.getKlass());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Module.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,693 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.classanalyzer.AnnotatedDependency.OptionalDependency;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class Module implements Comparable<Module> {
+
+    private static Map<String, Module> modules = new LinkedHashMap<String, Module>();
+
+    public static Module addModule(ModuleConfig config) {
+        String name = config.module;
+        if (modules.containsKey(name)) {
+            throw new RuntimeException("module \"" + name + "\" already exists");
+        }
+
+        Module m = new Module(config);
+        modules.put(name, m);
+        return m;
+    }
+
+    public static Module findModule(String name) {
+        return modules.get(name);
+    }
+
+    static Collection<Module> getAllModules() {
+        return Collections.unmodifiableCollection(modules.values());
+    }
+    private final String name;
+    private final ModuleConfig config;
+    private final Set<Klass> classes;
+    private final Set<ResourceFile> resources;
+    private final Set<Reference> unresolved;
+    private final Set<Dependency> dependents;
+    private final Map<String, PackageInfo> packages;
+    private final Set<Module> members;
+    private Module group;
+    private boolean isBaseModule;
+
+    private Module(ModuleConfig config) {
+        this.name = config.module;
+        this.isBaseModule = config.isBase;
+        this.classes = new TreeSet<Klass>();
+        this.resources = new TreeSet<ResourceFile>();
+        this.config = config;
+        this.unresolved = new HashSet<Reference>();
+        this.dependents = new TreeSet<Dependency>();
+        this.packages = new TreeMap<String, PackageInfo>();
+        this.members = new TreeSet<Module>();
+        this.group = this; // initialize to itself
+    }
+
+    String name() {
+        return name;
+    }
+
+    Module group() {
+        return group;
+    }
+
+    boolean isBase() {
+        return isBaseModule;
+    }
+
+    Set<Module> members() {
+        return members;
+    }
+
+    boolean contains(Klass k) {
+        return k != null && classes.contains(k);
+    }
+
+    boolean isEmpty() {
+        return classes.isEmpty() && resources.isEmpty();
+    }
+
+    /**
+     * Returns an Iterable of Dependency, only one for each dependent
+     * module of the strongest dependency (i.e.
+     * hard static > hard dynamic > optional static > optional dynamic
+     */
+    Iterable<Dependency> dependents() {
+        Map<Module, Dependency> deps = new LinkedHashMap<Module, Dependency>();
+        for (Dependency dep : dependents) {
+            Dependency d = deps.get(dep.module);
+            if (d == null || dep.compareTo(d) > 0) {
+                deps.put(dep.module, dep);
+            }
+        }
+        return deps.values();
+    }
+
+    @Override
+    public int compareTo(Module o) {
+        if (o == null) {
+            return -1;
+        }
+        return name.compareTo(o.name);
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    void addKlass(Klass k) {
+        classes.add(k);
+        k.setModule(this);
+
+        // update package statistics
+        String pkg = k.getPackageName();
+        PackageInfo pkginfo = packages.get(pkg);
+        if (pkginfo == null) {
+            pkginfo = new PackageInfo(pkg);
+            packages.put(pkg, pkginfo);
+        }
+        if (k.exists()) {
+            // only count the class that is parsed
+            pkginfo.add(k.getFileSize());
+        }
+    }
+
+    void addResource(ResourceFile res) {
+        resources.add(res);
+        res.setModule(this);
+    }
+
+    void processRootsAndReferences() {
+        // start with the root set
+        Deque<Klass> pending = new ArrayDeque<Klass>();
+        for (Klass k : Klass.getAllClasses()) {
+            if (k.getModule() != null) {
+                continue;
+            }
+            String classname = k.getClassName();
+            if (config.matchesRoot(classname) && !config.isExcluded(classname)) {
+                addKlass(k);
+                pending.add(k);
+            }
+        }
+
+        // follow all references
+        Klass k;
+        while ((k = pending.poll()) != null) {
+            if (!classes.contains(k)) {
+                addKlass(k);
+            }
+            for (Klass other : k.getReferencedClasses()) {
+                Module otherModule = other.getModule();
+                if (otherModule != null && otherModule != this) {
+                    // this module is dependent on otherModule
+                    addDependency(k, other);
+                    continue;
+                }
+
+                if (!classes.contains(other)) {
+                    if (config.isExcluded(other.getClassName())) {
+                        // reference to an excluded class
+                        unresolved.add(new Reference(k, other));
+                    } else {
+                        pending.add(other);
+                    }
+                }
+            }
+        }
+
+        // add other matching classes that don't require dependency analysis
+        for (Klass c : Klass.getAllClasses()) {
+            if (c.getModule() == null) {
+                String classname = c.getClassName();
+                if (config.matchesIncludes(classname) && !config.isExcluded(classname)) {
+                    addKlass(c);
+                    // dependencies
+                    for (Klass other : c.getReferencedClasses()) {
+                        Module otherModule = other.getModule();
+                        if (otherModule == null) {
+                            unresolved.add(new Reference(c, other));
+                        } else {
+                            if (otherModule != this) {
+                                // this module is dependent on otherModule
+                                addDependency(c, other);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+
+        // add other matching classes that don't require dependency analysis
+        for (ResourceFile res : ResourceFile.getAllResources()) {
+            if (res.getModule() == null) {
+                String name = res.getName();
+                if (config.matchesIncludes(name) && !config.isExcluded(name)) {
+                    addResource(res);
+                }
+            }
+        }
+    }
+
+    void addDependency(Klass from, Klass to) {
+        Dependency dep = new Dependency(from, to);
+        dependents.add(dep);
+    }
+
+    void fixupDependencies() {
+        // update dependencies for classes that were allocated to modules after
+        // this module was processed.
+        for (Reference ref : unresolved) {
+            Module m = ref.referree().getModule();
+            if (m == null || m != this) {
+                addDependency(ref.referrer, ref.referree);
+            }
+        }
+
+        fixupAnnotatedDependencies();
+    }
+
+    private void fixupAnnotatedDependencies() {
+        // add dependencies that this klass may depend on due to the AnnotatedDependency
+        dependents.addAll(AnnotatedDependency.getDependencies(this));
+    }
+
+    boolean isModuleDependence(Klass k) {
+        Module m = k.getModule();
+        return m == null || (!classes.contains(k) && !m.isBase());
+    }
+
+    Module getModuleDependence(Klass k) {
+        if (isModuleDependence(k)) {
+            Module m = k.getModule();
+            if (group == this && m != null) {
+                // top-level module
+                return m.group;
+            } else {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    <P> void visit(Set<Module> visited, Visitor<P> visitor, P p) {
+        if (!visited.contains(this)) {
+            visited.add(this);
+            visitor.preVisit(this, p);
+            for (Module m : members) {
+                m.visit(visited, visitor, p);
+                visitor.postVisit(this, m, p);
+            }
+        } else {
+            throw new RuntimeException("Cycle detected: module " + this.name);
+        }
+    }
+
+    void addMember(Module m) {
+        // merge class list
+        for (Klass k : m.classes) {
+            classes.add(k);
+        }
+
+        // merge resource list
+        for (ResourceFile res : m.resources) {
+            resources.add(res);
+        }
+
+        // merge the package statistics
+        for (PackageInfo pinfo : m.getPackageInfos()) {
+            String packageName = pinfo.pkgName;
+            PackageInfo pkginfo = packages.get(packageName);
+            if (pkginfo == null) {
+                pkginfo = new PackageInfo(packageName);
+                packages.put(packageName, pkginfo);
+            }
+            pkginfo.add(pinfo);
+        }
+    }
+
+    static void buildModuleMembers() {
+        // set up module member relationship
+        for (Module m : modules.values()) {
+            m.group = m; // initialize to itself
+            for (String name : m.config.members()) {
+                Module member = modules.get(name);
+                if (member == null) {
+                    throw new RuntimeException("module \"" + name + "\" doesn't exist");
+                }
+                m.members.add(member);
+            }
+        }
+
+        // set up the top-level module
+        Visitor<Module> groupSetter = new Visitor<Module>() {
+
+            public void preVisit(Module m, Module p) {
+                m.group = p;
+                if (p.isBaseModule) {
+                    // all members are also base
+                    m.isBaseModule = true;
+                }
+            }
+
+            public void postVisit(Module m, Module child, Module p) {
+                // nop - breadth-first search
+            }
+        };
+
+        // propagate the top-level module to all its members
+        for (Module p : modules.values()) {
+            for (Module m : p.members) {
+                if (m.group == m) {
+                    m.visit(new TreeSet<Module>(), groupSetter, p);
+                }
+            }
+        }
+
+        Visitor<Module> mergeClassList = new Visitor<Module>() {
+
+            public void preVisit(Module m, Module p) {
+                // nop - depth-first search
+            }
+
+            public void postVisit(Module m, Module child, Module p) {
+                m.addMember(child);
+            }
+        };
+
+        Set<Module> visited = new TreeSet<Module>();
+        for (Module m : modules.values()) {
+            if (m.group() == m) {
+                if (m.members().size() > 0) {
+                    // merge class list from all its members
+                    m.visit(visited, mergeClassList, m);
+                }
+
+                // clear the dependencies before fixup
+                m.dependents.clear();
+
+                // fixup dependencies
+                for (Klass k : m.classes) {
+                    for (Klass other : k.getReferencedClasses()) {
+                        if (m.isModuleDependence(other)) {
+                            // this module is dependent on otherModule
+                            m.addDependency(k, other);
+                        }
+                    }
+                }
+
+                // add dependencies that this klass may depend on due to the AnnotatedDependency
+                m.fixupAnnotatedDependencies();
+            }
+        }
+    }
+
+    class PackageInfo implements Comparable {
+
+        final String pkgName;
+        int count;
+        long filesize;
+
+        PackageInfo(String name) {
+            this.pkgName = name;
+            this.count = 0;
+            this.filesize = 0;
+        }
+
+        void add(PackageInfo pkg) {
+            this.count += pkg.count;
+            this.filesize += pkg.filesize;
+        }
+
+        void add(long size) {
+            count++;
+            filesize += size;
+
+        }
+
+        @Override
+        public int compareTo(Object o) {
+            return pkgName.compareTo(((PackageInfo) o).pkgName);
+        }
+    }
+
+    Set<PackageInfo> getPackageInfos() {
+        return new TreeSet<PackageInfo>(packages.values());
+    }
+
+    void printSummaryTo(String output) throws IOException {
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            long total = 0L;
+            int count = 0;
+            writer.format("%10s\t%10s\t%s\n", "Bytes", "Classes", "Package name");
+            for (String pkg : packages.keySet()) {
+                PackageInfo info = packages.get(pkg);
+                if (info.count > 0) {
+                    writer.format("%10d\t%10d\t%s\n", info.filesize, info.count, pkg);
+                    total += info.filesize;
+                    count += info.count;
+                }
+            }
+
+            writer.format("\nTotal: %d bytes (uncompressed) %d classes\n", total, count);
+        } finally {
+            writer.close();
+        }
+
+    }
+
+    void printClassListTo(String output) throws IOException {
+        // no file created if the module doesn't have any class
+        if (classes.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            for (Klass c : classes) {
+                if (c.exists()) {
+                    writer.format("%s\n", c.getClassFilePathname());
+                } else {
+                    trace("%s in module %s missing\n", c, this);
+                }
+            }
+
+        } finally {
+            writer.close();
+        }
+    }
+
+    void printResourceListTo(String output) throws IOException {
+        // no file created if the module doesn't have any resource file
+        if (resources.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            for (ResourceFile res : resources) {
+                writer.format("%s\n", res.getPathname());
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    void printDependenciesTo(String output, boolean showDynamic) throws IOException {
+        // no file created if the module doesn't have any class
+        if (classes.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            // classes that this klass may depend on due to the AnnotatedDependency
+            Map<Reference, Set<AnnotatedDependency>> annotatedDeps = AnnotatedDependency.getReferences(this);
+
+            for (Klass klass : classes) {
+                Set<Klass> references = klass.getReferencedClasses();
+                for (Klass other : references) {
+                    String classname = klass.getClassName();
+                    boolean optional = OptionalDependency.isOptional(klass, other);
+                    if (optional) {
+                        classname = "[optional] " + classname;
+                    }
+
+                    Module m = getModuleDependence(other);
+                    if (m != null || other.getModule() == null) {
+                        writer.format("%-40s -> %s (%s)", classname, other, m);
+                        Reference ref = new Reference(klass, other);
+                        if (annotatedDeps.containsKey(ref)) {
+                            for (AnnotatedDependency ad : annotatedDeps.get(ref)) {
+                                writer.format(" %s", ad.getTag());
+                            }
+                            // printed; so remove the dependency from the annotated deps list
+                            annotatedDeps.remove(ref);
+                        }
+                        writer.format("\n");
+                    }
+                }
+            }
+
+
+            // print remaining dependencies specified in AnnotatedDependency list
+            if (annotatedDeps.size() > 0) {
+                for (Map.Entry<Reference, Set<AnnotatedDependency>> entry : annotatedDeps.entrySet()) {
+                    Reference ref = entry.getKey();
+                    Module m = getModuleDependence(ref.referree);
+                    if (m != null || ref.referree.getModule() == null) {
+                        String classname = ref.referrer.getClassName();
+                        boolean optional = true;
+                        boolean dynamic = true;
+                        String tag = "";
+                        for (AnnotatedDependency ad : entry.getValue()) {
+                            if (optional && !ad.isOptional()) {
+                                optional = false;
+                                tag = ad.getTag();
+                            }
+                            if (!ad.isDynamic()) {
+                                dynamic = false;
+                            }
+                        }
+                        if (!showDynamic && optional && dynamic) {
+                            continue;
+                        }
+                        if (optional) {
+                            if (dynamic) {
+                                classname = "[dynamic] " + classname;
+                            } else {
+                                classname = "[optional] " + classname;
+                            }
+                        }
+                        writer.format("%-40s -> %s (%s) %s%n", classname, ref.referree, m, tag);
+                    }
+                }
+            }
+
+        } finally {
+            writer.close();
+        }
+    }
+
+    static class Dependency implements Comparable<Dependency> {
+
+        final Module module;
+        final boolean optional;
+        final boolean dynamic;
+
+        Dependency(Klass from, Klass to) {
+            // static dependency
+            this.module = to.getModule() != null ? to.getModule().group() : null;
+            this.optional = OptionalDependency.isOptional(from, to);
+            this.dynamic = false;
+        }
+
+        Dependency(Module m, boolean optional, boolean dynamic) {
+            this.module = m != null ? m.group() : null;
+            this.optional = optional;
+            this.dynamic = dynamic;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Dependency)) {
+                return false;
+            }
+            if (this == obj) {
+                return true;
+            }
+
+            Dependency d = (Dependency) obj;
+            if (this.module != d.module) {
+                return false;
+            } else {
+                return this.optional == d.optional && this.dynamic == d.dynamic;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 19 * hash + (this.module != null ? this.module.hashCode() : 0);
+            hash = 19 * hash + (this.optional ? 1 : 0);
+            hash = 19 * hash + (this.dynamic ? 1 : 0);
+            return hash;
+        }
+
+        @Override
+        public int compareTo(Dependency d) {
+            if (this.equals(d)) {
+                return 0;
+            }
+
+            // Hard static > hard dynamic > optional static > optional dynamic
+            if (this.module == d.module) {
+                if (this.optional == d.optional) {
+                    return this.dynamic ? -1 : 1;
+                } else {
+                    return this.optional ? -1 : 1;
+                }
+            } else if (this.module != null && d.module != null) {
+                return (this.module.compareTo(d.module));
+            } else {
+                return (this.module == null) ? -1 : 1;
+            }
+        }
+
+        @Override
+        public String toString() {
+            String s = module.name();
+            if (dynamic && optional) {
+                s += " (dynamic)";
+            } else if (optional) {
+                s += " (optional)";
+            }
+            return s;
+        }
+    }
+
+    static class Reference implements Comparable<Reference> {
+
+        private final Klass referrer, referree;
+
+        Reference(Klass referrer, Klass referree) {
+            this.referrer = referrer;
+            this.referree = referree;
+        }
+
+        Klass referrer() {
+            return referrer;
+        }
+
+        Klass referree() {
+            return referree;
+        }
+
+        @Override
+        public int hashCode() {
+            return referrer.hashCode() ^ referree.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Reference)) {
+                return false;
+            }
+            if (this == obj) {
+                return true;
+            }
+
+            Reference r = (Reference) obj;
+            return (this.referrer.equals(r.referrer) &&
+                    this.referree.equals(r.referree));
+        }
+
+        @Override
+        public int compareTo(Reference r) {
+            int ret = referrer.compareTo(r.referrer);
+            if (ret == 0) {
+                ret = referree.compareTo(r.referree);
+            }
+            return ret;
+        }
+    }
+
+    interface Visitor<P> {
+
+        public void preVisit(Module m, P param);
+
+        public void postVisit(Module m, Module child, P param);
+    }
+    private static boolean traceOn = System.getProperty("classanalyzer.debug") != null;
+
+    private static void trace(String format, Object... params) {
+        System.err.format(format, params);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ModuleConfig.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ModuleConfig {
+
+    private static String baseModuleName = "base";
+    private final Set<String> roots;
+    private final Set<String> includes;
+    private final Filter filter;
+    private List<String> members;
+    final String module;
+    final boolean isBase;
+
+    private ModuleConfig(String name) throws IOException {
+        this.roots = new TreeSet<String>();
+        this.includes = new TreeSet<String>();
+        this.module = name;
+        this.isBase = name.equals(baseModuleName);
+        this.filter = new Filter(this);
+    }
+
+    List<String> members() {
+        if (members == null) {
+            members = new LinkedList<String>();
+
+            for (String s : includes) {
+                if (!s.contains("*") && Module.findModule(s) != null) {
+                    // module member
+                    members.add(s);
+                }
+            }
+        }
+        return members;
+    }
+
+    boolean matchesRoot(String name) {
+        for (String pattern : roots) {
+            if (matches(name, pattern)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean matchesIncludes(String name) {
+        for (String pattern : includes) {
+            if (matches(name, pattern)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isExcluded(String name) {
+        return filter.isExcluded(name);
+    }
+
+    boolean matchesPackage(String packageName, String pattern) {
+        int pos = pattern.lastIndexOf('.');
+        String pkg = pos > 0 ? pattern.substring(0, pos) : "<unnamed>";
+        return packageName.equals(pkg);
+    }
+
+
+    boolean matches(String name, String pattern) {
+        if (pattern.contains("**") && !pattern.endsWith("**")) {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+
+        String javaName = name;
+
+        boolean isResourceFile = name.indexOf('/') >= 0;
+        if (isResourceFile) {
+            // it's a resource file; convert the name as a java
+            javaName = name.replace('/', '.');
+        }
+        if (pattern.indexOf('/') < 0) {
+            // if the pattern doesn't contain '/
+            return matchesJavaName(javaName, pattern);
+        } else {
+            if (isResourceFile) {
+                // the pattern is for matching resource file
+                return matchesNameWithSlash(name, pattern);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    boolean matchesJavaName(String name, String pattern) {
+        int pos = name.lastIndexOf('.');
+        String packageName = pos > 0 ? name.substring(0, pos) : "<unnamed>";
+        if (pattern.endsWith("**")) {
+            String p = pattern.substring(0, pattern.length() - 2);
+            return name.startsWith(p);
+        } else if (pattern.endsWith("*") && pattern.indexOf('*') == pattern.lastIndexOf('*')) {
+            if (matchesPackage(packageName, pattern)) {
+                // package name has to be exact match
+                String p = pattern.substring(0, pattern.length() - 1);
+                return name.startsWith(p);
+            } else {
+                return false;
+            }
+        } else if (pattern.contains("*")) {
+            String basename = pos > 0 ? name.substring(pos + 1, name.length()) : name;
+            pos = pattern.indexOf('*');
+            String prefix = pattern.substring(0, pos);
+            String suffix = pattern.substring(pos + 1, pattern.length());
+            if (name.startsWith(prefix) && matchesPackage(packageName, prefix)) {
+                // package name has to be exact match
+                if (suffix.contains("*")) {
+                    return name.matches(convertToRegex(pattern));
+                } else {
+                    return basename.endsWith(suffix);
+                }
+            } else {
+                // we don't support wildcard be used in the package name
+                return false;
+            }
+        } else {
+            // exact match or inner class
+            return name.equals(pattern) || name.startsWith(pattern + "$");
+        }
+    }
+
+    boolean matchesNameWithSlash(String name, String pattern) {
+        if (pattern.endsWith("**")) {
+            String p = pattern.substring(0, pattern.length() - 2);
+            return name.startsWith(p);
+        } else if (pattern.contains("*")) {
+            int pos = pattern.indexOf('*');
+            String prefix = pattern.substring(0, pos);
+            String suffix = pattern.substring(pos + 1, pattern.length());
+            String tail = name.substring(pos, name.length());
+
+            if (!name.startsWith(prefix)) {
+                // prefix has to exact match
+                return false;
+            }
+
+            if (pattern.indexOf('*') == pattern.lastIndexOf('*')) {
+                // exact match prefix with no '/' in the tail string
+                String wildcard = tail.substring(0, tail.length() - suffix.length());
+                return tail.indexOf('/') < 0 && tail.endsWith(suffix);
+            }
+
+            if (suffix.contains("*")) {
+                return matchesNameWithSlash(tail, suffix);
+            } else {
+                // tail ends with the suffix while no '/' in the wildcard matched string
+                String any = tail.substring(0, tail.length() - suffix.length());
+                return tail.endsWith(suffix) && any.indexOf('/') < 0;
+            }
+        } else {
+            // exact match
+            return name.equals(pattern);
+        }
+    }
+
+    private String convertToRegex(String pattern) {
+        StringBuilder sb = new StringBuilder();
+        int i = 0;
+        int index = 0;
+        int plen = pattern.length();
+        while (i < plen) {
+            char p = pattern.charAt(i);
+            if (p == '*') {
+                sb.append("(").append(pattern.substring(index, i)).append(")");
+                if (i + 1 < plen && pattern.charAt(i + 1) == '*') {
+                    sb.append(".*");
+                    index = i + 2;
+                } else {
+                    sb.append("[^\\.]*");
+                    index = i + 1;
+                }
+            }
+            i++;
+        }
+        if (index < plen) {
+            sb.append("(").append(pattern.substring(index, plen)).append(")");
+        }
+        return sb.toString();
+    }
+
+    static class Filter {
+
+        final ModuleConfig config;
+        final Set<String> exclude = new TreeSet<String>();
+        final Set<String> allow = new TreeSet<String>();
+
+        Filter(ModuleConfig config) {
+            this.config = config;
+        }
+
+        Filter exclude(String pattern) {
+            exclude.add(pattern);
+            return this;
+        }
+
+        Filter allow(String pattern) {
+            allow.add(pattern);
+            return this;
+        }
+
+        String allowedBy(String name) {
+            String allowedBy = null;
+            for (String pattern : allow) {
+                if (config.matches(name, pattern)) {
+                    if (name.equals(pattern)) {
+                        return pattern;  // exact match
+                    }
+                    if (allowedBy == null) {
+                        allowedBy = pattern;
+                    } else {
+                        if (pattern.length() > allowedBy.length()) {
+                            allowedBy = pattern;
+                        }
+                    }
+                }
+            }
+            return allowedBy;
+        }
+
+        String excludedBy(String name) {
+            String allowedBy = allowedBy(name);
+            String excludedBy = null;
+
+            if (allowedBy != null && name.equals(allowedBy)) {
+                return null;  // exact match
+            }
+            for (String pattern : exclude) {
+                if (config.matches(name, pattern)) {
+                    // not matched by allowed rule or exact match
+                    if (allowedBy == null || name.equals(pattern)) {
+                        return pattern;
+                    }
+                    if (excludedBy == null) {
+                        excludedBy = pattern;
+                    } else {
+                        if (pattern.length() > excludedBy.length()) {
+                            excludedBy = pattern;
+                        }
+                    }
+                }
+            }
+            return excludedBy;
+        }
+
+        boolean isExcluded(String name) {
+            String allowedBy = allowedBy(name);
+            String excludedBy = excludedBy(name);
+
+            if (excludedBy == null) {
+                return false;
+            }
+            // not matched by allowed rule or exact match
+            if (allowedBy == null || name.equals(excludedBy)) {
+                return true;
+            }
+
+            if (allowedBy == null) {
+                return true;
+            }
+            if (allowedBy != null &&
+                    excludedBy.length() > allowedBy.length()) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private static String trimComment(String line) {
+        StringBuilder sb = new StringBuilder();
+
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c1 = line.indexOf("//", pos);
+            if (c1 > 0 && !Character.isWhitespace(line.charAt(c1-1))) {
+                // not a comment
+                c1 = -1;
+            }
+
+            int c2 = line.indexOf("/*", pos);
+            if (c2 > 0 && !Character.isWhitespace(line.charAt(c2-1))) {
+                // not a comment
+                c2 = -1;
+            }
+
+            int c = line.length();
+            int n = line.length();
+            if (c1 >= 0 || c2 >= 0) {
+                if (c1 >= 0) {
+                    c = c1;
+                }
+                if (c2 >= 0 && c2 < c) {
+                    c = c2;
+                }
+                int c3 = line.indexOf("*/", c2 + 2);
+                if (c == c2 && c3 > c2) {
+                    n = c3 + 2;
+                }
+            }
+            if (c > 0) {
+                if (sb.length() > 0) {
+                    // add a whitespace if multiple comments on one line
+                    sb.append(" ");
+                }
+                sb.append(line.substring(pos, c));
+            }
+            pos = n;
+        }
+        return sb.toString();
+    }
+
+    private static boolean beginBlockComment(String line) {
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c = line.indexOf("/*", pos);
+            if (c < 0) {
+                return false;
+            }
+
+            if (c > 0 && !Character.isWhitespace(line.charAt(c-1))) {
+                return false;
+            }
+
+            int c1 = line.indexOf("//", pos);
+            if (c1 >= 0 && c1 < c) {
+                return false;
+            }
+
+            int c2 = line.indexOf("*/", c + 2);
+            if (c2 < 0) {
+                return true;
+            }
+            pos = c + 2;
+        }
+        return false;
+    }
+
+    static void setBaseModule(String name) {
+        baseModuleName = name;
+    }
+    // TODO: we shall remove "-" from the regex once we define
+    // the naming convention for the module names without dashes
+    static final Pattern classNamePattern = Pattern.compile("[\\w\\.\\*_$-/]+");
+
+    static List<ModuleConfig> readConfigurationFile(String file) throws IOException {
+        List<ModuleConfig> result = new ArrayList<ModuleConfig>();
+        // parse configuration file
+        FileInputStream in = new FileInputStream(file);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+
+            int lineNumber = 0;
+            boolean inRoots = false;
+            boolean inIncludes = false;
+            boolean inAllows = false;
+            boolean inExcludes = false;
+            boolean inBlockComment = false;
+            ModuleConfig config = null;
+
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+
+                if (inBlockComment) {
+                    int c = line.indexOf("*/");
+                    if (c >= 0) {
+                        line = line.substring(c + 2, line.length());
+                        inBlockComment = false;
+                    } else {
+                        // skip lines until end of comment block
+                        continue;
+                    }
+                }
+
+                inBlockComment = beginBlockComment(line);
+
+                line = trimComment(line).trim();
+                // ignore empty lines
+                if (line.length() == 0) {
+                    continue;
+                }
+
+                String values;
+                if (inRoots || inIncludes || inExcludes || inAllows) {
+                    values = line;
+                } else {
+                    String[] s = line.split("\\s+");
+                    String keyword = s[0].trim();
+                    if (keyword.equals("module")) {
+                        if (s.length != 3 || !s[2].trim().equals("{")) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed");
+                        }
+                        config = new ModuleConfig(s[1].trim());
+                        result.add(config);
+                        // switch to a new module; so reset the flags
+                        inRoots = false;
+                        inIncludes = false;
+                        inExcludes = false;
+                        inAllows = false;
+                        continue;
+                    } else if (keyword.equals("roots")) {
+                        inRoots = true;
+                    } else if (keyword.equals("include")) {
+                        inIncludes = true;
+                    } else if (keyword.equals("exclude")) {
+                        inExcludes = true;
+                    } else if (keyword.equals("allow")) {
+                        inAllows = true;
+                    } else if (keyword.equals("}")) {
+                        if (config == null || s.length != 1) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed");
+                        } else {
+                            // end of a module
+                            config = null;
+                            continue;
+                        }
+                    } else {
+                        throw new RuntimeException(file + ", \"" + keyword + "\" on line " +
+                                lineNumber + ", is not recognized");
+                    }
+                    values = line.substring(keyword.length(), line.length()).trim();
+                }
+
+                if (config == null) {
+                    throw new RuntimeException(file + ", module not specified");
+                }
+
+                int len = values.length();
+                if (len == 0) {
+                    continue;
+                }
+                char lastchar = values.charAt(len - 1);
+                if (lastchar != ',' && lastchar != ';') {
+                    throw new RuntimeException(file + ", line " +
+                            lineNumber + ", is malformed:" +
+                            " ',' or ';' is missing.");
+                }
+
+                values = values.substring(0, len - 1);
+                // parse the values specified for a keyword specified
+                for (String s : values.split(",")) {
+                    s = s.trim();
+                    if (s.length() > 0) {
+                        if (!classNamePattern.matcher(s).matches()) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed: \"" + s + "\"");
+                        }
+                        if (inRoots) {
+                            config.roots.add(s);
+                        } else if (inIncludes) {
+                            config.includes.add(s);
+                        } else if (inExcludes) {
+                            config.filter.exclude(s);
+                        } else if (inAllows) {
+                            config.filter.allow(s);
+                        }
+
+                    }
+                }
+                if (lastchar == ';') {
+                    inRoots = false;
+                    inIncludes = false;
+                    inExcludes = false;
+                    inAllows = false;
+                }
+            }
+
+            if (inBlockComment) {
+                throw new RuntimeException(file + ", line " +
+                        lineNumber + ", missing \"*/\" to end a block comment");
+            }
+            if (config != null) {
+                throw new RuntimeException(file + ", line " +
+                        lineNumber + ", missing \"}\" to end module definition" +
+                        " for \"" + config.module + "\"");
+            }
+
+        } finally {
+            in.close();
+        }
+
+        return result;
+    }
+
+    private String format(String keyword, Collection<String> values) {
+        if (values.size() == 0) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        String format = "%4s%-9s";
+        String spaces = String.format(format, "", "");
+        sb.append(String.format(format, "", keyword));
+        int count = 0;
+        for (String s : values) {
+            if (count > 0) {
+                sb.append(",\n").append(spaces);
+            } else if (count++ > 0) {
+                sb.append(", ");
+            }
+            sb.append(s);
+        }
+        if (count > 0) {
+            sb.append(";\n");
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("module " + module).append(" {\n");
+        sb.append(format("include", includes));
+        sb.append(format("root", roots));
+        sb.append(format("allow", filter.allow));
+        sb.append(format("exclude", filter.exclude));
+        sb.append("}\n");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResolutionInfo.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import com.sun.classanalyzer.Klass.Method;
+
+/**
+ *
+ * @author mchung
+ */
+public class ResolutionInfo implements Comparable<ResolutionInfo> {
+
+    enum Type {
+
+        REFLECTION("reflection", true),
+        NATIVE("native", true),
+        INTERFACE("interface", false),
+        SUPER("super", false),
+        EXPLICIT("explicit", false),
+        VERIFICATION("verification", false),
+        METHODTRACE("method trace", true),
+        CONSTANT_POOL("constant pool", true),
+        CHECKED_EXCEPTION("throws", true),
+        METHOD("method", true),
+        FIELD("field", true),
+        EXTENDS("extends", true),
+        IMPLEMENTS("implements", true),
+        NOINFO("No info", false);
+
+        private final String name;
+        private final boolean hasInfo;
+
+        private Type(String name, boolean hasInfo) {
+            this.name = name;
+            this.hasInfo = hasInfo;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean hasInfo() {
+            return hasInfo;
+        }
+
+        public static Type getType(String s) {
+            if (s.isEmpty()) {
+                return NOINFO;
+            }
+            for (Type t : values()) {
+                if (s.equals(t.name)) {
+                    return t;
+                }
+            }
+            // Need to fix the VM output to add "native"
+            // throw new IllegalArgumentException("Invalid ResolutionInfo.type \"" + s + "\"");
+            System.out.println("WARNING: Invalid ResolutionInfo.type \"" + s + "\"");
+            return null;
+        }
+    }
+    final Klass fromClass;
+    final Method method;
+    final Klass toClass;
+    final int linenumber;
+    final Type type;
+    final String info;
+    private boolean isPublic = false;
+
+    private ResolutionInfo(Klass from, Klass to, int linenumber, Type type, String info) {
+        this.fromClass = from;
+        this.method = null;
+        this.toClass = to;
+        this.linenumber = linenumber;
+        this.type = type;
+        this.info = info;
+    }
+
+    private ResolutionInfo(Klass from, Method m, Klass to, int linenumber, Type type) {
+        this.fromClass = from;
+        this.method = m;
+        this.toClass = to;
+        this.linenumber = linenumber;
+        this.type = type;
+        this.info = m.toString();
+    }
+
+    public boolean isPublic() {
+        return isPublic;
+    }
+
+    public void setPublicAccess(boolean value) {
+        isPublic = value;
+    }
+    static ResolutionInfo resolved(Klass from, Klass to) {
+        return new ResolutionInfo(from, to, 0, Type.NOINFO, "");
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, int linenumber) {
+        return new ResolutionInfo(from, to, linenumber, Type.NOINFO, "");
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, int linenumber, String reason) {
+        String[] ss = reason.split("\\s+");
+        Type type;
+        String info;
+        if (linenumber == -1) {
+            type = Type.NATIVE;
+            info = ss[0];  // native method name
+        } else {
+            info = ss.length == 2 ? ss[1] : "";
+            type = Type.getType(ss[0]);
+            if (type == null) {
+                if (reason.isEmpty()) {
+                    throw new IllegalArgumentException("Invalid type: " + reason + " (" + ss[0] + ")" + ss.length);
+                }
+                // assume it's native
+                type = Type.NATIVE;
+                info = reason.isEmpty() ? ss[0] : reason;
+            }
+        }
+
+        return new ResolutionInfo(from, to, linenumber, type, info);
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, Method callee) {
+        return new ResolutionInfo(from, callee, to, 0, Type.METHODTRACE);
+    }
+
+    static ResolutionInfo resolvedConstantPool(Klass from, Klass to, int index) {
+        return new ResolutionInfo(from, to, 0, Type.CONSTANT_POOL, "#" + index);
+    }
+
+    static ResolutionInfo resolvedField(Klass from, Klass to, String fieldname) {
+        return new ResolutionInfo(from, to, 0, Type.FIELD, fieldname);
+    }
+
+    static ResolutionInfo resolvedMethodSignature(Klass from, Klass to, Method m) {
+        return new ResolutionInfo(from, m, to, 0, Type.METHOD);
+    }
+
+    static ResolutionInfo resolvedCheckedException(Klass from, Klass to, Method m) {
+        return new ResolutionInfo(from, m, to, 0, Type.CHECKED_EXCEPTION);
+    }
+
+    static ResolutionInfo resolvedExtends(Klass from, Klass to) {
+        String info = from.getClassName() + " implements " + to.getClassName();
+        return new ResolutionInfo(from, to, 0, Type.EXTENDS, info);
+    }
+
+    static ResolutionInfo resolvedImplements(Klass from, Klass to) {
+        String info = from.getClassName() + " implements " + to.getClassName();
+        return new ResolutionInfo(from, to, 0, Type.IMPLEMENTS, info);
+    }
+
+    @Override
+    public int compareTo(ResolutionInfo ri) {
+        if (this.fromClass == ri.fromClass &&
+                this.toClass == ri.toClass &&
+                this.linenumber == ri.linenumber &&
+                this.type == ri.type &&
+                this.info.equals(ri.info)) {
+            return 0;
+        } else if (this.fromClass == ri.fromClass) {
+            if (this.linenumber > ri.linenumber) {
+                return 1;
+            } else if (this.linenumber < ri.linenumber) {
+                return -1;
+            } else if (this.type != ri.type) {
+                return this.type.getName().compareTo(ri.type.getName());
+            } else if (this.toClass != ri.toClass) {
+                return this.toClass.compareTo(ri.toClass);
+            } else {
+                return this.info.compareTo(ri.info);
+            }
+        } else {
+            return this.fromClass.compareTo(ri.fromClass);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResourceFile.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ResourceFile implements Comparable<ResourceFile> {
+
+    private final String pathname;
+    private Module module;
+
+    ResourceFile(String pathname) {
+        this.pathname = pathname.replace(File.separatorChar, '/');
+    }
+
+    Module getModule() {
+        return module;
+    }
+
+    void setModule(Module m) {
+        if (module != null) {
+            throw new RuntimeException("Module for " + this + " already set");
+        }
+        this.module = m;
+    }
+
+    String getName() {
+        return pathname;
+    }
+
+    String getPathname() {
+        return pathname;
+    }
+
+    @Override
+    public String toString() {
+        return pathname;
+    }
+
+    @Override
+    public int compareTo(ResourceFile o) {
+        return pathname.compareTo(o.pathname);
+    }
+    static Set<ResourceFile> resources = new TreeSet<ResourceFile>();
+
+    static boolean isResource(String pathname) {
+        String name = pathname.replace(File.separatorChar, '/');
+
+        if (name.endsWith("META-INF/MANIFEST.MF")) {
+            return false;
+        }
+        if (name.contains("META-INF/JCE_RSA.")) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static void addResource(String name, InputStream in) {
+        ResourceFile res;
+        name = name.replace(File.separatorChar, '/');
+        if (name.startsWith("META-INF/services")) {
+            res = new ServiceProviderConfigFile(name, in);
+        } else {
+            res = new ResourceFile(name);
+        }
+        resources.add(res);
+    }
+
+    static Set<ResourceFile> getAllResources() {
+        return Collections.unmodifiableSet(resources);
+    }
+
+    static class ServiceProviderConfigFile extends ResourceFile {
+
+        private final List<String> providers = new ArrayList<String>();
+        private final String service;
+        ServiceProviderConfigFile(String pathname, InputStream in) {
+            super(pathname);
+            readServiceConfiguration(in, providers);
+            this.service = pathname.substring("META-INF/services".length() + 1, pathname.length());
+        }
+
+        @Override
+        String getName() {
+            if (providers.isEmpty()) {
+                return service;
+            } else {
+                // just use the first one for matching
+                return providers.get(0);
+            }
+        }
+
+        @SuppressWarnings("empty-statement")
+        void readServiceConfiguration(InputStream in, List<String> names) {
+            BufferedReader br = null;
+            try {
+                if (in != null) {
+                    // Properties doesn't perserve the order of the input file
+                    br = new BufferedReader(new InputStreamReader(in, "utf-8"));
+                    int lc = 1;
+                    while ((lc = parseLine(br, lc, names)) >= 0);
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (br != null) {
+                    try {
+                        br.close();
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        }
+
+        // Parse a single line from the given configuration file, adding the name
+        // on the line to the names list.
+        //
+        private int parseLine(BufferedReader r, int lc, List<String> names) throws IOException {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) {
+                ln = ln.substring(0, ci);
+            }
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
+                    throw new RuntimeException("Illegal configuration-file syntax");
+                }
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp)) {
+                    throw new RuntimeException("Illegal provider-class name: " + ln);
+                }
+                for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
+                        throw new RuntimeException("Illegal provider-class name: " + ln);
+                    }
+                }
+                if (!names.contains(ln)) {
+                    names.add(ln);
+                }
+            }
+            return lc + 1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ShowDeps.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 com.sun.classanalyzer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * A simple tool to print out the static dependencies for a given set of JAR,
+ * class files, or combinations of. The tools supports an -ignore option to
+ * ignore references to classes listed in the file (including .classlists
+ * created by the ClassAnalyzer tool).
+ */
+
+public class ShowDeps {
+
+    static void usage() {
+        System.out.println("java ShowDeps [-ignore <classlist>] file...");
+        System.out.println("   where <file> is a class or JAR file, or a directory");
+        System.out.println();
+        System.out.println("Example usages:");
+        System.out.println("  java ShowDeps Foo.jar");
+        System.out.println("  java ShowDeps -ignore base.classlist Foo.jar");
+        System.out.println("  java ShowDeps -ignore base.classlist -ignore " +
+            "jaxp-parsers.classlist <dir>");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        // process -ignore options
+        int argi = 0;
+        Set<String> ignore = new HashSet<String>();
+        while (argi < args.length && args[argi].equals("-ignore")) {
+            argi++;
+            Scanner s = new Scanner(new File(args[argi++]));
+            try {
+                while (s.hasNextLine()) {
+                    String line = s.nextLine();
+                    if (!line.endsWith(".class"))
+                        continue;
+                    int len = line.length();
+                    // convert to class names
+                    String clazz = line.replace('\\', '.').replace('/', '.')
+                        .substring(0, len-6);
+                    ignore.add(clazz);
+                }
+            } finally {
+                s.close();
+            }
+        }
+
+        if (argi >= args.length)
+            usage();
+
+        // parse all classes
+        while (argi < args.length)
+            ClassPath.setClassPath(args[argi++]);
+        ClassPath.parseAllClassFiles();
+
+        // find the classes that don't exist
+        Set<Klass> unresolved = new TreeSet<Klass>();
+        for (Klass k : Klass.getAllClasses()) {
+            if (k.getFileSize() == 0)
+                unresolved.add(k);
+        }
+
+        // print references to classes that don't exist
+        for (Klass k: Klass.getAllClasses()) {
+            for (Klass other : k.getReferencedClasses()) {
+                if (unresolved.contains(other)) {
+                    String name = other.toString();
+                    if (!ignore.contains(name)) {
+                        System.out.format("%s -> %s\n", k, other);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/jdk/src/share/bin/java.c	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/bin/java.c	Sun Jan 17 18:42:34 2010 -0800
@@ -93,6 +93,7 @@
  * Prototypes for functions internal to launcher.
  */
 static void SetClassPath(const char *s);
+static void SetModulesBootClassPath(const char *s);
 static void SelectVersion(int argc, char **argv, char **main_class);
 static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
                                char **pclassname, int *pret, const char *jvmpath);
@@ -277,6 +278,9 @@
         return(ret);
     }
 
+    /* Set bootclasspath for modules */
+    SetModulesBootClassPath(jrepath);
+
     /* Override class path if -jar flag was specified */
     if (jarfile != 0) {
         SetClassPath(jarfile);
@@ -694,6 +698,44 @@
 }
 
 /*
+ * Set the bootclasspath for modules.
+ * A temporary workaround until jigsaw is integrated into JDK 7.
+ */
+static void
+SetModulesBootClassPath(const char *jrepath)
+{
+    char *def, *s;
+    char pathname[MAXPATHLEN];
+    const char separator[] = { FILE_SEPARATOR, '\0' };
+    const char *orig = jrepath;
+    static const char format[] = "-Xbootclasspath/p:%s";
+    struct stat statbuf;
+
+    /* return if jre/lib/rt.jar exists */
+    sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
+    if (stat(pathname, &statbuf) == 0) {
+        return;
+    }
+
+    /* return if jre/classes exists */
+    sprintf(pathname, "%s%sclasses", jrepath, separator);
+    if (stat(pathname, &statbuf) == 0) {
+        return;
+    }
+
+    /* modularized jre */
+    sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
+    s = (char *) JLI_WildcardExpandClasspath(pathname);
+    def = JLI_MemAlloc(sizeof(format)
+                       - 2 /* strlen("%s") */
+                       + JLI_StrLen(s));
+    sprintf(def, format, s);
+    AddOption(def, NULL);
+    if (s != orig)
+        JLI_MemFree((char *) s);
+}
+
+/*
  * The SelectVersion() routine ensures that an appropriate version of
  * the JRE is running.  The specification for the appropriate version
  * is obtained from either the manifest of a jar file (preferred) or
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Sun Jan 17 18:42:34 2010 -0800
@@ -33,10 +33,10 @@
 import java.util.Hashtable;
 import java.util.Properties;
 import java.util.Enumeration;
-import java.applet.Applet;
 
 import org.omg.CORBA.ORB;
 
+import javax.naming.Context;
 import javax.naming.ConfigurationException;
 
 /**
@@ -191,16 +191,48 @@
         }
 
         // Get Applet from environment
-        Applet applet = null;
         if (env != null) {
-            applet = (Applet) env.get("java.naming.applet");
+            Object applet = env.get(Context.APPLET);
+            if (applet != null) {
+                // Create ORBs for an applet
+                return initAppletORB(applet, orbProp);
+            }
         }
 
-        // Create ORBs using applet and orbProp
-        if (applet != null) {
-            return ORB.init(applet, orbProp);
-        } else {
-            return ORB.init(new String[0], orbProp);
+        // Create ORBs using orbProp for a standalone application
+        return ORB.init(new String[0], orbProp);
+    }
+
+    /**
+     * This method returns a new ORB instance for the given applet
+     * without creating a static dependency on java.applet.
+     */
+    private static ORB initAppletORB(Object applet, Properties orbProp) {
+        try {
+            Class<?> appletClass  = Class.forName("java.applet.Applet", true, null);
+            if (!appletClass.isInstance(applet)) {
+                throw new ClassCastException(applet.getClass().getName());
+            }
+
+            // invoke the static method ORB.init(applet, orbProp);
+            Method method = ORB.class.getMethod("init", appletClass, Properties.class);
+            return (ORB) method.invoke(null, applet, orbProp);
+        } catch (ClassNotFoundException e) {
+            // java.applet.Applet doesn't exist and the applet parameter is
+            // non-null; so throw CCE
+            throw new ClassCastException(applet.getClass().getName());
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            } else if (cause instanceof Error) {
+                throw (Error) cause;
+            }
+            throw new AssertionError(e);
+        } catch (IllegalAccessException iae) {
+            throw new AssertionError(iae);
         }
     }
 
--- a/jdk/src/share/classes/java/lang/StrictMath.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/lang/StrictMath.java	Sun Jan 17 18:42:34 2010 -0800
@@ -26,6 +26,7 @@
 package java.lang;
 import java.util.Random;
 import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
 
 /**
  * The class {@code StrictMath} contains methods for performing basic
@@ -316,7 +317,9 @@
      *          floating-point value that is greater than or equal to
      *          the argument and is equal to a mathematical integer.
      */
-    public static native double ceil(double a);
+    public static double ceil(double a) {
+        return floorOrCeil(a, -0.0, 1.0, 1.0);
+    }
 
     /**
      * Returns the largest (closest to positive infinity)
@@ -333,7 +336,54 @@
      *          floating-point value that less than or equal to the argument
      *          and is equal to a mathematical integer.
      */
-    public static native double floor(double a);
+    public static double floor(double a) {
+        return floorOrCeil(a, -1.0, 0.0, -1.0);
+    }
+
+    /**
+     * Internal method to share logic between floor and ceil.
+     *
+     * @param a the value to be floored or ceiled
+     * @param negativeBoundary result for values in (-1, 0)
+     * @param positiveBoundary result for values in (0, 1)
+     * @param increment value to add when the argument is non-integral
+     */
+    private static double floorOrCeil(double a,
+                                      double negativeBoundary,
+                                      double positiveBoundary,
+                                      double sign) {
+        int exponent = Math.getExponent(a);
+
+        if (exponent < 0) {
+            /*
+             * Absolute value of argument is less than 1.
+             * floorOrceil(-0.0) => -0.0
+             * floorOrceil(+0.0) => +0.0
+             */
+            return ((a == 0.0) ? a :
+                    ( (a < 0.0) ?  negativeBoundary : positiveBoundary) );
+        } else if (exponent >= 52) {
+            /*
+             * Infinity, NaN, or a value so large it must be integral.
+             */
+            return a;
+        }
+        // Else the argument is either an integral value already XOR it
+        // has to be rounded to one.
+        assert exponent >= 0 && exponent <= 51;
+
+        long doppel = Double.doubleToRawLongBits(a);
+        long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+
+        if ( (mask & doppel) == 0L )
+            return a; // integral value
+        else {
+            double result = Double.longBitsToDouble(doppel & (~mask));
+            if (sign*a > 0.0)
+                result = result + sign;
+            return result;
+        }
+    }
 
     /**
      * Returns the {@code double} value that is closest in value
--- a/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java	Sun Jan 17 18:42:34 2010 -0800
@@ -32,7 +32,7 @@
  * for monitoring and managing a component in the Java platform.
  * Each platform managed object has a unique
  * <a href="ManagementFactory.html#MXBean">object name</a>
- * for the {@linkplain ManagementFactory.getPlatformMBeanServer
+ * for the {@linkplain ManagementFactory#getPlatformMBeanServer
  * platform MBeanServer} access.
  * All platform MXBeans will implement this interface.
  *
--- a/jdk/src/share/classes/java/nio/X-Buffer.java.template	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/nio/X-Buffer.java.template	Sun Jan 17 18:42:34 2010 -0800
@@ -32,24 +32,24 @@
 #end[char]
 
 /**
- * $A$ $fulltype$ buffer.
+ * $A$ $type$ buffer.
  *
  * <p> This class defines {#if[byte]?six:four} categories of operations upon
- * $fulltype$ buffers:
+ * $type$ buffers:
  *
  * <ul>
  *
  *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
  *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
- *   single $fulltype$s; </p></li>
+ *   single $type$s; </p></li>
  *
  *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from this buffer
+ *   methods that transfer contiguous sequences of $type$s from this buffer
  *   into an array; {#if[!byte]?and}</p></li>
  *
  *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from $a$
- *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
+ *   methods that transfer contiguous sequences of $type$s from $a$
+ *   $type$ array{#if[char]?,&#32;a&#32;string,} or some other $type$
  *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
  *
 #if[byte]
@@ -67,22 +67,22 @@
  *
  *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
  *   #duplicate </code>duplicating<code>}, and {@link #slice
- *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
+ *   </code>slicing<code>} $a$ $type$ buffer.  </p></li>
  *
  * </ul>
  *
- * <p> $Fulltype$ buffers can be created either by {@link #allocate
+ * <p> $Type$ buffers can be created either by {@link #allocate
  * </code><i>allocation</i><code>}, which allocates space for the buffer's
  *
 #if[byte]
  *
  * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
- * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
+ * existing $type$ array {#if[char]?or&#32;string} into a buffer.
  *
 #else[byte]
  *
  * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
- * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
+ * $type$ array {#if[char]?or&#32;string} into a buffer, or by creating a
  * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
  *
 #end[byte]
@@ -189,12 +189,12 @@
 *
 #if[!byte]
  *
- * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
+ * <p> Like a byte buffer, $a$ $type$ buffer is either <a
  * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
- * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
- * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
+ * $type$ buffer created via the <tt>wrap</tt> methods of this class will
+ * be non-direct.  $A$ $type$ buffer created as a view of a byte buffer will
  * be direct if, and only if, the byte buffer itself is direct.  Whether or not
- * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
+ * $a$ $type$ buffer is direct may be determined by invoking the {@link
  * #isDirect isDirect} method.  </p>
  *
 #end[!byte]
@@ -287,7 +287,7 @@
 #if[byte]
 
     /**
-     * Allocates a new direct $fulltype$ buffer.
+     * Allocates a new direct $type$ buffer.
      *
      * <p> The new buffer's position will be zero, its limit will be its
      * capacity, its mark will be undefined, and each of its elements will be
@@ -295,9 +295,9 @@
      * {@link #hasArray </code>backing array<code>} is unspecified.
      *
      * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
+     *         The new buffer's capacity, in $type$s
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IllegalArgumentException
      *          If the <tt>capacity</tt> is a negative integer
@@ -309,7 +309,7 @@
 #end[byte]
 
     /**
-     * Allocates a new $fulltype$ buffer.
+     * Allocates a new $type$ buffer.
      *
      * <p> The new buffer's position will be zero, its limit will be its
      * capacity, its mark will be undefined, and each of its elements will be
@@ -318,9 +318,9 @@
      * offset<code>} will be zero.
      *
      * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
+     *         The new buffer's capacity, in $type$s
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IllegalArgumentException
      *          If the <tt>capacity</tt> is a negative integer
@@ -332,9 +332,9 @@
     }
 
     /**
-     * Wraps $a$ $fulltype$ array into a buffer.
+     * Wraps $a$ $type$ array into a buffer.
      *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * <p> The new buffer will be backed by the given $type$ array;
      * that is, modifications to the buffer will cause the array to be modified
      * and vice versa.  The new buffer's capacity will be
      * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
@@ -356,7 +356,7 @@
      *         <tt>array.length - offset</tt>.
      *         The new buffer's limit will be set to <tt>offset + length</tt>.
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IndexOutOfBoundsException
      *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
@@ -373,9 +373,9 @@
     }
 
     /**
-     * Wraps $a$ $fulltype$ array into a buffer.
+     * Wraps $a$ $type$ array into a buffer.
      *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * <p> The new buffer will be backed by the given $type$ array;
      * that is, modifications to the buffer will cause the array to be modified
      * and vice versa.  The new buffer's capacity and limit will be
      * <tt>array.length</tt>, its position will be zero, and its mark will be
@@ -386,7 +386,7 @@
      * @param  array
      *         The array that will back this buffer
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public static $Type$Buffer wrap($type$[] array) {
         return wrap(array, 0, array.length);
@@ -486,7 +486,7 @@
 #end[char]
 
     /**
-     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
+     * Creates a new $type$ buffer whose content is a shared subsequence of
      * this buffer's content.
      *
      * <p> The content of the new buffer will start at this buffer's current
@@ -495,17 +495,17 @@
      * values will be independent.
      *
      * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of $fulltype$s remaining in this buffer, and its mark
+     * will be the number of $type$s remaining in this buffer, and its mark
      * will be undefined.  The new buffer will be direct if, and only if, this
      * buffer is direct, and it will be read-only if, and only if, this buffer
      * is read-only.  </p>
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public abstract $Type$Buffer slice();
 
     /**
-     * Creates a new $fulltype$ buffer that shares this buffer's content.
+     * Creates a new $type$ buffer that shares this buffer's content.
      *
      * <p> The content of the new buffer will be that of this buffer.  Changes
      * to this buffer's content will be visible in the new buffer, and vice
@@ -517,12 +517,12 @@
      * and only if, this buffer is direct, and it will be read-only if, and
      * only if, this buffer is read-only.  </p>
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public abstract $Type$Buffer duplicate();
 
     /**
-     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
+     * Creates a new, read-only $type$ buffer that shares this buffer's
      * content.
      *
      * <p> The content of the new buffer will be that of this buffer.  Changes
@@ -537,7 +537,7 @@
      * <p> If this buffer is itself read-only then this method behaves in
      * exactly the same way as the {@link #duplicate duplicate} method.  </p>
      *
-     * @return  The new, read-only $fulltype$ buffer
+     * @return  The new, read-only $type$ buffer
      */
     public abstract $Type$Buffer asReadOnlyBuffer();
 
@@ -545,10 +545,10 @@
     // -- Singleton get/put methods --
 
     /**
-     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
+     * Relative <i>get</i> method.  Reads the $type$ at this buffer's
      * current position, and then increments the position. </p>
      *
-     * @return  The $fulltype$ at the buffer's current position
+     * @return  The $type$ at the buffer's current position
      *
      * @throws  BufferUnderflowException
      *          If the buffer's current position is not smaller than its limit
@@ -558,11 +558,11 @@
     /**
      * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> Writes the given $fulltype$ into this buffer at the current
+     * <p> Writes the given $type$ into this buffer at the current
      * position, and then increments the position. </p>
      *
      * @param  $x$
-     *         The $fulltype$ to be written
+     *         The $type$ to be written
      *
      * @return  This buffer
      *
@@ -575,13 +575,13 @@
     public abstract $Type$Buffer put($type$ $x$);
 
     /**
-     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
+     * Absolute <i>get</i> method.  Reads the $type$ at the given
      * index. </p>
      *
      * @param  index
-     *         The index from which the $fulltype$ will be read
+     *         The index from which the $type$ will be read
      *
-     * @return  The $fulltype$ at the given index
+     * @return  The $type$ at the given index
      *
      * @throws  IndexOutOfBoundsException
      *          If <tt>index</tt> is negative
@@ -592,14 +592,14 @@
     /**
      * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> Writes the given $fulltype$ into this buffer at the given
+     * <p> Writes the given $type$ into this buffer at the given
      * index. </p>
      *
      * @param  index
-     *         The index at which the $fulltype$ will be written
+     *         The index at which the $type$ will be written
      *
      * @param  $x$
-     *         The $fulltype$ value to be written
+     *         The $type$ value to be written
      *
      * @return  This buffer
      *
@@ -618,14 +618,14 @@
     /**
      * Relative bulk <i>get</i> method.
      *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  If there are fewer $fulltype$s remaining in the
+     * <p> This method transfers $type$s from this buffer into the given
+     * destination array.  If there are fewer $type$s remaining in the
      * buffer than are required to satisfy the request, that is, if
      * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
+     * $type$s are transferred and a {@link BufferUnderflowException} is
      * thrown.
      *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
+     * <p> Otherwise, this method copies <tt>length</tt> $type$s from this
      * buffer into the given array, starting at the current position of this
      * buffer and at the given offset in the array.  The position of this
      * buffer is then incremented by <tt>length</tt>.
@@ -638,26 +638,26 @@
      *     for (int i = off; i < off + len; i++)
      *         dst[i] = src.get(); </pre>
      *
-     * except that it first checks that there are sufficient $fulltype$s in
+     * except that it first checks that there are sufficient $type$s in
      * this buffer and it is potentially much more efficient. </p>
      *
      * @param  dst
-     *         The array into which $fulltype$s are to be written
+     *         The array into which $type$s are to be written
      *
      * @param  offset
-     *         The offset within the array of the first $fulltype$ to be
+     *         The offset within the array of the first $type$ to be
      *         written; must be non-negative and no larger than
      *         <tt>dst.length</tt>
      *
      * @param  length
-     *         The maximum number of $fulltype$s to be written to the given
+     *         The maximum number of $type$s to be written to the given
      *         array; must be non-negative and no larger than
      *         <tt>dst.length - offset</tt>
      *
      * @return  This buffer
      *
      * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          If there are fewer than <tt>length</tt> $type$s
      *          remaining in this buffer
      *
      * @throws  IndexOutOfBoundsException
@@ -677,7 +677,7 @@
     /**
      * Relative bulk <i>get</i> method.
      *
-     * <p> This method transfers $fulltype$s from this buffer into the given
+     * <p> This method transfers $type$s from this buffer into the given
      * destination array.  An invocation of this method of the form
      * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
      *
@@ -687,7 +687,7 @@
      * @return  This buffer
      *
      * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          If there are fewer than <tt>length</tt> $type$s
      *          remaining in this buffer
      */
     public $Type$Buffer get($type$[] dst) {
@@ -700,15 +700,15 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers the $fulltype$s remaining in the given source
-     * buffer into this buffer.  If there are more $fulltype$s remaining in the
+     * <p> This method transfers the $type$s remaining in the given source
+     * buffer into this buffer.  If there are more $type$s remaining in the
      * source buffer than in this buffer, that is, if
      * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
+     * then no $type$s are transferred and a {@link
      * BufferOverflowException} is thrown.
      *
      * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
+     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $type$s from the given
      * buffer into this buffer, starting at each buffer's current position.
      * The positions of both buffers are then incremented by <i>n</i>.
      *
@@ -723,14 +723,14 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The source buffer from which $fulltype$s are to be read;
+     *         The source buffer from which $type$s are to be read;
      *         must not be this buffer
      *
      * @return  This buffer
      *
      * @throws  BufferOverflowException
      *          If there is insufficient space in this buffer
-     *          for the remaining $fulltype$s in the source buffer
+     *          for the remaining $type$s in the source buffer
      *
      * @throws  IllegalArgumentException
      *          If the source buffer is this buffer
@@ -752,14 +752,14 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers $fulltype$s into this buffer from the given
-     * source array.  If there are more $fulltype$s to be copied from the array
+     * <p> This method transfers $type$s into this buffer from the given
+     * source array.  If there are more $type$s to be copied from the array
      * than remain in this buffer, that is, if
      * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferOverflowException} is
+     * $type$s are transferred and a {@link BufferOverflowException} is
      * thrown.
      *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
+     * <p> Otherwise, this method copies <tt>length</tt> $type$s from the
      * given array into this buffer, starting at the given offset in the array
      * and at the current position of this buffer.  The position of this buffer
      * is then incremented by <tt>length</tt>.
@@ -776,14 +776,14 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The array from which $fulltype$s are to be read
+     *         The array from which $type$s are to be read
      *
      * @param  offset
-     *         The offset within the array of the first $fulltype$ to be read;
+     *         The offset within the array of the first $type$ to be read;
      *         must be non-negative and no larger than <tt>array.length</tt>
      *
      * @param  length
-     *         The number of $fulltype$s to be read from the given array;
+     *         The number of $type$s to be read from the given array;
      *         must be non-negative and no larger than
      *         <tt>array.length - offset</tt>
      *
@@ -813,7 +813,7 @@
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> This method transfers the entire content of the given source
-     * $fulltype$ array into this buffer.  An invocation of this method of the
+     * $type$ array into this buffer.  An invocation of this method of the
      * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
      * invocation
      *
@@ -837,15 +837,15 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers $fulltype$s from the given string into this
-     * buffer.  If there are more $fulltype$s to be copied from the string than
+     * <p> This method transfers $type$s from the given string into this
+     * buffer.  If there are more $type$s to be copied from the string than
      * remain in this buffer, that is, if
      * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
+     * then no $type$s are transferred and a {@link
      * BufferOverflowException} is thrown.
      *
      * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
+     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $type$s
      * from the given string into this buffer, starting at the given
      * <tt>start</tt> index and at the current position of this buffer.  The
      * position of this buffer is then incremented by <i>n</i>.
@@ -862,15 +862,15 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The string from which $fulltype$s are to be read
+     *         The string from which $type$s are to be read
      *
      * @param  start
-     *         The offset within the string of the first $fulltype$ to be read;
+     *         The offset within the string of the first $type$ to be read;
      *         must be non-negative and no larger than
      *         <tt>string.length()</tt>
      *
      * @param  end
-     *         The offset within the string of the last $fulltype$ to be read,
+     *         The offset within the string of the last $type$ to be read,
      *         plus one; must be non-negative and no larger than
      *         <tt>string.length()</tt>
      *
@@ -921,7 +921,7 @@
     // -- Other stuff --
 
     /**
-     * Tells whether or not this buffer is backed by an accessible $fulltype$
+     * Tells whether or not this buffer is backed by an accessible $type$
      * array.
      *
      * <p> If this method returns <tt>true</tt> then the {@link #array() array}
@@ -936,7 +936,7 @@
     }
 
     /**
-     * Returns the $fulltype$ array that backs this
+     * Returns the $type$ array that backs this
      * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> Modifications to this buffer's content will cause the returned
@@ -993,17 +993,17 @@
     /**
      * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> The $fulltype$s between the buffer's current position and its limit,
+     * <p> The $type$s between the buffer's current position and its limit,
      * if any, are copied to the beginning of the buffer.  That is, the
-     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
-     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
-     * to index one, and so forth until the $fulltype$ at index
+     * $type$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
+     * to index zero, the $type$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
+     * to index one, and so forth until the $type$ at index
      * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
      * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
      * The buffer's position is then set to <i>n+1</i> and its limit is set to
      * its capacity.  The mark, if defined, is discarded.
      *
-     * <p> The buffer's position is set to the number of $fulltype$s copied,
+     * <p> The buffer's position is set to the number of $type$s copied,
      * rather than to zero, so that an invocation of this method can be
      * followed immediately by an invocation of another relative <i>put</i>
      * method. </p>
@@ -1032,7 +1032,7 @@
     public abstract $Type$Buffer compact();
 
     /**
-     * Tells whether or not this $fulltype$ buffer is direct. </p>
+     * Tells whether or not this $type$ buffer is direct. </p>
      *
      * @return  <tt>true</tt> if, and only if, this buffer is direct
      */
@@ -1098,6 +1098,13 @@
      *
      *   <li><p> The two sequences of remaining elements, considered
      *   independently of their starting positions, are pointwise equal.
+#if[floatingPointType]
+     *   This method considers two $type$ elements {@code a} and {@code b}
+     *   to be equal if
+     *   {@code (a == b) || ($Fulltype$.isNaN(a) && $Fulltype$.isNaN(b))}.
+     *   The values {@code -0.0} and {@code +0.0} are considered to be
+     *   equal, unlike {@link $Fulltype$#equals(Object)}.
+#end[floatingPointType]
      *   </p></li>
      *
      * </ol>
@@ -1118,24 +1125,37 @@
         if (this.remaining() != that.remaining())
             return false;
         int p = this.position();
-        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 != v2) {
-                if ((v1 != v1) && (v2 != v2))   // For float and double
-                    continue;
+        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
+            if (!equals(this.get(i), that.get(j)))
                 return false;
-            }
-        }
         return true;
     }
 
+    private static boolean equals($type$ x, $type$ y) {
+#if[floatingPointType]
+        return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y));
+#else[floatingPointType]
+        return x == y;
+#end[floatingPointType]
+    }
+
     /**
      * Compares this buffer to another.
      *
      * <p> Two $type$ buffers are compared by comparing their sequences of
      * remaining elements lexicographically, without regard to the starting
      * position of each sequence within its corresponding buffer.
+#if[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}, except that
+     * {@code -0.0} and {@code 0.0} are considered to be equal.
+     * {@code $Fulltype$.NaN} is considered by this method to be equal
+     * to itself and greater than all other {@code $type$} values
+     * (including {@code $Fulltype$.POSITIVE_INFINITY}).
+#else[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}.
+#end[floatingPointType]
      *
      * <p> A $type$ buffer is not comparable to any other type of object.
      *
@@ -1145,20 +1165,23 @@
     public int compareTo($Type$Buffer that) {
         int n = this.position() + Math.min(this.remaining(), that.remaining());
         for (int i = this.position(), j = that.position(); i < n; i++, j++) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 == v2)
-                continue;
-            if ((v1 != v1) && (v2 != v2))       // For float and double
-                continue;
-            if (v1 < v2)
-                return -1;
-            return +1;
+            int cmp = compare(this.get(i), that.get(j));
+            if (cmp != 0)
+                return cmp;
         }
         return this.remaining() - that.remaining();
     }
 
-
+    private static int compare($type$ x, $type$ y) {
+#if[floatingPointType]
+        return ((x < y)  ? -1 :
+                (x > y)  ? +1 :
+                (x == y) ?  0 :
+                $Fulltype$.isNaN(x) ? ($Fulltype$.isNaN(y) ? 0 : +1) : -1);
+#else[floatingPointType]
+        return $Fulltype$.compare(x, y);
+#end[floatingPointType]
+    }
 
     // -- Other char stuff --
 
@@ -1326,7 +1349,7 @@
     }
 
     /**
-     * Appends the specified $fulltype$  to this
+     * Appends the specified $type$  to this
      * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
@@ -1336,7 +1359,7 @@
      *     dst.put($x$) </pre>
      *
      * @param  $x$
-     *         The 16-bit $fulltype$ to append
+     *         The 16-bit $type$ to append
      *
      * @return  This buffer
      *
@@ -1362,10 +1385,10 @@
     /**
      * Retrieves this buffer's byte order.
      *
-     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
+     * <p> The byte order of $a$ $type$ buffer created by allocation or by
      * wrapping an existing <tt>$type$</tt> array is the {@link
      * ByteOrder#nativeOrder </code>native order<code>} of the underlying
-     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
+     * hardware.  The byte order of $a$ $type$ buffer created as a <a
      * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
      * byte buffer at the moment that the view is created.  </p>
      *
--- a/jdk/src/share/classes/java/rmi/activation/Activatable.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/rmi/activation/Activatable.java	Sun Jan 17 18:42:34 2010 -0800
@@ -73,7 +73,7 @@
      * can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int)
      * exportObject} method with this object, and the specified location,
      * data, restart mode, and port.  Subsequent calls to {@link #getID}
      * will return the activation identifier returned from the call to
@@ -120,7 +120,7 @@
      * can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * exportObject} method with this object, and the specified location,
      * data, restart mode, port, and client and server socket factories.
      * Subsequent calls to {@link #getID} will return the activation
@@ -312,7 +312,7 @@
      * separately, so that exceptions can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * exportObject} method with the specified object, location, data,
      * restart mode, and port, and <code>null</code> for both client and
      * server socket factories, and then returns the resulting activation
--- a/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java	Sun Jan 17 18:42:34 2010 -0800
@@ -187,7 +187,7 @@
      * host that accepts requests on the specified <code>port</code>.
      *
      * <p>The <code>Registry</code> instance is exported as if the static
-     * {@link UnicastRemoteObject.exportObject(Remote,int)
+     * {@link UnicastRemoteObject#exportObject(Remote,int)
      * UnicastRemoteObject.exportObject} method is invoked, passing the
      * <code>Registry</code> instance and the specified <code>port</code> as
      * arguments, except that the <code>Registry</code> instance is
@@ -213,7 +213,7 @@
      *
      * <p>The <code>Registry</code> instance is exported as if
      * the static {@link
-     * UnicastRemoteObject.exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
+     * UnicastRemoteObject#exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * UnicastRemoteObject.exportObject} method is invoked, passing the
      * <code>Registry</code> instance, the specified <code>port</code>, the
      * specified <code>RMIClientSocketFactory</code>, and the specified
--- a/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Sun Jan 17 18:42:34 2010 -0800
@@ -138,7 +138,6 @@
      * instance
      * @throws  Throwable the exception to throw from the method invocation
      * on the proxy instance
-     * @see
      **/
     public Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable
--- a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java	Sun Jan 17 18:42:34 2010 -0800
@@ -216,7 +216,7 @@
     /**
      * Returns the reason that the validation failed. The reason is
      * associated with the index of the certificate returned by
-     * {@link getIndex}.
+     * {@link #getIndex}.
      *
      * @return the reason that the validation failed, or
      *    <code>BasicReason.UNSPECIFIED</code> if a reason has not been
--- a/jdk/src/share/classes/java/text/Bidi.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/text/Bidi.java	Sun Jan 17 18:42:34 2010 -0800
@@ -121,9 +121,9 @@
      *
      * @param paragraph a paragraph of text with optional character and paragraph attribute information
      *
-     * @see TextAttribute#BIDI_EMBEDDING
-     * @see TextAttribute#NUMERIC_SHAPING
-     * @see TextAttribute#RUN_DIRECTION
+     * @see java.awt.font.TextAttribute#BIDI_EMBEDDING
+     * @see java.awt.font.TextAttribute#NUMERIC_SHAPING
+     * @see java.awt.font.TextAttribute#RUN_DIRECTION
      */
     public Bidi(AttributedCharacterIterator paragraph) {
         if (paragraph == null) {
--- a/jdk/src/share/classes/java/util/Objects.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/util/Objects.java	Sun Jan 17 18:42:34 2010 -0800
@@ -119,7 +119,7 @@
     *
     * @param values the values to be hashed
     * @return a hash value of the sequence of input values
-    * @see Arrays#hashCode
+    * @see Arrays#hashCode(Object[])
     * @see List#hashCode
     */
     public static int hash(Object... values) {
--- a/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java	Sun Jan 17 18:42:34 2010 -0800
@@ -51,7 +51,7 @@
  * The {@link PlatformManagedObject#getObjectName} method
  * can be used to obtain its {@code ObjectName}.
  *
- * @See java.lang.management.PlatformManagedObject
+ * @see java.lang.management.PlatformManagedObject
  *
  * @author  Mandy Chung
  * @since   1.7
--- a/jdk/src/share/classes/javax/accessibility/AccessibleContext.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleContext.java	Sun Jan 17 18:42:34 2010 -0800
@@ -296,7 +296,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleTextSequence
+     * @see AccessibleTextSequence
      */
     public static final String ACCESSIBLE_TEXT_PROPERTY
         = "AccessibleText";
@@ -311,7 +311,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleTextSequence
+     * @see AccessibleTextSequence
      *
      * @since 1.5
      */
@@ -334,7 +334,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleAttributeSequence
+     * @see AccessibleAttributeSequence
      *
      * @since 1.5
      */
--- a/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java	Sun Jan 17 18:42:34 2010 -0800
@@ -45,7 +45,6 @@
  * @see Accessible#getAccessibleContext
  * @see AccessibleContext
  * @see AccessibleContext#getAccessibleText
- * @see AccessibleText.AccessibleTextChunk
  *
  * @author       Peter Korn
  * @author       Lynn Monsanto
--- a/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java	Sun Jan 17 18:42:34 2010 -0800
@@ -32,16 +32,11 @@
  * the standard mechanism for an assistive technology to determine the
  * key bindings which exist for this object.
  * Any object that has such key bindings should support this
- * interface.  Applications can determine if an object supports the
- * AccessibleKeyBinding interface by first obtaining its AccessibleContext
- * (see @link Accessible} and then calling the
- * {@link AccessibleContext#getAccessibleKeyBinding} method.  If the return
- * value is not null, the object supports this interface.
+ * interface.
  *
  * @see Accessible
  * @see Accessible#getAccessibleContext
  * @see AccessibleContext
- * @see AccessibleContext#getAccessibleKeyBinding
  *
  * @author      Lynn Monsanto
  * @since 1.4
@@ -58,21 +53,7 @@
     /**
      * Returns a key binding for this object.  The value returned is an
      * java.lang.Object which must be cast to appropriate type depending
-     * on the underlying implementation of the key.  For example, if the
-     * Object returned is a javax.swing.KeyStroke, the user of this
-     * method should do the following:
-     * <nf><code>
-     * Component c = <get the component that has the key bindings>
-     * AccessibleContext ac = c.getAccessibleContext();
-     * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
-     * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
-     *     Object o = akb.getAccessibleKeyBinding(i);
-     *     if (o instanceof javax.swing.KeyStroke) {
-     *         javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
-     *         <do something with the key binding>
-     *     }
-     * }
-     * </code></nf>
+     * on the underlying implementation of the key.
      *
      * @param i zero-based index of the key bindings
      * @return a javax.lang.Object which specifies the key binding
--- a/jdk/src/share/classes/org/ietf/jgss/GSSName.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/org/ietf/jgss/GSSName.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 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
@@ -103,11 +103,12 @@
      * follows: service@hostname.<p>
      *
      * It represents the following Oid value:<br>
-     * <code>{ 1(iso), 3(org), 6(dod), 1(internet), 5(security),
-     * 6(nametypes), 2(gss-host-based-services) }</code>
+     *  <code>{ iso(1) member-body(2) United
+     * States(840) mit(113554) infosys(1) gssapi(2) generic(1) service_name(4)
+     * }</code>
      */
     public static final Oid NT_HOSTBASED_SERVICE
-        = Oid.getInstance("1.3.6.1.5.6.2");
+        = Oid.getInstance("1.2.840.113554.1.2.1.4");
 
     /**
      * Name type to indicate a named user on a local system.<p>
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Sun Jan 17 18:42:34 2010 -0800
@@ -326,7 +326,7 @@
         }
 
         // generate references and signature value
-        List allReferences = new ArrayList(si.getReferences());
+        List allReferences = new ArrayList();
 
         // traverse the Signature and register all objects with IDs that
         // may contain References
@@ -356,6 +356,9 @@
                 }
             }
         }
+        // always add SignedInfo references after Manifest references so
+        // that Manifest reference are digested first
+        allReferences.addAll(si.getReferences());
 
         // generate/digest each reference
         for (int i = 0, size = allReferences.size(); i < size; i++) {
--- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 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
@@ -89,6 +89,11 @@
         Oid[] retVal = new Oid[mechs.length];
         int pos = 0;
 
+        // Compatibility with RFC 2853 old NT_HOSTBASED_SERVICE value.
+        if (nameType.equals(GSSNameImpl.oldHostbasedServiceName)) {
+            nameType = GSSName.NT_HOSTBASED_SERVICE;
+        }
+
         // Iterate thru all mechs in GSS
         for (int i = 0; i < mechs.length; i++) {
             // what nametypes does this mech support?
--- a/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,29 @@
 
 public class GSSNameImpl implements GSSName {
 
+    /**
+     * The old Oid used in RFC 2853. Now supported as
+     * input parameters in:
+     *
+     * 1. The four overloaded GSSManager.createName(*) methods
+     * 2. GSSManager.getMechsForName(Oid)
+     *
+     * Note that even if a GSSName is created with this old Oid,
+     * its internal name type and getStringNameType() output are
+     * always the new value.
+     */
+    final static Oid oldHostbasedServiceName;
+
+    static {
+        Oid tmp = null;
+        try {
+            tmp = new Oid("1.3.6.1.5.6.2");
+        } catch (Exception e) {
+            // should never happen
+        }
+        oldHostbasedServiceName = tmp;
+    }
+
     private GSSManagerImpl gssManager = null;
 
     /*
@@ -134,6 +157,9 @@
                         Oid mech)
         throws GSSException {
 
+        if (oldHostbasedServiceName.equals(appNameType)) {
+            appNameType = GSSName.NT_HOSTBASED_SERVICE;
+        }
         if (appName == null)
             throw new GSSExceptionImpl(GSSException.BAD_NAME,
                                    "Cannot import null name");
--- a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 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
@@ -66,9 +66,6 @@
     public static final Oid NT_GSS_KRB5_PRINCIPAL =
                 GSSUtil.createOid("1.2.840.113554.1.2.2.1");
 
-    public static final Oid NT_HOSTBASED_SERVICE2 =
-                GSSUtil.createOid("1.2.840.113554.1.2.1.4");
-
     private static final String DEFAULT_HANDLER =
             "auth.login.defaultCallbackHandler";
 
--- a/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2010 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
@@ -55,8 +55,7 @@
     static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
 
     private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {
-        if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType) ||
-            GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) {
+        if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
             Oid[] supportedNTs = null;
             try {
                 supportedNTs = stub.inquireNamesForMech();
@@ -83,15 +82,9 @@
                     if (supportedNTs[i].equals(nameType)) return nameType;
                 }
                 // Special handling the specified name type
-                if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
-                    SunNativeProvider.debug("Override " + nameType +
-                        " with mechanism default(null)");
-                    return null; // Use mechanism specific default
-                } else {
-                    SunNativeProvider.debug("Override " + nameType +
-                        " with " + GSSUtil.NT_HOSTBASED_SERVICE2);
-                    return GSSUtil.NT_HOSTBASED_SERVICE2;
-                }
+                SunNativeProvider.debug("Override " + nameType +
+                    " with mechanism default(null)");
+                return null; // Use mechanism specific default
             }
         }
         return nameType;
--- a/jdk/src/share/classes/sun/security/krb5/Config.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java	Sun Jan 17 18:42:34 2010 -0800
@@ -109,6 +109,7 @@
     public static synchronized void refresh() throws KrbException {
         singleton = new Config();
         KeyTab.refresh();
+        KrbKdcReq.KdcAccessibility.reset();
     }
 
 
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Sun Jan 17 18:42:34 2010 -0800
@@ -512,6 +512,23 @@
     }
 
     /**
+     * Determines if a kvno matches another kvno. Used in the method
+     * findKey(type, kvno, keys). Always returns true if either input
+     * is null or zero, in case any side does not have kvno info available.
+     *
+     * Note: zero is included because N/A is not a legal value for kvno
+     * in javax.security.auth.kerberos.KerberosKey. Therefore, the info
+     * that the kvno is N/A might be lost when converting between this
+     * class and KerberosKey.
+     */
+    private static boolean versionMatches(Integer v1, Integer v2) {
+        if (v1 == null || v1 == 0 || v2 == null || v2 == 0) {
+            return true;
+        }
+        return v1.equals(v2);
+    }
+
+    /**
      * Find a key with given etype and kvno
      * @param kvno if null, return any (first?) key
      */
@@ -525,15 +542,20 @@
         }
 
         int ktype;
+        boolean etypeFound = false;
         for (int i = 0; i < keys.length; i++) {
             ktype = keys[i].getEType();
             if (EType.isSupported(ktype)) {
                 Integer kv = keys[i].getKeyVersionNumber();
-                if (etype == ktype && (kvno == null || kvno.equals(kv))) {
-                    return keys[i];
+                if (etype == ktype) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
+                        return keys[i];
+                    }
                 }
             }
         }
+
         // Key not found.
         // allow DES key to be used for the DES etypes
         if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
@@ -543,12 +565,16 @@
                 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
                         ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
                     Integer kv = keys[i].getKeyVersionNumber();
-                    if (kvno == null || kvno.equals(kv)) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
                         return new EncryptionKey(etype, keys[i].getBytes());
                     }
                 }
             }
         }
+        if (etypeFound) {
+            throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
+        }
         return null;
     }
 }
--- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java	Sun Jan 17 18:42:34 2010 -0800
@@ -31,25 +31,26 @@
 
 package sun.security.krb5;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Locale;
 import sun.security.krb5.internal.Krb5;
 import sun.security.krb5.internal.UDPClient;
 import sun.security.krb5.internal.TCPClient;
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
 import java.util.StringTokenizer;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
 
 public abstract class KrbKdcReq {
 
-    /**
-     * Default port for a KDC.
-     */
-    private static final int DEFAULT_KDC_PORT = Krb5.KDC_INET_DEFAULT_PORT;
-
     // Currently there is no option to specify retries
     // in the kerberos configuration file
 
@@ -66,7 +67,48 @@
 
     private static int udpPrefLimit = -1;
 
+    private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy";
+
+    /**
+     * What to do when a KDC is unavailable, specified in the
+     * java.security file with key krb5.kdc.bad.policy.
+     * Possible values can be TRY_LAST or TRY_LESS
+     */
+    private enum BpType {
+        NONE, TRY_LAST, TRY_LESS
+    }
+    private static int tryLessMaxRetries = 1;
+    private static int tryLessTimeout = 5000;
+
+    private static final BpType badPolicy;
+
     static {
+        String value = AccessController.doPrivileged(
+        new PrivilegedAction<String>() {
+            public String run() {
+                return Security.getProperty(BAD_POLICY_KEY);
+            }
+        });
+        if (value != null) {
+            value = value.toLowerCase(Locale.ENGLISH);
+            String[] ss = value.split(":");
+            if ("tryless".equals(ss[0])) {
+                if (ss.length > 1) {
+                    String[] params = ss[1].split(",");
+                    tryLessMaxRetries = Integer.parseInt(params[0]);
+                    if (params.length > 1) {
+                        tryLessTimeout = Integer.parseInt(params[1]);
+                    }
+                }
+                badPolicy = BpType.TRY_LESS;
+            } else if ("trylast".equals(ss[0])) {
+                badPolicy = BpType.TRY_LAST;
+            } else {
+                badPolicy = BpType.NONE;
+            }
+        } else {
+            badPolicy = BpType.NONE;
+        }
 
         /*
          * Get default timeout.
@@ -131,22 +173,16 @@
             }
         }
 
-        /*
-         * Get timeout.
-         */
-
-        int timeout = getKdcTimeout(realm);
-
         String kdcList = cfg.getKDCList(realm);
         if (kdcList == null) {
             throw new KrbException("Cannot get kdc for realm " + realm);
         }
         String tempKdc = null; // may include the port number also
-        StringTokenizer st = new StringTokenizer(kdcList);
-        while (st.hasMoreTokens()) {
-            tempKdc = st.nextToken();
+        for (String tmp: KdcAccessibility.list(kdcList)) {
+            tempKdc = tmp;
             try {
                 send(realm,tempKdc,useTCP);
+                KdcAccessibility.removeBad(tempKdc);
                 break;
             } catch (Exception e) {
                 if (DEBUG) {
@@ -154,6 +190,7 @@
                             tempKdc);
                     e.printStackTrace(System.out);
                 }
+                KdcAccessibility.addBad(tempKdc);
                 savedException = e;
             }
         }
@@ -174,16 +211,21 @@
 
         if (obuf == null)
             return;
-        PrivilegedActionException savedException = null;
+
         int port = Krb5.KDC_INET_DEFAULT_PORT;
+        int retries = DEFAULT_KDC_RETRY_LIMIT;
+        int timeout = getKdcTimeout(realm);
 
-        /*
-         * Get timeout.
-         */
-        int timeout = getKdcTimeout(realm);
-        /*
-         * Get port number for this KDC.
-         */
+        if (badPolicy == BpType.TRY_LESS &&
+                KdcAccessibility.isBad(tempKdc)) {
+            if (retries > tryLessMaxRetries) {
+                retries = tryLessMaxRetries; // less retries
+            }
+            if (timeout > tryLessTimeout) {
+                timeout = tryLessTimeout; // less time
+            }
+        }
+
         String kdc = null;
         String portStr = null;
 
@@ -225,12 +267,12 @@
                                +  port +  ", timeout="
                                + timeout
                                + ", number of retries ="
-                               + DEFAULT_KDC_RETRY_LIMIT
+                               + retries
                                + ", #bytes=" + obuf.length);
         }
 
         KdcCommunication kdcCommunication =
-            new KdcCommunication(kdc, port, useTCP, timeout, obuf);
+            new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf);
         try {
             ibuf = AccessController.doPrivileged(kdcCommunication);
             if (DEBUG) {
@@ -258,14 +300,16 @@
         private int port;
         private boolean useTCP;
         private int timeout;
+        private int retries;
         private byte[] obuf;
 
         public KdcCommunication(String kdc, int port, boolean useTCP,
-                                int timeout, byte[] obuf) {
+                                int timeout, int retries, byte[] obuf) {
             this.kdc = kdc;
             this.port = port;
             this.useTCP = useTCP;
             this.timeout = timeout;
+            this.retries = retries;
             this.obuf = obuf;
         }
 
@@ -294,7 +338,7 @@
             } else {
                 // For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to
                 // get the response
-                for (int i=1; i <= DEFAULT_KDC_RETRY_LIMIT; i++) {
+                for (int i=1; i <= retries; i++) {
                     UDPClient kdcClient = new UDPClient(kdc, port, timeout);
 
                     if (DEBUG) {
@@ -310,7 +354,7 @@
                          * Send the data to the kdc.
                          */
 
-                    kdcClient.send(obuf);
+                        kdcClient.send(obuf);
 
                         /*
                          * And get a response.
@@ -323,7 +367,7 @@
                                 System.out.println ("SocketTimeOutException with " +
                                                     "attempt: " + i);
                             }
-                            if (i == DEFAULT_KDC_RETRY_LIMIT) {
+                            if (i == retries) {
                                 ibuf = null;
                                 throw se;
                             }
@@ -385,4 +429,67 @@
 
         return -1;
     }
+
+    /**
+     * Maintains a KDC accessible list. Unavailable KDCs are put into a
+     * blacklist, when a KDC in the blacklist is available, it's removed
+     * from there. No insertion order in the blacklist.
+     *
+     * There are two methods to deal with KDCs in the blacklist. 1. Only try
+     * them when there's no KDC not on the blacklist. 2. Still try them, but
+     * with lesser number of retries and smaller timeout value.
+     */
+    static class KdcAccessibility {
+        // Known bad KDCs
+        private static Set<String> bads = new HashSet<String>();
+
+        private static synchronized void addBad(String kdc) {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: add " + kdc);
+            }
+            bads.add(kdc);
+        }
+
+        private static synchronized void removeBad(String kdc) {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: remove " + kdc);
+            }
+            bads.remove(kdc);
+        }
+
+        private static synchronized boolean isBad(String kdc) {
+            return bads.contains(kdc);
+        }
+
+        public static synchronized void reset() {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: reset");
+            }
+            bads.clear();
+        }
+
+        // Returns a preferred KDC list by putting the bad ones at the end
+        private static synchronized String[] list(String kdcList) {
+            StringTokenizer st = new StringTokenizer(kdcList);
+            List<String> list = new ArrayList<String>();
+            if (badPolicy == BpType.TRY_LAST) {
+                List<String> badkdcs = new ArrayList<String>();
+                while (st.hasMoreTokens()) {
+                    String t = st.nextToken();
+                    if (bads.contains(t)) badkdcs.add(t);
+                    else list.add(t);
+                }
+                // Bad KDCs are put at last
+                list.addAll(badkdcs);
+            } else {
+                // All KDCs are returned in their original order,
+                // This include TRY_LESS and NONE
+                while (st.hasMoreTokens()) {
+                    list.add(st.nextToken());
+                }
+            }
+            return list.toArray(new String[list.size()]);
+        }
+    }
 }
+
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2010 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
@@ -50,11 +50,12 @@
 import sun.security.krb5.internal.crypto.KeyUsage;
 
 import sun.security.jgss.krb5.Krb5Util;
+import sun.security.krb5.KrbException;
+import sun.security.krb5.internal.Krb5;
 
 import sun.security.ssl.Debug;
 import sun.security.ssl.HandshakeInStream;
 import sun.security.ssl.HandshakeOutStream;
-import sun.security.ssl.KerberosClientKeyExchange;
 import sun.security.ssl.ProtocolVersion;
 
 /**
@@ -188,7 +189,14 @@
             // See if we have the right key to decrypt the ticket to get
             // the session key.
             int encPartKeyType = encPart.getEType();
-            KerberosKey dkey = findKey(encPartKeyType, serverKeys);
+            Integer encPartKeyVersion = encPart.getKeyVersionNumber();
+            KerberosKey dkey = null;
+            try {
+                dkey = findKey(encPartKeyType, encPartKeyVersion, serverKeys);
+            } catch (KrbException ke) { // a kvno mismatch
+                throw new IOException(
+                        "Cannot find key matching version number", ke);
+            }
             if (dkey == null) {
                 // %%% Should print string repr of etype
                 throw new IOException(
@@ -355,12 +363,34 @@
         return localPrincipal;
     }
 
-    private static KerberosKey findKey(int etype, KerberosKey[] keys) {
+    /**
+     * Determines if a kvno matches another kvno. Used in the method
+     * findKey(etype, version, keys). Always returns true if either input
+     * is null or zero, in case any side does not have kvno info available.
+     *
+     * Note: zero is included because N/A is not a legal value for kvno
+     * in javax.security.auth.kerberos.KerberosKey. Therefore, the info
+     * that the kvno is N/A might be lost when converting between
+     * EncryptionKey and KerberosKey.
+     */
+    private static boolean versionMatches(Integer v1, int v2) {
+        if (v1 == null || v1 == 0 || v2 == 0) {
+            return true;
+        }
+        return v1.equals(v2);
+    }
+
+    private static KerberosKey findKey(int etype, Integer version,
+            KerberosKey[] keys) throws KrbException {
         int ktype;
+        boolean etypeFound = false;
         for (int i = 0; i < keys.length; i++) {
             ktype = keys[i].getKeyType();
             if (etype == ktype) {
-                return keys[i];
+                etypeFound = true;
+                if (versionMatches(version, keys[i].getVersionNumber())) {
+                    return keys[i];
+                }
             }
         }
         // Key not found.
@@ -370,14 +400,20 @@
             for (int i = 0; i < keys.length; i++) {
                 ktype = keys[i].getKeyType();
                 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
-                    ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
-                    return new KerberosKey(keys[i].getPrincipal(),
-                        keys[i].getEncoded(),
-                        etype,
-                        keys[i].getVersionNumber());
+                        ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
+                    etypeFound = true;
+                    if (versionMatches(version, keys[i].getVersionNumber())) {
+                        return new KerberosKey(keys[i].getPrincipal(),
+                            keys[i].getEncoded(),
+                            etype,
+                            keys[i].getVersionNumber());
+                    }
                 }
             }
         }
+        if (etypeFound) {
+            throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
+        }
         return null;
     }
 }
--- a/jdk/src/share/lib/security/java.security	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/lib/security/java.security	Sun Jan 17 18:42:34 2010 -0800
@@ -55,10 +55,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -72,7 +72,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -149,7 +149,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -168,10 +168,10 @@
 # is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +183,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +192,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +201,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +213,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +237,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,4 +259,31 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
+#
+# Policy for failed Kerberos KDC lookups:
+#
+# When a KDC is unavailable (network error, service failure, etc), it is
+# put inside a blacklist and accessed less often for future requests. The
+# value (case-insensitive) for this policy can be:
+#
+# tryLast
+#    KDCs in the blacklist are always tried after those not on the list.
+#
+# tryLess[:max_retries,timeout]
+#    KDCs in the blacklist are still tried by their order in the configuration,
+#    but with smaller max_retries and timeout values. max_retries and timeout
+#    are optional numerical parameters (default 1 and 5000, which means once
+#    and 5 seconds). Please notes that if any of the values defined here is
+#    more than what is defined in krb5.conf, it will be ignored.
+#
+# Whenever a KDC is detected as available, it is removed from the blacklist.
+# The blacklist is reset when krb5.conf is reloaded. You can add
+# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
+# reloaded whenever a JAAS authentication is attempted.
+#
+# Example,
+#   krb5.kdc.bad.policy = tryLast
+#   krb5.kdc.bad.policy = tryLess:2,2000
+krb5.kdc.bad.policy = tryLast
+
--- a/jdk/src/share/native/java/lang/StrictMath.c	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/share/native/java/lang/StrictMath.c	Sun Jan 17 18:42:34 2010 -0800
@@ -95,18 +95,6 @@
 }
 
 JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_ceil(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jceil((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_floor(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jfloor((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
 Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
 {
     return (jdouble) jatan2((double)d1, (double)d2);
--- a/jdk/src/windows/native/java/net/SocketInputStream.c	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/src/windows/native/java/net/SocketInputStream.c	Sun Jan 17 18:42:34 2010 -0800
@@ -121,6 +121,9 @@
             newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
             if (newfd == -1) {
                 NET_ThrowSocketException(env, "Socket Closed");
+                if (bufP != BUF) {
+                    free(bufP);
+                }
                 return -1;
             }
         }
--- a/jdk/test/Makefile	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/Makefile	Sun Jan 17 18:42:34 2010 -0800
@@ -291,7 +291,7 @@
   fi ; \
   testExitCode=`$(CAT) $(EXITCODE)`; \
   $(ECHO) "EXIT CODE: $${testExitCode}"; \
-  exit ${testExitCode}
+  exit $${testExitCode}
 
 BUNDLE_UP_AND_EXIT = \
 ( \
@@ -300,7 +300,7 @@
   $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
   $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
   if [ -r "$${_summary}" ] ; then \
-    $(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \
+    $(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \
     $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
     $(EGREP) ' Passed\.' $(RUNLIST) \
       | $(EGREP) -v ' Error\.' \
@@ -370,7 +370,8 @@
 endif
 # With samevm, you cannot use -javaoptions?
 ifeq ($(USE_JTREG_SAMEVM),true)
-  EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
+  JTREG_SAMEVM_OPTION = -samevm
+  EXTRA_JTREG_OPTIONS += $(JTREG_SAMEVM_OPTION) $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
   JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%)
 else
   JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
@@ -418,8 +419,9 @@
 $(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
 endef
 define SummaryInfo
-$(ECHO) "Summary for: $?"
+$(ECHO) "########################################################"
 $(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
+$(ECHO) "########################################################"
 endef
 
 # ------------------------------------------------------------------
@@ -446,10 +448,14 @@
 jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
             java/beans/PropertyEditor
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_beans3
 jdk_beans3: java/beans/XMLEncoder
 	$(call RunOthervmBatch)
 
+# All beans tests
 jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3
 	@$(SummaryInfo)
 
@@ -475,6 +481,7 @@
 jdk_management2: com/sun/jmx com/sun/management sun/management
 	$(call RunOthervmBatch)
 
+# All management tests
 jdk_management: jdk_management1 jdk_management2
 	@$(SummaryInfo)
 
@@ -506,10 +513,14 @@
 jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
           java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_nio3
 jdk_nio3: com/sun/nio sun/nio
 	$(call RunOthervmBatch)
 
+# All nio tests
 jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
 	@$(SummaryInfo)
 
@@ -529,10 +540,14 @@
 JDK_ALL_TARGETS += jdk_security2
 jdk_security2: javax/crypto com/sun/crypto
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_security3
 jdk_security3: com/sun/security lib/security javax/security sun/security
 	$(call RunOthervmBatch)
 
+# All security tests
 jdk_security: jdk_security1 jdk_security2 jdk_security3
 	@$(SummaryInfo)
 
@@ -547,15 +562,18 @@
 jdk_text: java/text sun/text
 	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_tools1
 jdk_tools1: com/sun/jdi
 	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_tools2
 jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
 	$(call RunOthervmBatch)
 
+# All tools tests
 jdk_tools: jdk_tools1 jdk_tools2
 	@$(SummaryInfo)
 
@@ -567,7 +585,9 @@
 # ------------------------------------------------------------------
 
 # Run all tests
-jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS))
+FILTER_OUT_LIST=jdk_awt jdk_rmi jdk_swing
+JDK_ALL_STABLE_TARGETS := $(filter-out $(FILTER_OUT_LIST), $(JDK_ALL_TARGETS))
+jdk_all: $(JDK_ALL_STABLE_TARGETS)
 	@$(SummaryInfo)
 
 # These are all phony targets
@@ -581,16 +601,22 @@
 JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
 # Only run automatic tests
 JTREG_BASIC_OPTIONS += -a
+# Always turn on assertions
+JTREG_ASSERT_OPTION = -ea -esa
+JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
 # Report details on all failed or error tests, times too
 JTREG_BASIC_OPTIONS += -v:fail,error,time
 # Retain all files for failing tests
 JTREG_BASIC_OPTIONS += -retain:fail,error
 # Ignore tests are not run and completely silent about it
-JTREG_BASIC_OPTIONS += -ignore:quiet
-# Multiple by 2 the timeout numbers
-JTREG_BASIC_OPTIONS += -timeoutFactor:2
+JTREG_IGNORE_OPTION = -ignore:quiet
+JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
+# Multiple by 4 the timeout numbers
+JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
+JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
 # Boost the max memory for jtreg to avoid gc thrashing
-JTREG_BASIC_OPTIONS += -J-Xmx512m
+JTREG_MEMORY_OPTION = -J-Xmx512m
+JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
 
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
--- a/jdk/test/ProblemList.txt	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/ProblemList.txt	Sun Jan 17 18:42:34 2010 -0800
@@ -431,6 +431,11 @@
 
 # jdk_management
 
+# Fails on Windows 2000, Test failed for iiop java.lang.NullPointerException
+#  at org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(Unknown Source)
+#  at com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:653)
+javax/management/remote/mandatory/connection/ReconnectTest.java generic-all
+
 # Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke
 javax/management/remote/mandatory/threads/ExecutorTest.java 	generic-all
 
@@ -494,10 +499,6 @@
 # Problems with rounding add failures on solaris-sparcv9 and -server
 java/math/BigDecimal/AddTests.java			 	solaris-sparcv9
 
-# Problems on windows with samevm, missing inputstream close()?
-# Also times out on solaris-sparcv9 -server
-java/math/BigInteger/BigIntegerTest.java		 	generic-all
-
 # Should be samevm? But seems problematic with samevm on windows
 java/math/BigInteger/ModPow65537.java			 	generic-all
 
@@ -581,6 +582,14 @@
 # Suspect many of these tests auffer from using fixed ports, no concrete 
 #   evidence.
 
+# Dies on Solaris 10 sparc and sparcv9, Linux  -ea -esa with 
+#   Interrupted or IO exception, maybe writing to non-unique named file?
+com/sun/net/httpserver/bugs/B6373555.java			generic-all
+
+# Dies on pretty much all platforms when run with -ea -esa, Assertion error
+java/net/CookieHandler/TestHttpCookie.java			generic-all
+java/net/URLClassLoader/closetest/CloseTest.java		generic-all
+
 # Fails on OpenSolaris, BindException unexpected 
 java/net/BindException/Test.java				generic-all
 
@@ -717,6 +726,9 @@
 # Connection refused, windows samevm
 sun/net/www/protocol/http/DigestTest.java			generic-all
 
+# Fails on Fedora 9 32bit & 64bit & Solaris 10, wrong proxy for http://localhost/index.html
+java/net/ProxySelector/B6737819.java				generic-all
+
 ############################################################################
 
 # jdk_nio
@@ -724,6 +736,33 @@
 # Suspect many of these tests auffer from using fixed ports, no concrete 
 #   evidence.
 
+# Fails with -ea -esa, Assertion error, but only on Solaris 10 machines?
+com/sun/nio/sctp/SctpChannel/Send.java				generic-all
+com/sun/nio/sctp/SctpChannel/Shutdown.java			generic-all
+
+# Fails on Windows 2000, Can't delete test directory .\x.SetLastModified.dir
+#    at SetLastModified.main(SetLastModified.java:107)
+java/io/File/SetLastModified.java                               generic-all
+
+# Fails on Solaris 10 x64, address already in use
+java/nio/channels/DatagramChannel/SRTest.java			generic-all
+
+# Fails on Solaris 10 x86, times out
+java/nio/channels/DatagramChannel/Sender.java			generic-all
+
+# Fails on Fedora 9 x86, address in use
+java/nio/channels/Selector/SelectWrite.java			generic-all
+
+# Fails on Fedora 9 32bit times out
+java/nio/channels/DatagramChannel/EmptyBuffer.java		generic-all
+
+# Fails on Windows 2000, ExceptionInInitializerError
+#   in WindowsAsynchronousServerSocketChannelImpl.java:316
+java/nio/channels/AsynchronousChannelGroup/Unbounded.java	generic-all
+
+# Fails on Windows 2000,  times out
+java/nio/channels/FileChannel/Transfer.java			generic-all
+
 # Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses 
 #    from a channel that is bound to the wildcard address
 com/sun/nio/sctp/SctpChannel/Bind.java				generic-all
@@ -893,6 +932,48 @@
 
 # jdk_security
 
+# Fails with -ea -esa, but only on Solaris sparc? Suspect it is timing out
+sun/security/tools/keytool/standard.sh				generic-all
+
+# Fails on Solaris 10 X64, address already in use
+sun/security/krb5/auto/HttpNegotiateServer.java			generic-all
+
+# Fails on almost all platforms
+#   java.lang.UnsupportedClassVersionError: SerialTest : 
+#      Unsupported major.minor version 51.0
+#    at java.lang.ClassLoader.defineClass1(Native Method)
+sun/security/util/Oid/S11N.sh					generic-all
+
+# Fails on Fedora 9 32bit
+#  GSSException: Failure unspecified at GSS-API level (Mechanism level: 
+#    Invalid argument (400) - Cannot find key of appropriate type to decrypt 
+#    AP REP - DES CBC mode with MD5)
+#  at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:778)
+sun/security/krb5/auto/NonMutualSpnego.java			generic-all
+
+# Fails on Solaris 10 sparc, GSSException: Failure unspecified at GSS-API level
+#   Also fails on Windows 2000 similar way
+sun/security/krb5/auto/ok-as-delegate.sh			generic-all
+
+# Fails on Windows 2000, GSSException: Failure unspecified at GSS-API level
+#    (Mechanism level: Request is a replay (34))
+sun/security/krb5/auto/ok-as-delegate-xrealm.sh			generic-all
+
+# Fails on Windows 2000, ExceptionInInitializerError
+sun/security/mscapi/AccessKeyStore.sh				generic-all
+
+# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
+sun/security/pkcs11/KeyAgreement/TestDH.java			generic-all
+
+# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
+sun/security/pkcs11/fips/ClientJSSEServerJSSE.java		generic-all
+
+# Fails on Solaris 10, KrbException: Additional pre-authentication required (25)
+sun/security/krb5/auto/basic.sh					generic-all
+
+# Fails on Fedora 9 64bit, PKCS11Exception: CKR_DEVICE_ERROR
+sun/security/pkcs11/KeyAgreement/TestDH.java			generic-all
+
 # Run too slow on Solaris 10 sparc
 sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc
 sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc
@@ -1088,6 +1169,16 @@
 #  So most if not all tools tests are now being run with "othervm" mode.
 #  Some of these tools tests have a tendency to use fixed ports, bad idea.
 
+# Fails with -ea -esa on Solaris, Assertion error (Solaris specific test)
+com/sun/tracing/BasicFunctionality.java				generic-all
+
+# Fails on Fedora 9 32bit, jps output differs problem
+sun/tools/jstatd/jstatdDefaults.sh				generic-all
+
+# Fails on Linux Fedora 9 32bit, Could not read data for remote JVM 16133
+#       jstat output differs from expected output
+sun/tools/jstatd/jstatdExternalRegistry.sh			generic-all
+
 # Output of jps differs from expected output.
 #   Invalid argument count on solaris-sparc and x64
 sun/tools/jstatd/jstatdPort.sh					generic-all
@@ -1099,6 +1190,11 @@
 sun/tools/jps/jps-Vvml_2.sh					generic-all
 sun/tools/jps/jps-m_2.sh					generic-all
 
+# Fails on Solaris 10 sparcv9, shell exits with 1
+#  Turning off use of shared archive because of choice of garbage collector or large pages 
+#  Could not synchronize with target
+sun/tools/jps/jps-v_1.sh					generic-all
+
 # Fails on OpenSolaris "Could not synchronize with target"
 sun/tools/jps/jps-Defaults.sh					generic-all
 sun/tools/jps/jps-V_2.sh					generic-all
@@ -1160,6 +1256,12 @@
 
 # jdk_util
 
+# Fails with -ea -esa on all platforms with Assertion error
+java/util/ResourceBundle/Test4300693.java			generic-all
+
+# Failing on all -client 32bit platforms starting with b77? See 6908348.
+java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all
+
 # Assert error, failures, on Linux Fedora 9 -server
 #   Windows samevm failure, assert error "Passed = 134, failed = 2"
 java/util/Arrays/ArrayObjectMethods.java			generic-all
--- a/jdk/test/com/sun/jdi/NoLaunchOptionTest.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/com/sun/jdi/NoLaunchOptionTest.java	Sun Jan 17 18:42:34 2010 -0800
@@ -31,6 +31,9 @@
  *  @build VMConnection
  *  @run main/othervm NoLaunchOptionTest
  */
+
+import java.net.ServerSocket;
+
 public class NoLaunchOptionTest extends Object {
     private Process subprocess;
     private int subprocessStatus;
@@ -121,12 +124,19 @@
     }
 
     public static void main(String[] args) throws Exception {
+        // find a free port
+        ServerSocket ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
+        ss.close();
+        String address = String.valueOf(port);
+
         String javaExe = System.getProperty("java.home") +
             java.io.File.separator + "bin" +
             java.io.File.separator + "java";
         String targetClass = "NotAClass";
         String cmds [] = {javaExe,
-                          "-agentlib:jdwp=transport=dt_socket,address=8000," +
+                          "-agentlib:jdwp=transport=dt_socket,address=" +
+                          address + "," +
                           "onthrow=java.lang.ClassNotFoundException,suspend=n",
                           targetClass};
         NoLaunchOptionTest myTest = new NoLaunchOptionTest();
--- a/jdk/test/com/sun/jdi/OptionTest.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/com/sun/jdi/OptionTest.java	Sun Jan 17 18:42:34 2010 -0800
@@ -32,6 +32,9 @@
  *  @run compile -g VMConnection.java
  *  @run main/othervm OptionTest
  */
+
+import java.net.ServerSocket;
+
 public class OptionTest extends Object {
     private Process subprocess;
     private int subprocessStatus;
@@ -122,12 +125,18 @@
     }
 
     public static void main(String[] args) throws Exception {
+        // find a free port
+        ServerSocket ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
+        ss.close();
+        String address = String.valueOf(port);
+
         String javaExe = System.getProperty("java.home") +
             java.io.File.separator + "bin" +
             java.io.File.separator + "java";
         String targetClass = "HelloWorld";
         String baseOptions = "transport=dt_socket" +
-                              ",address=8000" +
+                              ",address=" + address +
                               ",server=y" +
                               ",suspend=n";
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Math/CeilAndFloorTests.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6908131
+ * @summary Check for correct implementation of Math.ceil and Math.floor
+ */
+
+import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
+
+public class CeilAndFloorTests {
+    private static int testCeilCase(double input, double expected) {
+        int failures = 0;
+        failures += Tests.test("Math.ceil",  input, Math.ceil(input),   expected);
+        failures += Tests.test("StrictMath.ceil",  input, StrictMath.ceil(input), expected);
+        return failures;
+    }
+
+    private static int testFloorCase(double input, double expected) {
+        int failures = 0;
+        failures += Tests.test("Math.floor",  input, Math.floor(input),   expected);
+        failures += Tests.test("StrictMath.floor",  input, StrictMath.floor(input), expected);
+        return failures;
+    }
+
+    private static int nearIntegerTests() {
+        int failures = 0;
+
+        double [] fixedPoints = {
+            -0.0,
+             0.0,
+            -1.0,
+             1.0,
+            -0x1.0p52,
+             0x1.0p52,
+            -Double.MAX_VALUE,
+             Double.MAX_VALUE,
+             Double.NEGATIVE_INFINITY,
+             Double.POSITIVE_INFINITY,
+             Double.NaN,
+        };
+
+        for(double fixedPoint : fixedPoints) {
+            failures += testCeilCase(fixedPoint, fixedPoint);
+            failures += testFloorCase(fixedPoint, fixedPoint);
+        }
+
+        for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            double powerOfTwo   = Math.scalb(1.0, i);
+            double neighborDown = FpUtils.nextDown(powerOfTwo);
+            double neighborUp   = Math.nextUp(powerOfTwo);
+
+            if (i < 0) {
+                failures += testCeilCase( powerOfTwo,  1.0);
+                failures += testCeilCase(-powerOfTwo, -0.0);
+
+                failures += testFloorCase( powerOfTwo,  0.0);
+                failures += testFloorCase(-powerOfTwo, -1.0);
+
+                failures += testCeilCase( neighborDown, 1.0);
+                failures += testCeilCase(-neighborDown, -0.0);
+
+                failures += testFloorCase( neighborUp,  0.0);
+                failures += testFloorCase(-neighborUp, -1.0);
+            } else {
+                failures += testCeilCase(powerOfTwo, powerOfTwo);
+                failures += testFloorCase(powerOfTwo, powerOfTwo);
+
+                if (neighborDown==Math.rint(neighborDown)) {
+                    failures += testCeilCase( neighborDown,  neighborDown);
+                    failures += testCeilCase(-neighborDown, -neighborDown);
+
+                    failures += testFloorCase( neighborDown, neighborDown);
+                    failures += testFloorCase(-neighborDown,-neighborDown);
+                } else {
+                    failures += testCeilCase( neighborDown, powerOfTwo);
+                    failures += testFloorCase(-neighborDown, -powerOfTwo);
+                }
+
+                if (neighborUp==Math.rint(neighborUp)) {
+                    failures += testCeilCase(neighborUp, neighborUp);
+                    failures += testCeilCase(-neighborUp, -neighborUp);
+
+                    failures += testFloorCase(neighborUp, neighborUp);
+                    failures += testFloorCase(-neighborUp, -neighborUp);
+                } else {
+                    failures += testFloorCase(neighborUp, powerOfTwo);
+                    failures += testCeilCase(-neighborUp, -powerOfTwo);
+                }
+            }
+        }
+
+        for(int i = -(0x10000); i <= 0x10000; i++) {
+            double d = (double) i;
+            double neighborDown = FpUtils.nextDown(d);
+            double neighborUp   = Math.nextUp(d);
+
+            failures += testCeilCase( d, d);
+            failures += testCeilCase(-d, -d);
+
+            failures += testFloorCase( d, d);
+            failures += testFloorCase(-d, -d);
+
+            if (Math.abs(d) > 1.0) {
+                failures += testCeilCase( neighborDown, d);
+                failures += testCeilCase(-neighborDown, -d+1);
+
+                failures += testFloorCase( neighborUp, d);
+                failures += testFloorCase(-neighborUp, -d-1);
+            }
+        }
+
+        return failures;
+    }
+
+    public static int roundingTests() {
+        int failures = 0;
+        double [][] testCases = {
+            { Double.MIN_VALUE,                           1.0},
+            {-Double.MIN_VALUE,                          -0.0},
+            { FpUtils.nextDown(DoubleConsts.MIN_NORMAL),  1.0},
+            {-FpUtils.nextDown(DoubleConsts.MIN_NORMAL), -0.0},
+            { DoubleConsts.MIN_NORMAL,                    1.0},
+            {-DoubleConsts.MIN_NORMAL,                   -0.0},
+
+            { 0.1,                                        1.0},
+            {-0.1,                                       -0.0},
+
+            { 0.5,                                        1.0},
+            {-0.5,                                       -0.0},
+
+            { 1.5,                                        2.0},
+            {-1.5,                                       -1.0},
+
+            { 2.5,                                        3.0},
+            {-2.5,                                       -2.0},
+
+            { FpUtils.nextDown(1.0),                      1.0},
+            { FpUtils.nextDown(-1.0),                    -1.0},
+
+            { Math.nextUp(1.0),                           2.0},
+            { Math.nextUp(-1.0),                         -0.0},
+
+            { 0x1.0p51,                                 0x1.0p51},
+            {-0x1.0p51,                                -0x1.0p51},
+
+            { FpUtils.nextDown(0x1.0p51),               0x1.0p51},
+            {-Math.nextUp(0x1.0p51),                   -0x1.0p51},
+
+            { Math.nextUp(0x1.0p51),                    0x1.0p51+1},
+            {-FpUtils.nextDown(0x1.0p51),              -0x1.0p51+1},
+
+            { FpUtils.nextDown(0x1.0p52),               0x1.0p52},
+            {-Math.nextUp(0x1.0p52),                   -0x1.0p52-1.0},
+
+            { Math.nextUp(0x1.0p52),                    0x1.0p52+1.0},
+            {-FpUtils.nextDown(0x1.0p52),              -0x1.0p52+1.0},
+        };
+
+        for(double[] testCase : testCases) {
+            failures += testCeilCase(testCase[0], testCase[1]);
+            failures += testFloorCase(-testCase[0], -testCase[1]);
+        }
+        return failures;
+    }
+
+    public static void main(String... args) {
+        int failures = 0;
+
+        failures += nearIntegerTests();
+        failures += roundingTests();
+
+        if (failures > 0) {
+            System.err.println("Testing {Math, StrictMath}.ceil incurred "
+                               + failures + " failures.");
+            throw new RuntimeException();
+        }
+    }
+}
--- a/jdk/test/java/math/BigInteger/BigIntegerTest.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java	Sun Jan 17 18:42:34 2010 -0800
@@ -642,37 +642,71 @@
 
         for(int i = 0; i < bitPatterns.length; i++) {
             BigInteger b1 = new BigInteger(bitPatterns[i], 16);
+            BigInteger b2 = null;
 
             File f = new File("serialtest");
             FileOutputStream fos = new FileOutputStream(f);
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(b1);
-            oos.flush();
-            oos.close();
-            FileInputStream fis = new FileInputStream(f);
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            BigInteger b2 = (BigInteger)ois.readObject();
+            try {
+                ObjectOutputStream oos = new ObjectOutputStream(fos);
+                try {
+                    oos.writeObject(b1);
+                    oos.flush();
+                } finally {
+                    oos.close();
+                }
 
-            if (!b1.equals(b2) ||
-                !b1.equals(b1.or(b2))) {
-                failCount++;
-                System.err.println("Serialized failed for hex " +
-                                   b1.toString(16));
+                FileInputStream fis = new FileInputStream(f);
+                try {
+                    ObjectInputStream ois = new ObjectInputStream(fis);
+                    try {
+                        b2 = (BigInteger)ois.readObject();
+                    } finally {
+                        ois.close();
+                    }
+                } finally {
+                    fis.close();
+                }
+
+                if (!b1.equals(b2) ||
+                    !b1.equals(b1.or(b2))) {
+                    failCount++;
+                    System.err.println("Serialized failed for hex " +
+                                       b1.toString(16));
+                }
+            } finally {
+                fos.close();
             }
             f.delete();
         }
 
         for(int i=0; i<10; i++) {
             BigInteger b1 = fetchNumber(rnd.nextInt(100));
+            BigInteger b2 = null;
             File f = new File("serialtest");
             FileOutputStream fos = new FileOutputStream(f);
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(b1);
-            oos.flush();
-            oos.close();
-            FileInputStream fis = new FileInputStream(f);
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            BigInteger b2 = (BigInteger)ois.readObject();
+            try {
+                ObjectOutputStream oos = new ObjectOutputStream(fos);
+                try {
+                    oos.writeObject(b1);
+                    oos.flush();
+                } finally {
+                    oos.close();
+                }
+
+                FileInputStream fis = new FileInputStream(f);
+                try {
+                    ObjectInputStream ois = new ObjectInputStream(fis);
+                    try {
+                        b2 = (BigInteger)ois.readObject();
+                    } finally {
+                        ois.close();
+                    }
+                } finally {
+                    fis.close();
+                }
+            } finally {
+                fos.close();
+            }
 
             if (!b1.equals(b2) ||
                 !b1.equals(b1.or(b2)))
--- a/jdk/test/java/nio/Buffer/Basic-X.java.template	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final $type$[] VALUES = {
+        $Fulltype$.MIN_VALUE,
+        ($type$) -1,
+        ($type$) 0,
+        ($type$) 1,
+        $Fulltype$.MAX_VALUE,
+#if[float]
+        $Fulltype$.NEGATIVE_INFINITY,
+        $Fulltype$.POSITIVE_INFINITY,
+        $Fulltype$.NaN,
+        ($type$) -0.0,
+#end[float]
+#if[double]
+        $Fulltype$.NEGATIVE_INFINITY,
+        $Fulltype$.POSITIVE_INFINITY,
+        $Fulltype$.NaN,
+        ($type$) -0.0,
+#end[double]
+    };
+
     private static void relGet($Type$Buffer b) {
         int n = b.capacity();
         $type$ v;
@@ -309,6 +329,12 @@
 
 #end[byte]
 
+    private static void fail(String problem,
+                             $Type$Buffer xb, $Type$Buffer yb,
+                             $type$ x, $type$ y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for ($type$ x : VALUES) {
+            $Type$Buffer xb = $Type$Buffer.wrap(new $type$[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for ($type$ y : VALUES) {
+                $Type$Buffer yb = $Type$Buffer.wrap(new $type$[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != $Fulltype$.compare(x, y)) {
+#if[float]
+                    if (x == 0.0 && y == 0.0) continue;
+#end[float]
+#if[double]
+                    if (x == 0.0 && y == 0.0) continue;
+#end[double]
+                    fail("Incorrect results for $Type$Buffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for $Type$Buffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicByte.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicByte.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final byte[] VALUES = {
+        Byte.MIN_VALUE,
+        (byte) -1,
+        (byte) 0,
+        (byte) 1,
+        Byte.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(ByteBuffer b) {
         int n = b.capacity();
         byte v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             ByteBuffer xb, ByteBuffer yb,
+                             byte x, byte y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (byte x : VALUES) {
+            ByteBuffer xb = ByteBuffer.wrap(new byte[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (byte y : VALUES) {
+                ByteBuffer yb = ByteBuffer.wrap(new byte[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Byte.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for ByteBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for ByteBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicChar.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicChar.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final char[] VALUES = {
+        Character.MIN_VALUE,
+        (char) -1,
+        (char) 0,
+        (char) 1,
+        Character.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(CharBuffer b) {
         int n = b.capacity();
         char v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             CharBuffer xb, CharBuffer yb,
+                             char x, char y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (char x : VALUES) {
+            CharBuffer xb = CharBuffer.wrap(new char[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (char y : VALUES) {
+                CharBuffer yb = CharBuffer.wrap(new char[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Character.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for CharBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for CharBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicDouble.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final double[] VALUES = {
+        Double.MIN_VALUE,
+        (double) -1,
+        (double) 0,
+        (double) 1,
+        Double.MAX_VALUE,
+
+
+
+
+
+
+
+        Double.NEGATIVE_INFINITY,
+        Double.POSITIVE_INFINITY,
+        Double.NaN,
+        (double) -0.0,
+
+    };
+
     private static void relGet(DoubleBuffer b) {
         int n = b.capacity();
         double v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             DoubleBuffer xb, DoubleBuffer yb,
+                             double x, double y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (double x : VALUES) {
+            DoubleBuffer xb = DoubleBuffer.wrap(new double[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (double y : VALUES) {
+                DoubleBuffer yb = DoubleBuffer.wrap(new double[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Double.compare(x, y)) {
+
+
+
+
+                    if (x == 0.0 && y == 0.0) continue;
+
+                    fail("Incorrect results for DoubleBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for DoubleBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicFloat.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final float[] VALUES = {
+        Float.MIN_VALUE,
+        (float) -1,
+        (float) 0,
+        (float) 1,
+        Float.MAX_VALUE,
+
+        Float.NEGATIVE_INFINITY,
+        Float.POSITIVE_INFINITY,
+        Float.NaN,
+        (float) -0.0,
+
+
+
+
+
+
+
+    };
+
     private static void relGet(FloatBuffer b) {
         int n = b.capacity();
         float v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             FloatBuffer xb, FloatBuffer yb,
+                             float x, float y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (float x : VALUES) {
+            FloatBuffer xb = FloatBuffer.wrap(new float[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (float y : VALUES) {
+                FloatBuffer yb = FloatBuffer.wrap(new float[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Float.compare(x, y)) {
+
+                    if (x == 0.0 && y == 0.0) continue;
+
+
+
+
+                    fail("Incorrect results for FloatBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for FloatBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicInt.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicInt.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final int[] VALUES = {
+        Integer.MIN_VALUE,
+        (int) -1,
+        (int) 0,
+        (int) 1,
+        Integer.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(IntBuffer b) {
         int n = b.capacity();
         int v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             IntBuffer xb, IntBuffer yb,
+                             int x, int y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (int x : VALUES) {
+            IntBuffer xb = IntBuffer.wrap(new int[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (int y : VALUES) {
+                IntBuffer yb = IntBuffer.wrap(new int[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Integer.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for IntBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for IntBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicLong.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicLong.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final long[] VALUES = {
+        Long.MIN_VALUE,
+        (long) -1,
+        (long) 0,
+        (long) 1,
+        Long.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(LongBuffer b) {
         int n = b.capacity();
         long v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             LongBuffer xb, LongBuffer yb,
+                             long x, long y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (long x : VALUES) {
+            LongBuffer xb = LongBuffer.wrap(new long[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (long y : VALUES) {
+                LongBuffer yb = LongBuffer.wrap(new long[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Long.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for LongBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for LongBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicShort.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/BasicShort.java	Sun Jan 17 18:42:34 2010 -0800
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final short[] VALUES = {
+        Short.MIN_VALUE,
+        (short) -1,
+        (short) 0,
+        (short) 1,
+        Short.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(ShortBuffer b) {
         int n = b.capacity();
         short v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             ShortBuffer xb, ShortBuffer yb,
+                             short x, short y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (short x : VALUES) {
+            ShortBuffer xb = ShortBuffer.wrap(new short[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (short y : VALUES) {
+                ShortBuffer yb = ShortBuffer.wrap(new short[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Short.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for ShortBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for ShortBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/genBasic.sh	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/nio/Buffer/genBasic.sh	Sun Jan 17 18:42:34 2010 -0800
@@ -36,5 +36,3 @@
 gen long Long Long
 gen float Float Float
 gen double Double Double
-
-rm -rf build
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Sun Jan 17 18:42:34 2010 -0800
@@ -146,13 +146,13 @@
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
+        oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
+
+        /* TODO: unbounded queue implementations are prone to OOME
+        oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
         oneRun(new LTQasSQ<Integer>(), pairs, iters);
         oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
-        oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
-
-        /* PriorityBlockingQueue is unbounded
-        oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
         */
     }
 
--- a/jdk/test/java/util/jar/JarFile/TurkCert.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/java/util/jar/JarFile/TurkCert.java	Sun Jan 17 18:42:34 2010 -0800
@@ -26,6 +26,7 @@
  * @bug 4624534
  * @summary Make sure jar certificates work for Turkish locale
  * @author kladko
+ * @run main/othervm TurkCert
  */
 
 import java.util.*;
--- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Sun Jan 17 18:42:34 2010 -0800
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4635230 6283345 6303830 6824440
+ * @bug 4635230 6283345 6303830 6824440 6867348
  * @summary Basic unit tests for generating XML Signatures with JSR 105
  * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
  *     X509KeySelector.java GenerationTests.java
@@ -126,13 +126,14 @@
         test_create_signature_x509_is();
         test_create_signature_x509_ski();
         test_create_signature_x509_sn();
-//      test_create_signature();
+        test_create_signature();
         test_create_exc_signature();
         test_create_sign_spec();
         test_create_signature_enveloping_sha256_dsa();
         test_create_signature_enveloping_sha384_rsa_sha256();
         test_create_signature_enveloping_sha512_rsa_sha384();
         test_create_signature_enveloping_sha512_rsa_sha512();
+        test_create_signature_reference_dependency();
     }
 
     private static void setup() throws Exception {
@@ -410,6 +411,55 @@
         System.out.println();
     }
 
+    static void test_create_signature_reference_dependency() throws Exception {
+        System.out.println("* Generating signature-reference-dependency.xml");
+        // create references
+        List<Reference> refs = Collections.singletonList
+            (fac.newReference("#object-1", sha1));
+
+        // create SignedInfo
+        SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs);
+
+        // create objects
+        List<XMLStructure> objs = new ArrayList<XMLStructure>();
+
+        // Object 1
+        List<Reference> manRefs = Collections.singletonList
+            (fac.newReference("#object-2", sha1));
+        objs.add(fac.newXMLObject(Collections.singletonList
+            (fac.newManifest(manRefs, "manifest-1")), "object-1", null, null));
+
+        // Object 2
+        Document doc = db.newDocument();
+        Element nc = doc.createElementNS(null, "NonCommentandus");
+        nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
+        nc.appendChild(doc.createComment(" Commentandum "));
+        objs.add(fac.newXMLObject(Collections.singletonList
+            (new DOMStructure(nc)), "object-2", null, null));
+
+        // create XMLSignature
+        XMLSignature sig = fac.newXMLSignature(si, rsa, objs, "signature", null);
+        DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc);
+
+        sig.sign(dsc);
+
+//      dumpDocument(doc, new PrintWriter(System.out));
+
+        DOMValidateContext dvc = new DOMValidateContext
+            (kvks, doc.getDocumentElement());
+        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+        if (sig.equals(sig2) == false) {
+            throw new Exception
+                ("Unmarshalled signature is not equal to generated signature");
+        }
+        if (sig2.validate(dvc) == false) {
+            throw new Exception("Validation of generated signature failed");
+        }
+
+        System.out.println();
+    }
+
     static void test_create_signature() throws Exception {
         System.out.println("* Generating signature.xml");
 
@@ -645,6 +695,7 @@
             envDoc.getElementsByTagName("YoursSincerely").item(0);
 
         DOMSignContext dsc = new DOMSignContext(signingKey, ys);
+        dsc.setURIDereferencer(httpUd);
 
         sig.sign(dsc);
 
@@ -660,6 +711,7 @@
 
         DOMValidateContext dvc = new DOMValidateContext
             (new X509KeySelector(ks), sigElement);
+        dvc.setURIDereferencer(httpUd);
         File f = new File(
             System.getProperty("dir.test.vector.baltimore") +
             System.getProperty("file.separator") +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.security.krb5.Config;
+
+public class BadKdc {
+
+    // Matches the krb5 debug output:
+    // >>> KDCCommunication: kdc=kdc.rabbit.hole UDP:14319, timeout=2000,...
+    //                                               ^ kdc#         ^ timeout
+    static final Pattern re = Pattern.compile(
+            ">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " +
+            "timeout=(\\d)000,");
+    public static void go(int[]... expected)
+            throws Exception {
+        System.setProperty("sun.security.krb5.debug", "true");
+
+        // Make sure KDCs' ports starts with 1 and 2 and 3,
+        // useful for checking debug output.
+        int p1 = 10000 + new java.util.Random().nextInt(10000);
+        int p2 = 20000 + new java.util.Random().nextInt(10000);
+        int p3 = 30000 + new java.util.Random().nextInt(10000);
+
+        FileWriter fw = new FileWriter("alternative-krb5.conf");
+
+        fw.write("[libdefaults]\n" +
+                "default_realm = " + OneKDC.REALM + "\n" +
+                "kdc_timeout = 2000\n");
+        fw.write("[realms]\n" + OneKDC.REALM + " = {\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" +
+                "}\n");
+
+        fw.close();
+        System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
+        Config.refresh();
+
+        // Turn on k3 only
+        KDC k3 = on(p3);
+
+        test(expected[0]);
+        test(expected[1]);
+        Config.refresh();
+        test(expected[2]);
+
+        k3.terminate(); // shutdown k3
+        on(p2);         // k2 is on
+        test(expected[3]);
+        on(p1);         // k1 and k2 is on
+        test(expected[4]);
+    }
+
+    private static KDC on(int p) throws Exception {
+        KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true);
+        k.addPrincipal(OneKDC.USER, OneKDC.PASS);
+        k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
+        return k;
+    }
+
+    /**
+     * One round of test for max_retries and timeout.
+     * @param timeout the expected timeout
+     * @param expected the expected kdc# timeout kdc# timeout...
+     */
+    private static void test(int... expected) throws Exception {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        PrintStream oldout = System.out;
+        System.setOut(new PrintStream(bo));
+        Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        System.setOut(oldout);
+
+        String[] lines = new String(bo.toByteArray()).split("\n");
+        System.out.println("----------------- TEST -----------------");
+        int count = 0;
+        for (String line: lines) {
+            Matcher m = re.matcher(line);
+            if (m.find()) {
+                System.out.println(line);
+                if (Integer.parseInt(m.group(1)) != expected[count++] ||
+                        Integer.parseInt(m.group(2)) != expected[count++]) {
+                    throw new Exception("Fail here");
+                }
+            }
+        }
+        if (count != expected.length) {
+            throw new Exception("Less rounds");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc1
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc1 {
+
+   public static void main(String[] args)
+           throws Exception {
+       Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+       BadKdc.go(
+               new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // The above line means try kdc1 for 2 seconds, then kdc1
+               // for 2 seconds,..., finally kdc3 for 2 seconds.
+               new int[]{1,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // refresh
+               new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // k3 off, k2 on
+               new int[]{1,2,2,2,1,2,2,2}, // 1
+               // k1 on
+               new int[]{1,2,1,2}  // empty
+       );
+   }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc2
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc2 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000");
+        BadKdc.go(
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                new int[]{1,1,1,1,2,1,2,1,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                // refresh
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                // k3 off, k2 on
+                new int[]{1,1,1,1,2,1,1,1,1,1,2,2}, // 1
+                // k1 on
+                new int[]{1,1,1,2}  // empty
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc3.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc3
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc3 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "tryLast");
+        BadKdc.go(
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
+                new int[]{3,2,3,2}, // 1, 2
+                // refresh
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
+                // k3 off, k2 on
+                new int[]{3,2,3,2,3,2,1,2,1,2,1,2,2,2,2,2}, // 1, 3
+                // k1 on
+                new int[]{2,2,2,2}  // 1, 3
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc4
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc4 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "");
+        BadKdc.go(
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            // refresh
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            // k3 off, k2 on
+            new int[]{1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2},
+            // k1 on
+            new int[]{1,2,1,2}
+        );
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Sun Jan 17 18:42:34 2010 -0800
@@ -141,6 +141,10 @@
     // Options
     private Map<Option,Object> options = new HashMap<Option,Object>();
 
+    private Thread thread1, thread2, thread3;
+    DatagramSocket u1 = null;
+    ServerSocket t1 = null;
+
     /**
      * Option names, to be expanded forever.
      */
@@ -480,8 +484,9 @@
             Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE);
             stringToKey.setAccessible(true);
             Integer kvno = null;
-            // For service whose password ending with a number, use it as kvno
-            if (p.toString().indexOf('/') >= 0) {
+            // For service whose password ending with a number, use it as kvno.
+            // Kvno must be postive.
+            if (p.toString().indexOf('/') > 0) {
                 char[] pass = getPassword(p, server);
                 if (Character.isDigit(pass[pass.length-1])) {
                     kvno = pass[pass.length-1] - '0';
@@ -940,8 +945,6 @@
      * @throws java.io.IOException for any communication error
      */
     protected void startServer(int port, boolean asDaemon) throws IOException {
-        DatagramSocket u1 = null;
-        ServerSocket t1 = null;
         if (port > 0) {
             u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
             t1 = new ServerSocket(port);
@@ -966,7 +969,7 @@
         this.port = port;
 
         // The UDP consumer
-        Thread thread = new Thread() {
+        thread1 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -982,11 +985,11 @@
                 }
             }
         };
-        thread.setDaemon(asDaemon);
-        thread.start();
+        thread1.setDaemon(asDaemon);
+        thread1.start();
 
         // The TCP consumer
-        thread = new Thread() {
+        thread2 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -1004,11 +1007,11 @@
                 }
             }
         };
-        thread.setDaemon(asDaemon);
-        thread.start();
+        thread2.setDaemon(asDaemon);
+        thread2.start();
 
         // The dispatcher
-        thread = new Thread() {
+        thread3 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -1018,10 +1021,21 @@
                 }
             }
         };
-        thread.setDaemon(true);
-        thread.start();
+        thread3.setDaemon(true);
+        thread3.start();
     }
 
+    public void terminate() {
+        try {
+            thread1.stop();
+            thread2.stop();
+            thread3.stop();
+            u1.close();
+            t1.close();
+        } catch (Exception e) {
+            // OK
+        }
+    }
     /**
      * Helper class to encapsulate a job in a KDC.
      */
--- a/jdk/test/sun/security/krb5/auto/MoreKvno.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/security/krb5/auto/MoreKvno.java	Sun Jan 17 18:42:34 2010 -0800
@@ -24,15 +24,20 @@
 /*
  * @test
  * @bug 6893158
+ * @bug 6907425
  * @summary AP_REQ check should use key version number
  */
 
+import org.ietf.jgss.GSSException;
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.KrbException;
 import sun.security.krb5.PrincipalName;
 import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.Krb5;
 
 public class MoreKvno {
 
+    static PrincipalName p;
     public static void main(String[] args)
             throws Exception {
 
@@ -41,21 +46,40 @@
 
         // Rewrite keytab, 3 set of keys with different kvno
         KeyTab ktab = KeyTab.create(OneKDC.KTAB);
-        PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
-        ktab.addEntry(p, "pass0".toCharArray(), 0);
+        p = new PrincipalName(
+            OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
+        ktab.addEntry(p, "pass1".toCharArray(), 1);
+        ktab.addEntry(p, "pass3".toCharArray(), 3);
         ktab.addEntry(p, "pass2".toCharArray(), 2);
-        ktab.addEntry(p, "pass1".toCharArray(), 1);
         ktab.save();
 
-        kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray());
-        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept");
-        kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray());
+        char[] pass = "pass2".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
+        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+
+        pass = "pass3".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
         // "server" initiate also, check pass2 is used at authentication
-        go(OneKDC.SERVER, "server");
+        go(OneKDC.SERVER, "server", pass);
+
+        try {
+            pass = "pass4".toCharArray();
+            kdc.addPrincipal(OneKDC.SERVER, pass);
+            go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+            throw new Exception("This test should fail");
+        } catch (GSSException gsse) {
+            KrbException ke = (KrbException)gsse.getCause();
+            if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) {
+                throw new Exception("Not expected failure code: " +
+                        ke.returnCode());
+            }
+        }
     }
 
-    static void go(String server, String entry) throws Exception {
+    static void go(String server, String entry, char[] pass) throws Exception {
         Context c, s;
+
+        // Part 1: Test keytab
         c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
         s = Context.fromJAAS(entry);
 
@@ -66,5 +90,17 @@
 
         s.dispose();
         c.dispose();
+
+        // Part 2: Test username/password pair
+        c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
+        s = Context.fromUserPass(p.getNameString(), pass, true);
+
+        c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        s.dispose();
+        c.dispose();
     }
 }
--- a/jdk/test/sun/security/krb5/auto/OneKDC.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/security/krb5/auto/OneKDC.java	Sun Jan 17 18:42:34 2010 -0800
@@ -24,8 +24,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.security.Security;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
--- a/jdk/test/sun/security/krb5/auto/SSL.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/security/krb5/auto/SSL.java	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009-2010 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6894643
+ * @bug 6894643 6913636
  * @summary Test JSSE Kerberos ciphersuite
  */
 import java.io.*;
@@ -32,12 +32,13 @@
 import java.security.Principal;
 import java.util.Date;
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+import sun.security.krb5.internal.ktab.KeyTab;
 
 public class SSL {
 
     private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
     private static final int LOOP_LIMIT = 1;
-    private static final char[] PASS = "secret".toCharArray();
     private static int loopCount = 0;
     private static volatile String server;
     private static volatile int port;
@@ -54,12 +55,39 @@
 
         kdc.addPrincipal(OneKDC.USER, OneKDC.PASS);
         kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
-        kdc.addPrincipal("host/" + server, PASS);
         KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
         System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
 
+        // Add 3 versions of keys into keytab
+        KeyTab ktab = KeyTab.create(OneKDC.KTAB);
+        PrincipalName service = new PrincipalName(
+                "host/" + server, PrincipalName.KRB_NT_SRV_HST);
+        ktab.addEntry(service, "pass1".toCharArray(), 1);
+        ktab.addEntry(service, "pass2".toCharArray(), 2);
+        ktab.addEntry(service, "pass3".toCharArray(), 3);
+        ktab.save();
+
+        // and use the middle one as the real key
+        kdc.addPrincipal("host/" + server, "pass2".toCharArray());
+
+        // JAAS config entry name ssl
+        System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+        File f = new File(OneKDC.JAAS_CONF);
+        FileOutputStream fos = new FileOutputStream(f);
+        fos.write((
+                "ssl {\n" +
+                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
+                "    principal=\"host/" + server + "\"\n" +
+                "    useKeyTab=true\n" +
+                "    keyTab=" + OneKDC.KTAB + "\n" +
+                "    isInitiator=false\n" +
+                "    storeKey=true;\n};\n"
+                ).getBytes());
+        fos.close();
+        f.deleteOnExit();
+
         final Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
-        final Context s = Context.fromUserPass("host/" + server, PASS, true);
+        final Context s = Context.fromJAAS("ssl");
 
         c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID);
         s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/Test5653.java	Sun Jan 17 18:42:34 2010 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6895424
+ * @summary RFC 5653
+ */
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class Test5653 {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        Oid oldOid = new Oid("1.3.6.1.5.6.2");
+        new OneKDC(null).writeJAASConf();
+
+        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+        GSSManager m = GSSManager.getInstance();
+        boolean found = false;
+
+        // Test 1: the getMechsForName() method accepts it.
+        for (Oid tmp: m.getMechsForName(oldOid)) {
+            if (tmp.equals(GSSUtil.GSS_KRB5_MECH_OID)) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            throw new Exception("Cannot found krb5 mech for old name type");
+        }
+
+        // Test 2: the createName() method accepts it.
+        GSSName name = m.createName("server@host.rabbit.hole", oldOid);
+
+        // Test 3: its getStringNameType() output is correct
+        if (!name.getStringNameType().equals(GSSName.NT_HOSTBASED_SERVICE)) {
+            throw new Exception("GSSName not correct name type");
+        }
+
+        // Test 4: everything still works.
+        GSSContext c1 = m.createContext(
+                name,
+                GSSUtil.GSS_KRB5_MECH_OID,
+                null,
+                GSSContext.DEFAULT_LIFETIME);
+        byte[] token = c1.initSecContext(new byte[0], 0, 0);
+
+        Context s;
+        s = Context.fromJAAS("server");
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        s.x().acceptSecContext(token, 0, token.length);
+    }
+}
--- a/jdk/test/sun/security/util/Oid/S11N.sh	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/security/util/Oid/S11N.sh	Sun Jan 17 18:42:34 2010 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
+# 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
@@ -21,8 +21,8 @@
 # have any questions.
 #
 # @test
-# @bug 4811968
-# @summary Serialization compatibility with old versions
+# @bug 4811968 6908628
+# @summary Serialization compatibility with old versions (and fix)
 # @author Weijun Wang
 #
 # set a few environment variables so that the shell-script can run stand-alone
@@ -99,7 +99,8 @@
 
 # the test code
 
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}SerialTest.java || exit 10
+${TESTJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \
+        -d . ${TESTSRC}${FS}SerialTest.java || exit 10
 
 OLDJAVA="
     /java/re/j2se/1.6.0/latest/binaries/${PF}
@@ -161,4 +162,10 @@
 rm -f tmp.oid.serial.old
 rm -f SerialTest.class
 
+for oldj in ${OLDJAVA}; do
+    if [ ! -d ${oldj} ]; then
+        echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr
+    fi
+done
+
 exit 0
--- a/jdk/test/sun/tools/jhat/HatRun.java	Mon Jan 11 23:25:20 2010 -0800
+++ b/jdk/test/sun/tools/jhat/HatRun.java	Sun Jan 17 18:42:34 2010 -0800
@@ -166,8 +166,10 @@
                             jre_home );
         String cdir      = System.getProperty("test.classes", ".");
         String os_arch   = System.getProperty("os.arch");
-        boolean d64      = os_arch.equals("sparcv9") ||
-                           os_arch.equals("amd64");
+        String os_name   = System.getProperty("os.name");
+        boolean d64      = os_name.equals("SunOS") && (
+                             os_arch.equals("sparcv9") ||
+                             os_arch.equals("amd64"));
         String isa_dir   = d64?(File.separator+os_arch):"";
         String java      = jre_home
                              + File.separator + "bin" + isa_dir