6909572: Add a new target for building modules
Summary: Add a new "modules" build target that builds jdk and jre module image
Reviewed-by: alanb, ohair
--- a/jdk/make/Makefile Fri Dec 18 07:49:02 2009 -0800
+++ b/jdk/make/Makefile Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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:
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/Makefile Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 <clinit>.</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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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("<", "<").replace(">", ">");
+ }
+
+ 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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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 Fri Dec 18 11:36:23 2009 -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);
+ }
+ }
+ }
+ }
+ }
+}