This commit is contained in:
Kelly O'Hair 2010-01-13 15:37:06 -08:00
commit 23fc99433b
94 changed files with 10582 additions and 334 deletions

View File

@ -74,6 +74,7 @@ import -- copy in the pre-built components (e.g. VM) \n\
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 @@ docs:: sanity-docs post-sanity-docs
# Release engineering targets.
#
include $(BUILDDIR)/common/Release.gmk
include $(BUILDDIR)/common/Modules.gmk
#
# Cscope targets.

442
jdk/make/common/Modules.gmk Normal file
View File

@ -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:

View File

@ -150,10 +150,8 @@ SUNWprivate_1.1 {
Java_java_lang_StrictMath_asin;
Java_java_lang_StrictMath_atan;
Java_java_lang_StrictMath_atan2;
Java_java_lang_StrictMath_ceil;
Java_java_lang_StrictMath_cos;
Java_java_lang_StrictMath_exp;
Java_java_lang_StrictMath_floor;
Java_java_lang_StrictMath_log;
Java_java_lang_StrictMath_log10;
Java_java_lang_StrictMath_pow;

View File

@ -107,4 +107,3 @@ text: .text%Java_java_lang_Class_isInstance;
text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_floor;

View File

@ -105,4 +105,3 @@ text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_sqrt;
text: .text%Java_java_lang_StrictMath_floor;

View File

@ -101,4 +101,3 @@ text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
text: .text%findJavaTZ_md;
text: .text%Java_java_lang_StrictMath_log;
text: .text%Java_java_lang_StrictMath_sqrt;
text: .text%Java_java_lang_StrictMath_floor;

View File

@ -152,7 +152,6 @@ STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
$(STATIC_LIBRARY_DIR): $(OBJDIR)
@$(prep-target)
@$(MKDIR) $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)

View File

@ -234,6 +234,7 @@ FILES_src = \
sun/nio/cs/UTF_16BE.java \
sun/nio/cs/UTF_16LE.java \
sun/nio/cs/UTF_8.java \
sun/nio/cs/Unicode.java \
sun/nio/cs/UnicodeDecoder.java \
sun/nio/cs/UnicodeEncoder.java \
sun/nio/cs/UTF_32.java \

View File

@ -44,6 +44,7 @@ rwkey=XX
case $type in
char) fulltype=character;;
int) fulltype=integer;;
*) fulltype=$type;;
esac
@ -54,6 +55,11 @@ case $type in
long | double) LBPV=3;;
esac
case $type in
float|double) floatingPointOrIntegralType=floatingPointType;;
*) floatingPointOrIntegralType=integralType;;
esac
typesAndBits() {
type="$1"; BO="$2"
@ -101,6 +107,7 @@ set -e
$SPP <$SRC >$DST \
-K$type \
-K$floatingPointOrIntegralType \
-Dtype=$type \
-DType=$Type \
-Dfulltype=$fulltype \

145
jdk/make/modules/Makefile Normal file
View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 **;
}

View File

@ -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;
* }
*/

View File

@ -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

View File

@ -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)

View File

@ -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>

View File

@ -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}

View File

@ -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>

View File

@ -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);
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,819 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package com.sun.classanalyzer;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.File;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.sun.tools.classfile.*;
import com.sun.tools.classfile.ConstantPool.*;
import static com.sun.tools.classfile.ConstantPool.*;
import com.sun.tools.classfile.Instruction.TypeKind;
import com.sun.tools.classfile.Type.*;
/**
* Generate the module config for the boot module with
* a given set of roots (classes or methods) and exclude list.
*
* This tool does method-level dependency analysis starting
* from the root set and follows references transitively as follows:
* <ul>
* <li>For a given class, it will parse the ClassFile to
* find its superclass and superinterfaces and also
* its static initializer &lt;clinit&gt;.</li>
* <li>For each method, it will parse its Code attribute
* to look for a Methodref, Fieldref, and InterfaceMethodref.
* </li>
* <li>For each Fieldref, it will include the type of
* the field in the dependency.</li>
* <li>For each MethodRef, it will follow all references in
* that method.</li>
* <li>For each InterfaceMethodref, it will follow all references in
* that method defined its implementation classes in
* the resulting dependency list.</li>
* </ul>
*
* Limitation:
* <ul>
* <li>For each Methodref, it only parses the method of
* the specified type. It doesn't analyze the class hierarchy
* and follow references of its subclasses since it ends up
* pulls in many unnecessary dependencies. For now,
* the list of subclasses and methods need to be listed in
* the root set.</li>
* </ul>
*
* @author Mandy Chung
*/
public class BootAnalyzer {
public static void main(String[] args) throws Exception {
String jdkhome = null;
String config = null;
String output = ".";
boolean printClassList = false;
// process arguments
int i = 0;
while (i < args.length) {
String arg = args[i++];
if (arg.equals("-jdkhome")) {
if (i < args.length) {
jdkhome = args[i++];
} else {
usage();
}
} else if (arg.equals("-config")) {
config = args[i++];
} else if (arg.equals("-output")) {
output = args[i++];
} else if (arg.equals("-classlist")) {
printClassList = true;
} else {
usage();
}
}
if (jdkhome == null || config == null) {
usage();
}
File jre = new File(jdkhome, "jre");
if (jre.exists()) {
ClassPath.setJDKHome(jdkhome);
} else {
File classes = new File(jdkhome, "classes");
if (classes.exists()) {
ClassPath.setClassPath(classes.getCanonicalPath());
} else {
throw new RuntimeException("Invalid jdkhome: " + jdkhome);
}
}
parseConfigFile(config);
followRoots();
// create output directory if it doesn't exist
File dir = new File(output);
if (!dir.isDirectory()) {
if (!dir.exists()) {
boolean created = dir.mkdir();
if (!created) {
throw new RuntimeException("Unable to create `" + dir + "'");
}
}
}
String bootmodule = "boot";
String bootconfig = resolve(dir, bootmodule, "config");
printBootConfig(bootconfig, bootmodule);
List<ModuleConfig> list = ModuleConfig.readConfigurationFile(bootconfig);
Module module = Module.addModule(list.get(0));
for (Klass k : Klass.getAllClasses()) {
module.addKlass(k);
}
module.fixupDependencies();
if (printClassList) {
module.printClassListTo(resolve(dir, bootmodule, "classlist"));
module.printSummaryTo(resolve(dir, bootmodule, "summary"));
}
}
// print boot.config file as an input to the ClassAnalyzer
private static void printBootConfig(String output, String bootmodule) throws IOException {
File f = new File(output);
PrintWriter writer = new PrintWriter(f);
try {
int count = 0;
writer.format("module %s {%n", bootmodule);
for (Klass k : Klass.getAllClasses()) {
if (count++ == 0) {
writer.format("%4s%7s %s", "", "include", k);
} else {
writer.format(",%n");
writer.format("%4s%7s %s", "", "", k);
}
}
writer.format(";%n}%n");
} finally {
writer.close();
}
}
private static String resolve(File dir, String mname, String suffix) {
File f = new File(dir, mname + "." + suffix);
return f.toString();
}
static List<MethodDescriptor> methods = new LinkedList<MethodDescriptor>();
static Deque<MethodDescriptor> pending = new ArrayDeque<MethodDescriptor>();
static Deque<MethodDescriptor> interfaceMethodRefs = new ArrayDeque<MethodDescriptor>();
static Filter filter = new Filter();
private static void followRoots() throws IOException {
MethodDescriptor md = null;
while ((md = pending.poll()) != null) {
if (!methods.contains(md)) {
methods.add(md);
if (md.classname.isEmpty()) {
trace("Warning: class missing %s%n", md);
continue;
}
if (filter.isExcluded(md.classname)) {
trace("excluded %s%n", md);
} else {
KlassInfo kinfo = getKlassInfo(md.classname);
if (kinfo.classname.contains("$")) {
int pos = kinfo.classname.lastIndexOf('$');
String outer = kinfo.classname.substring(0, pos);
if (!cache.containsKey(outer)) {
trace(" include outer class %s%n", outer);
getKlassInfo(outer).ensureParse();
}
}
kinfo.ensureParse();
if (md.methodname.length() > 0) {
if (filter.isExcluded(md.name)) {
trace("excluded %s%n", md);
} else {
if (md.interfaceMethodRef) {
trace("interface methodref %s%n", md);
interfaceMethodRefs.add(md);
} else {
List<String> descriptors = kinfo.parse(md);
if (descriptors.isEmpty()) {
if (kinfo.getSuperclass() != null) {
String sn = kinfo.getSuperclass().classname;
MethodDescriptor superMD = new MethodDescriptor(sn + "." + md.methodname, md.descriptor, false);
if (!methods.contains(superMD) && !pending.contains(superMD)) {
trace(" delegated %s to %s%n", md, superMD);
pending.add(superMD);
}
} else if (kinfo.isClass()) {
trace(" %s (not found)%n", md);
} else {
trace(" %s (interface)%n", md);
}
} else {
if (md.descriptor.equals("*")) {
trace(" parsed %s : ", md.name);
for (String s : descriptors) {
trace(" %s", s);
}
trace("%n");
}
}
}
}
}
}
}
if (pending.isEmpty()) {
for (Klass k : Klass.getAllClasses()) {
if (k.getFileSize() == 0) {
getKlassInfo(k.getClassName()).ensureParse();
}
}
while ((md = interfaceMethodRefs.poll()) != null) {
addSubClassMethods(md);
}
}
}
}
static void addSubClassMethods(MethodDescriptor md) throws IOException {
for (KlassInfo kinfo : getSubClasses(md.classname)) {
String methodname = kinfo.classname + "." + md.methodname;
MethodDescriptor other = new MethodDescriptor(methodname, md.descriptor, false);
if (!methods.contains(other) && !pending.contains(other)) {
trace("Warning: subclass from %s to %s%n", md.classname, other);
pending.add(other);
}
}
}
private final static String privilegedActionInterf = "java.security.PrivilegedAction";
private final static String privilegedExceptionActionInterf = "java.security.PrivilegedExceptionAction";
static boolean isPrivilegedAction(String classname) {
if (classname.isEmpty()) {
return false;
}
KlassInfo kinfo = getKlassInfo(classname);
for (KlassInfo ki : kinfo.getInterfaces()) {
String interf = ki.classname;
if (interf.equals(privilegedActionInterf) ||
interf.equals(privilegedExceptionActionInterf)) {
return true;
}
}
return false;
}
static Map<String, KlassInfo> cache = new HashMap<String, KlassInfo>();
static KlassInfo getKlassInfo(String classname) {
classname = classname.replace('/', '.');
KlassInfo kinfo = cache.get(classname);
if (kinfo == null) {
kinfo = new KlassInfo(classname);
cache.put(classname, kinfo);
}
return kinfo;
}
static class KlassInfo {
final String classname;
private ClassFileParser parser;
private KlassInfo superclass;
private List<KlassInfo> interfaces = new LinkedList<KlassInfo>();
KlassInfo(String classname) {
this.classname = classname;
}
boolean isClass() {
ensureParse();
return parser.classfile.isClass();
}
KlassInfo getSuperclass() {
ensureParse();
return superclass;
}
List<KlassInfo> getInterfaces() {
ensureParse();
return java.util.Collections.unmodifiableList(interfaces);
}
void ensureParse() {
try {
getClassFileParser();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
synchronized ClassFileParser getClassFileParser() throws IOException {
if (parser == null) {
parser = ClassPath.parserForClass(classname);
if (parser != null) {
parseClassFile();
List<String> descriptors = parse(new MethodDescriptor(classname + ".<clinit>", "()V", false));
}
}
return parser;
}
List<String> parse(MethodDescriptor md) {
ensureParse();
try {
List<String> descriptors = new LinkedList<String>();
for (Method m : parser.classfile.methods) {
String name = m.getName(parser.classfile.constant_pool);
String desc = parser.constantPoolParser.getDescriptor(m.descriptor.index);
if (name.equals(md.methodname)) {
if (md.descriptor.equals("*") || md.descriptor.equals(desc)) {
parseMethod(parser, m);
descriptors.add(desc);
}
}
}
return descriptors;
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
}
private void parseClassFile() throws IOException {
parser.parseClassInfo();
ClassFile classfile = parser.classfile;
try {
if (classfile.super_class > 0) {
superclass = getKlassInfo(classfile.getSuperclassName());
}
if (classfile.interfaces != null) {
for (int i = 0; i < classfile.interfaces.length; i++) {
interfaces.add(getKlassInfo(classfile.getInterfaceName(i)));
}
}
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
}
}
static List<KlassInfo> getSubClasses(String classname) throws IOException {
List<KlassInfo> result = new LinkedList<KlassInfo>();
List<KlassInfo> list = new LinkedList<KlassInfo>();
list.addAll(cache.values());
for (KlassInfo kinfo : list) {
if (kinfo.getSuperclass() != null && classname.equals(kinfo.getSuperclass().classname)) {
result.add(kinfo);
}
for (KlassInfo interf : kinfo.getInterfaces()) {
if (classname.equals(interf.classname)) {
result.add(kinfo);
}
}
}
return result;
}
private static void parseConfigFile(String config) throws IOException {
FileInputStream in = new FileInputStream(config);
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int lineNumber = 0;
while ((line = reader.readLine()) != null) {
lineNumber++;
if ((line = line.trim()).length() > 0) {
if (line.startsWith("#")) {
continue;
}
String[] s = line.split("\\s+");
if ("exclude".equals(s[0])) {
filter.exclude(s[1]);
} else {
String name = s[0].replace('/', '.');
if (name.length() > 0) {
String classname = name.replace('/', '.');
if (s.length == 2) {
// method name
int pos = classname.lastIndexOf('.');
classname = classname.substring(0, pos);
}
KlassInfo kinfo = getKlassInfo(classname);
if (kinfo.getClassFileParser() != null) {
// class exists
MethodDescriptor md = (s.length == 1) ? new MethodDescriptor(name) : new MethodDescriptor(name, s[1], false);
if (!pending.contains(md)) {
pending.add(md);
}
} else {
// class not found
trace("Class %s not found%n", classname);
}
}
}
}
}
} finally {
in.close();
}
}
private static void parseMethod(ClassFileParser cfparser, Method m) {
Klass.Method kmethod = cfparser.parseMethod(m);
Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
if (c_attr != null) {
LineNumberTable_attribute lineNumTable =
(LineNumberTable_attribute) c_attr.attributes.get(Attribute.LineNumberTable);
InstructorVisitor visitor = new InstructorVisitor(cfparser, lineNumTable);
trace("parseMethod %s %s %n", cfparser.this_klass, kmethod);
for (Instruction instr : c_attr.getInstructions()) {
try {
instr.accept(visitor, kmethod);
} catch (ArrayIndexOutOfBoundsException e) {
throw new RuntimeException("error at or after byte " + instr.getPC());
}
}
if (c_attr.exception_table_langth > 0) {
for (int i = 0; i <
c_attr.exception_table.length; i++) {
Code_attribute.Exception_data handler = c_attr.exception_table[i];
int catch_type = handler.catch_type;
if (catch_type > 0) {
visitor.addConstantPoolRef(catch_type, kmethod, handler.start_pc);
}
}
}
}
}
static class MethodDescriptor {
final String name;
final String classname;
final String methodname;
final String descriptor;
final boolean interfaceMethodRef;
MethodDescriptor(String classname) {
this.classname = classname.replace('/', '.');
this.name = this.classname;
this.methodname = "";
this.descriptor = "";
this.interfaceMethodRef = false;
if (this.classname.length() == 1) {
throw new RuntimeException("invalid " + this);
}
}
MethodDescriptor(String name, String descriptor, boolean interfaceMethodRef) {
name = name.replace('/', '.');
this.name = name;
int pos = name.lastIndexOf('.');
this.classname = name.substring(0, pos);
this.methodname = name.substring(pos + 1, name.length());
this.descriptor = descriptor;
this.interfaceMethodRef = interfaceMethodRef;
if (this.classname.length() == 1) {
throw new RuntimeException("invalid " + this);
}
}
@Override
public boolean equals(Object obj) {
MethodDescriptor m = (MethodDescriptor) obj;
return this.name.equals(m.name) &&
this.descriptor.equals(m.descriptor);
}
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 97 * hash + (this.descriptor != null ? this.descriptor.hashCode() : 0);
return hash;
}
public String toString() {
if (descriptor.isEmpty()) {
return name;
} else {
return name + " : " + descriptor;
}
}
}
static class Filter {
private Set<String> excludes = new TreeSet<String>();
Filter exclude(String pattern) {
excludes.add(pattern);
return this;
}
boolean isExcluded(String klass) {
for (String pattern : excludes) {
if (matches(klass, pattern)) {
return true;
}
}
return false;
}
private boolean matches(String klass, String pattern) {
int pos = klass.lastIndexOf('.');
String packageName = pos > 0 ? klass.substring(0, pos) : "<unnamed>";
if (pattern.endsWith("**")) {
String p = pattern.substring(0, pattern.length() - 2);
return klass.startsWith(p);
} else if (pattern.endsWith("*")) {
pos = pattern.lastIndexOf('.');
String pkg = pos > 0 ? pattern.substring(0, pos) : "<unnamed>";
if (packageName.equals(pkg)) {
// package name has to be exact match
String p = pattern.substring(0, pattern.length() - 1);
return klass.startsWith(p);
} else {
return false;
}
} else {
// exact match or inner class
return klass.equals(pattern) || klass.startsWith(pattern + "$");
}
}
}
static class InstructorVisitor implements Instruction.KindVisitor<Void, Klass.Method> {
private final ClassFileParser parser;
private final LineNumberTable_attribute lineNumTable;
InstructorVisitor(ClassFileParser parser, LineNumberTable_attribute lineNumTable) {
this.parser = parser;
this.lineNumTable = lineNumTable;
}
int getLineNumber(int pc) {
if (lineNumTable != null) {
int start_pc = 0;
int lineno = 0;
for (int i = 0; i < lineNumTable.line_number_table_length; i++) {
int cur_start_pc = lineNumTable.line_number_table[i].start_pc;
if (pc == 0 && cur_start_pc == 0) {
return lineNumTable.line_number_table[i].line_number;
} else if (pc >= start_pc && pc < cur_start_pc) {
return lineno;
}
start_pc = cur_start_pc;
lineno = lineNumTable.line_number_table[i].line_number;
}
}
return 0;
}
void addConstantPoolRef(int index, Klass.Method m, int pc) {
try {
CPInfo cpInfo = parser.classfile.constant_pool.get(index);
String name = cpInfo.accept(typeFinder, null);
if (name != null) {
trace(" %s %s at line %d%n", parser.constantPoolParser.tagName(index), name, getLineNumber(pc));
}
} catch (InvalidIndex ex) {
throw new RuntimeException(ex);
}
}
public Void visitNoOperands(Instruction instr, Klass.Method m) {
return null;
}
public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) {
return null;
}
public Void visitBranch(Instruction instr, int offset, Klass.Method m) {
return null;
}
public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) {
addConstantPoolRef(index, m, instr.getPC());
return null;
}
public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) {
addConstantPoolRef(index, m, instr.getPC());
return null;
}
public Void visitLocal(Instruction instr, int index, Klass.Method m) {
return null;
}
public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) {
return null;
}
public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) {
return null;
}
public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) {
return null;
}
public Void visitValue(Instruction instr, int value, Klass.Method m) {
return null;
}
public Void visitUnknown(Instruction instr, Klass.Method m) {
return null;
}
private ConstantPool.Visitor<String, Void> typeFinder = new ConstantPool.Visitor<String, Void>() {
String getClassName(CPRefInfo info, Void p) {
try {
return parser.checkClassName(info.getClassName()).replace('/', '.');
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
}
boolean addReferencedClass(String name) {
if (Klass.findKlass(name) == null) {
MethodDescriptor md = new MethodDescriptor(name);
if (!methods.contains(md) && !pending.contains(md)) {
pending.add(md);
}
return true;
}
return false;
}
private String privilegedActionClass = "";
void cachePrivilegedAction(String classname) {
trace(" found PrivilegedAction %s%n", classname);
privilegedActionClass = classname;
}
void doPrivilegedCall(String method) {
if (privilegedActionClass.length() > 0) {
MethodDescriptor md = new MethodDescriptor(privilegedActionClass + ".run", "*", false);
if (!methods.contains(md) && !pending.contains(md)) {
trace(" doPrivileged %s%n", md);
pending.add(md);
}
}
}
private String addMethodDescriptor(CPRefInfo info, Void p) {
try {
String classname = getClassName(info, null);
String method = classname + "." + info.getNameAndTypeInfo().getName();
String descriptor = info.getNameAndTypeInfo().getType();
if (method.endsWith(".<init>") && isPrivilegedAction(classname)) {
cachePrivilegedAction(classname);
}
if (method.equals("java.security.AccessController.doPrivileged")) {
doPrivilegedCall(method);
return method;
}
boolean interfaceMethodRef = info instanceof CONSTANT_InterfaceMethodref_info;
MethodDescriptor md = new MethodDescriptor(method, descriptor, interfaceMethodRef);
if (!methods.contains(md) && !pending.contains(md)) {
pending.add(md);
}
return method;
} catch (ConstantPoolException e) {
throw new RuntimeException(e);
}
}
public String visitClass(CONSTANT_Class_info info, Void p) {
try {
String classname = parser.checkClassName(info.getName()).replace('/', '.');
if (classname.length() > 0) {
addReferencedClass(classname);
}
return classname;
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
}
public String visitDouble(CONSTANT_Double_info info, Void p) {
// skip
return null;
}
public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
try {
String classname = getClassName(info, p);
if (classname.length() > 0) {
addReferencedClass(classname);
}
String type = info.getNameAndTypeInfo().getType();
String fieldType = parser.checkClassName(type).replace('/', '.');
if (fieldType.length() > 0) {
addReferencedClass(classname);
}
return parser.constantPoolParser.stringValue(info);
} catch (ConstantPoolException e) {
throw new RuntimeException(e);
}
}
public String visitFloat(CONSTANT_Float_info info, Void p) {
// skip
return null;
}
public String visitInteger(CONSTANT_Integer_info info, Void p) {
// skip
return null;
}
public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
return addMethodDescriptor(info, p);
}
public String visitLong(CONSTANT_Long_info info, Void p) {
// skip
return null;
}
public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
// skip
return null;
}
public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
return addMethodDescriptor(info, p);
}
public String visitString(CONSTANT_String_info info, Void p) {
// skip
return null;
}
public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
return null;
}
};
}
static boolean traceOn = System.getProperty("classanalyzer.debug") != null;
private static void trace(String format, Object... args) {
if (traceOn) {
System.out.format(format, args);
}
}
private static void usage() {
System.out.println("Usage: BootAnalyzer <options>");
System.out.println("Options: ");
System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
System.out.println("\t-config <roots for the boot module>");
System.out.println("\t-output <output dir>");
System.out.println("\t-classlist print class list and summary");
System.exit(-1);
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
};
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -0,0 +1,357 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package com.sun.classanalyzer;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import com.sun.tools.classfile.AccessFlags;
/**
*
* @author Mandy Chung
*/
public class Klass implements Comparable<Klass> {
private final String classname;
private final String packagename;
private Module module;
private boolean isJavaLangObject;
private String[] paths;
private Map<String, Set<Method>> methods;
private AccessFlags accessFlags;
private long filesize;
private SortedMap<Klass, Set<ResolutionInfo>> deps;
private SortedMap<Klass, Set<ResolutionInfo>> referrers;
private List<AnnotatedDependency> annotatedDeps;
private Set<String> classForNameRefs;
private Klass(String classname) {
this.classname = classname;
this.paths = classname.replace('.', '/').split("/");
this.isJavaLangObject = classname.equals("java.lang.Object");
this.deps = new TreeMap<Klass, Set<ResolutionInfo>>();
this.referrers = new TreeMap<Klass, Set<ResolutionInfo>>();
this.methods = new HashMap<String, Set<Method>>();
this.annotatedDeps = new ArrayList<AnnotatedDependency>();
this.classForNameRefs = new TreeSet<String>();
int pos = classname.lastIndexOf('.');
this.packagename = (pos > 0) ? classname.substring(0, pos) : "<unnamed>";
}
String getBasename() {
return paths[paths.length - 1];
}
String getClassName() {
return classname;
}
String getPackageName() {
return packagename;
}
String getClassFilePathname() {
StringBuilder sb = new StringBuilder(paths[0]);
for (int i = 1; i < paths.length; i++) {
String p = paths[i];
sb.append(File.separator).append(p);
}
return sb.append(".class").toString();
}
boolean isPublic() {
return accessFlags == null || accessFlags.is(AccessFlags.ACC_PUBLIC);
}
Module getModule() {
return module;
}
void setModule(Module m) {
if (module != null) {
throw new RuntimeException("Module for " + this + " already set");
}
this.module = m;
}
Set<Klass> getReferencedClasses() {
return deps.keySet();
}
Set<Klass> getReferencingClasses() {
return referrers.keySet();
}
void setAccessFlags(int flags) {
this.accessFlags = new AccessFlags(flags);
}
void setFileSize(long size) {
this.filesize = size;
}
long getFileSize() {
return this.filesize;
}
boolean exists() {
return filesize > 0;
}
boolean skip(Klass k) {
// skip if either class is a root or same class
return k.isJavaLangObject || this == k || k.classname.equals(classname);
}
void addDep(Method callee, ResolutionInfo resInfo) {
addDep(callee.getKlass(), resInfo);
}
void addDep(Klass ref, ResolutionInfo ri) {
if (skip(ref)) {
return;
}
Set<ResolutionInfo> resInfos;
if (!deps.containsKey(ref)) {
resInfos = new TreeSet<ResolutionInfo>();
deps.put(ref, resInfos);
} else {
resInfos = deps.get(ref);
}
resInfos.add(ri);
}
void addReferrer(Method caller, ResolutionInfo resInfo) {
addReferrer(caller.getKlass(), resInfo);
}
void addReferrer(Klass k, ResolutionInfo ri) {
if (skip(k)) {
return;
}
Set<ResolutionInfo> resInfos;
if (!referrers.containsKey(k)) {
resInfos = new TreeSet<ResolutionInfo>();
referrers.put(k, resInfos);
} else {
resInfos = referrers.get(k);
}
resInfos.add(ri);
}
Method getMethod(String name) {
return getMethod(name, "");
}
Method getMethod(String name, String signature) {
Set<Method> set;
if (methods.containsKey(name)) {
set = methods.get(name);
} else {
set = new TreeSet<Method>();
methods.put(name, set);
}
for (Method m : set) {
if (m.getName().equals(name) && m.getSignature().equals(signature)) {
return m;
}
}
Method m = new Method(this, name, signature);
set.add(m);
return m;
}
@Override
public String toString() {
return classname;
}
@Override
public int compareTo(Klass o) {
return classname.compareTo(o.classname);
}
void addAnnotatedDep(AnnotatedDependency dep) {
annotatedDeps.add(dep);
}
void addClassForNameReference(String method) {
classForNameRefs.add(method);
}
List<AnnotatedDependency> getAnnotatedDeps() {
return annotatedDeps;
}
private static Map<String, Klass> classes = new TreeMap<String, Klass>();
static Set<Klass> getAllClasses() {
return new TreeSet<Klass>(classes.values());
}
static Klass findKlassFromPathname(String filename) {
String name = filename;
if (filename.endsWith(".class")) {
name = filename.substring(0, filename.length() - 6);
}
// trim ".class"
name = name.replace('/', '.');
for (Klass k : classes.values()) {
if (name.endsWith(k.getClassName())) {
return k;
}
}
return null;
}
static Klass findKlass(String classname) {
return classes.get(classname);
}
static Klass getKlass(String name) {
Klass k;
String classname = name.replace('/', '.');
if (classname.charAt(classname.length() - 1) == ';') {
classname = classname.substring(0, classname.length() - 1);
}
if (classes.containsKey(classname)) {
k = classes.get(classname);
} else {
k = new Klass(classname);
classes.put(classname, k);
}
return k;
}
public class Method implements Comparable<Method> {
private final Klass k;
private final String method;
private final String signature;
private long codeLength;
// non-primitive types only
private final List<Klass> argTypes;
private final Klass returnType;
boolean isAbstract = false;
boolean marked = false;
public Method(Klass k, String method, String signature) {
this(k, method, signature, null, null);
}
public Method(Klass k, String method, String signature, Klass returnType, List<Klass> argTypes) {
this.k = k;
this.method = method;
this.signature = signature;
this.argTypes = argTypes;
this.returnType = returnType;
this.codeLength = 0;
}
public Klass getKlass() {
return k;
}
public String getName() {
return method;
}
public String getSignature() {
return signature;
}
public Klass getReturnType() {
return returnType;
}
public List<Klass> argTypes() {
return argTypes;
}
public void setCodeLength(long len) {
this.codeLength = len;
}
public long getCodeLength() {
return codeLength;
}
@Override
public boolean equals(Object o) {
if (o instanceof Method) {
return compareTo((Method) o) == 0;
} else {
return false;
}
}
@Override
public int hashCode() {
int hash = 3;
hash = 71 * hash + (this.k != null ? this.k.hashCode() : 0);
hash = 71 * hash + (this.method != null ? this.method.hashCode() : 0);
return hash;
}
@Override
public String toString() {
if (signature.isEmpty()) {
return k.classname + "." + method;
} else {
return signature;
}
}
public String toHtmlString() {
return toString().replace("<", "&lt;").replace(">", "&gt;");
}
boolean isClinit() {
return method.equals("<clinit>");
}
public int compareTo(Method m) {
if (k == m.getKlass()) {
if (method.equals(m.method)) {
return signature.compareTo(m.signature);
} else {
return method.compareTo(m.method);
}
} else {
return k.compareTo(m.getKlass());
}
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}
}
}
}

View File

@ -93,6 +93,7 @@ static int numOptions, maxOptions;
* Prototypes for functions internal to launcher.
*/
static void SetClassPath(const char *s);
static void SetModulesBootClassPath(const char *s);
static void SelectVersion(int argc, char **argv, char **main_class);
static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
char **pclassname, int *pret, const char *jvmpath);
@ -277,6 +278,9 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
return(ret);
}
/* Set bootclasspath for modules */
SetModulesBootClassPath(jrepath);
/* Override class path if -jar flag was specified */
if (jarfile != 0) {
SetClassPath(jarfile);
@ -693,6 +697,44 @@ SetClassPath(const char *s)
JLI_MemFree((char *) s);
}
/*
* Set the bootclasspath for modules.
* A temporary workaround until jigsaw is integrated into JDK 7.
*/
static void
SetModulesBootClassPath(const char *jrepath)
{
char *def, *s;
char pathname[MAXPATHLEN];
const char separator[] = { FILE_SEPARATOR, '\0' };
const char *orig = jrepath;
static const char format[] = "-Xbootclasspath/p:%s";
struct stat statbuf;
/* return if jre/lib/rt.jar exists */
sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
if (stat(pathname, &statbuf) == 0) {
return;
}
/* return if jre/classes exists */
sprintf(pathname, "%s%sclasses", jrepath, separator);
if (stat(pathname, &statbuf) == 0) {
return;
}
/* modularized jre */
sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
s = (char *) JLI_WildcardExpandClasspath(pathname);
def = JLI_MemAlloc(sizeof(format)
- 2 /* strlen("%s") */
+ JLI_StrLen(s));
sprintf(def, format, s);
AddOption(def, NULL);
if (s != orig)
JLI_MemFree((char *) s);
}
/*
* The SelectVersion() routine ensures that an appropriate version of
* the JRE is running. The specification for the appropriate version

View File

@ -33,10 +33,10 @@ import java.lang.reflect.InvocationTargetException;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;
import java.applet.Applet;
import org.omg.CORBA.ORB;
import javax.naming.Context;
import javax.naming.ConfigurationException;
/**
@ -191,16 +191,48 @@ public class CorbaUtils {
}
// Get Applet from environment
Applet applet = null;
if (env != null) {
applet = (Applet) env.get("java.naming.applet");
Object applet = env.get(Context.APPLET);
if (applet != null) {
// Create ORBs for an applet
return initAppletORB(applet, orbProp);
}
}
// Create ORBs using applet and orbProp
if (applet != null) {
return ORB.init(applet, orbProp);
} else {
return ORB.init(new String[0], orbProp);
// Create ORBs using orbProp for a standalone application
return ORB.init(new String[0], orbProp);
}
/**
* This method returns a new ORB instance for the given applet
* without creating a static dependency on java.applet.
*/
private static ORB initAppletORB(Object applet, Properties orbProp) {
try {
Class<?> appletClass = Class.forName("java.applet.Applet", true, null);
if (!appletClass.isInstance(applet)) {
throw new ClassCastException(applet.getClass().getName());
}
// invoke the static method ORB.init(applet, orbProp);
Method method = ORB.class.getMethod("init", appletClass, Properties.class);
return (ORB) method.invoke(null, applet, orbProp);
} catch (ClassNotFoundException e) {
// java.applet.Applet doesn't exist and the applet parameter is
// non-null; so throw CCE
throw new ClassCastException(applet.getClass().getName());
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new AssertionError(e);
} catch (IllegalAccessException iae) {
throw new AssertionError(iae);
}
}

View File

@ -26,6 +26,7 @@
package java.lang;
import java.util.Random;
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;
/**
* The class {@code StrictMath} contains methods for performing basic
@ -316,7 +317,9 @@ public final class StrictMath {
* floating-point value that is greater than or equal to
* the argument and is equal to a mathematical integer.
*/
public static native double ceil(double a);
public static double ceil(double a) {
return floorOrCeil(a, -0.0, 1.0, 1.0);
}
/**
* Returns the largest (closest to positive infinity)
@ -333,7 +336,54 @@ public final class StrictMath {
* floating-point value that less than or equal to the argument
* and is equal to a mathematical integer.
*/
public static native double floor(double a);
public static double floor(double a) {
return floorOrCeil(a, -1.0, 0.0, -1.0);
}
/**
* Internal method to share logic between floor and ceil.
*
* @param a the value to be floored or ceiled
* @param negativeBoundary result for values in (-1, 0)
* @param positiveBoundary result for values in (0, 1)
* @param increment value to add when the argument is non-integral
*/
private static double floorOrCeil(double a,
double negativeBoundary,
double positiveBoundary,
double sign) {
int exponent = Math.getExponent(a);
if (exponent < 0) {
/*
* Absolute value of argument is less than 1.
* floorOrceil(-0.0) => -0.0
* floorOrceil(+0.0) => +0.0
*/
return ((a == 0.0) ? a :
( (a < 0.0) ? negativeBoundary : positiveBoundary) );
} else if (exponent >= 52) {
/*
* Infinity, NaN, or a value so large it must be integral.
*/
return a;
}
// Else the argument is either an integral value already XOR it
// has to be rounded to one.
assert exponent >= 0 && exponent <= 51;
long doppel = Double.doubleToRawLongBits(a);
long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
if ( (mask & doppel) == 0L )
return a; // integral value
else {
double result = Double.longBitsToDouble(doppel & (~mask));
if (sign*a > 0.0)
result = result + sign;
return result;
}
}
/**
* Returns the {@code double} value that is closest in value

View File

@ -32,7 +32,7 @@ import javax.management.ObjectName;
* for monitoring and managing a component in the Java platform.
* Each platform managed object has a unique
* <a href="ManagementFactory.html#MXBean">object name</a>
* for the {@linkplain ManagementFactory.getPlatformMBeanServer
* for the {@linkplain ManagementFactory#getPlatformMBeanServer
* platform MBeanServer} access.
* All platform MXBeans will implement this interface.
*

View File

@ -32,24 +32,24 @@ import java.io.IOException;
#end[char]
/**
* $A$ $fulltype$ buffer.
* $A$ $type$ buffer.
*
* <p> This class defines {#if[byte]?six:four} categories of operations upon
* $fulltype$ buffers:
* $type$ buffers:
*
* <ul>
*
* <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
* {@link #put($type$) </code><i>put</i><code>} methods that read and write
* single $fulltype$s; </p></li>
* single $type$s; </p></li>
*
* <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
* methods that transfer contiguous sequences of $fulltype$s from this buffer
* methods that transfer contiguous sequences of $type$s from this buffer
* into an array; {#if[!byte]?and}</p></li>
*
* <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
* methods that transfer contiguous sequences of $fulltype$s from $a$
* $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
* methods that transfer contiguous sequences of $type$s from $a$
* $type$ array{#if[char]?,&#32;a&#32;string,} or some other $type$
* buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
*
#if[byte]
@ -67,22 +67,22 @@ import java.io.IOException;
*
* <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
* #duplicate </code>duplicating<code>}, and {@link #slice
* </code>slicing<code>} $a$ $fulltype$ buffer. </p></li>
* </code>slicing<code>} $a$ $type$ buffer. </p></li>
*
* </ul>
*
* <p> $Fulltype$ buffers can be created either by {@link #allocate
* <p> $Type$ buffers can be created either by {@link #allocate
* </code><i>allocation</i><code>}, which allocates space for the buffer's
*
#if[byte]
*
* content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
* existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
* existing $type$ array {#if[char]?or&#32;string} into a buffer.
*
#else[byte]
*
* content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
* $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
* $type$ array {#if[char]?or&#32;string} into a buffer, or by creating a
* <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
*
#end[byte]
@ -189,12 +189,12 @@ import java.io.IOException;
*
#if[!byte]
*
* <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
* <p> Like a byte buffer, $a$ $type$ buffer is either <a
* href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>. A
* $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
* be non-direct. $A$ $fulltype$ buffer created as a view of a byte buffer will
* $type$ buffer created via the <tt>wrap</tt> methods of this class will
* be non-direct. $A$ $type$ buffer created as a view of a byte buffer will
* be direct if, and only if, the byte buffer itself is direct. Whether or not
* $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
* $a$ $type$ buffer is direct may be determined by invoking the {@link
* #isDirect isDirect} method. </p>
*
#end[!byte]
@ -287,7 +287,7 @@ public abstract class $Type$Buffer
#if[byte]
/**
* Allocates a new direct $fulltype$ buffer.
* Allocates a new direct $type$ buffer.
*
* <p> The new buffer's position will be zero, its limit will be its
* capacity, its mark will be undefined, and each of its elements will be
@ -295,9 +295,9 @@ public abstract class $Type$Buffer
* {@link #hasArray </code>backing array<code>} is unspecified.
*
* @param capacity
* The new buffer's capacity, in $fulltype$s
* The new buffer's capacity, in $type$s
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*
* @throws IllegalArgumentException
* If the <tt>capacity</tt> is a negative integer
@ -309,7 +309,7 @@ public abstract class $Type$Buffer
#end[byte]
/**
* Allocates a new $fulltype$ buffer.
* Allocates a new $type$ buffer.
*
* <p> The new buffer's position will be zero, its limit will be its
* capacity, its mark will be undefined, and each of its elements will be
@ -318,9 +318,9 @@ public abstract class $Type$Buffer
* offset<code>} will be zero.
*
* @param capacity
* The new buffer's capacity, in $fulltype$s
* The new buffer's capacity, in $type$s
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*
* @throws IllegalArgumentException
* If the <tt>capacity</tt> is a negative integer
@ -332,9 +332,9 @@ public abstract class $Type$Buffer
}
/**
* Wraps $a$ $fulltype$ array into a buffer.
* Wraps $a$ $type$ array into a buffer.
*
* <p> The new buffer will be backed by the given $fulltype$ array;
* <p> The new buffer will be backed by the given $type$ array;
* that is, modifications to the buffer will cause the array to be modified
* and vice versa. The new buffer's capacity will be
* <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
@ -356,7 +356,7 @@ public abstract class $Type$Buffer
* <tt>array.length - offset</tt>.
* The new buffer's limit will be set to <tt>offset + length</tt>.
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*
* @throws IndexOutOfBoundsException
* If the preconditions on the <tt>offset</tt> and <tt>length</tt>
@ -373,9 +373,9 @@ public abstract class $Type$Buffer
}
/**
* Wraps $a$ $fulltype$ array into a buffer.
* Wraps $a$ $type$ array into a buffer.
*
* <p> The new buffer will be backed by the given $fulltype$ array;
* <p> The new buffer will be backed by the given $type$ array;
* that is, modifications to the buffer will cause the array to be modified
* and vice versa. The new buffer's capacity and limit will be
* <tt>array.length</tt>, its position will be zero, and its mark will be
@ -386,7 +386,7 @@ public abstract class $Type$Buffer
* @param array
* The array that will back this buffer
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*/
public static $Type$Buffer wrap($type$[] array) {
return wrap(array, 0, array.length);
@ -486,7 +486,7 @@ public abstract class $Type$Buffer
#end[char]
/**
* Creates a new $fulltype$ buffer whose content is a shared subsequence of
* Creates a new $type$ buffer whose content is a shared subsequence of
* this buffer's content.
*
* <p> The content of the new buffer will start at this buffer's current
@ -495,17 +495,17 @@ public abstract class $Type$Buffer
* values will be independent.
*
* <p> The new buffer's position will be zero, its capacity and its limit
* will be the number of $fulltype$s remaining in this buffer, and its mark
* will be the number of $type$s remaining in this buffer, and its mark
* will be undefined. The new buffer will be direct if, and only if, this
* buffer is direct, and it will be read-only if, and only if, this buffer
* is read-only. </p>
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*/
public abstract $Type$Buffer slice();
/**
* Creates a new $fulltype$ buffer that shares this buffer's content.
* Creates a new $type$ buffer that shares this buffer's content.
*
* <p> The content of the new buffer will be that of this buffer. Changes
* to this buffer's content will be visible in the new buffer, and vice
@ -517,12 +517,12 @@ public abstract class $Type$Buffer
* and only if, this buffer is direct, and it will be read-only if, and
* only if, this buffer is read-only. </p>
*
* @return The new $fulltype$ buffer
* @return The new $type$ buffer
*/
public abstract $Type$Buffer duplicate();
/**
* Creates a new, read-only $fulltype$ buffer that shares this buffer's
* Creates a new, read-only $type$ buffer that shares this buffer's
* content.
*
* <p> The content of the new buffer will be that of this buffer. Changes
@ -537,7 +537,7 @@ public abstract class $Type$Buffer
* <p> If this buffer is itself read-only then this method behaves in
* exactly the same way as the {@link #duplicate duplicate} method. </p>
*
* @return The new, read-only $fulltype$ buffer
* @return The new, read-only $type$ buffer
*/
public abstract $Type$Buffer asReadOnlyBuffer();
@ -545,10 +545,10 @@ public abstract class $Type$Buffer
// -- Singleton get/put methods --
/**
* Relative <i>get</i> method. Reads the $fulltype$ at this buffer's
* Relative <i>get</i> method. Reads the $type$ at this buffer's
* current position, and then increments the position. </p>
*
* @return The $fulltype$ at the buffer's current position
* @return The $type$ at the buffer's current position
*
* @throws BufferUnderflowException
* If the buffer's current position is not smaller than its limit
@ -558,11 +558,11 @@ public abstract class $Type$Buffer
/**
* Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> Writes the given $fulltype$ into this buffer at the current
* <p> Writes the given $type$ into this buffer at the current
* position, and then increments the position. </p>
*
* @param $x$
* The $fulltype$ to be written
* The $type$ to be written
*
* @return This buffer
*
@ -575,13 +575,13 @@ public abstract class $Type$Buffer
public abstract $Type$Buffer put($type$ $x$);
/**
* Absolute <i>get</i> method. Reads the $fulltype$ at the given
* Absolute <i>get</i> method. Reads the $type$ at the given
* index. </p>
*
* @param index
* The index from which the $fulltype$ will be read
* The index from which the $type$ will be read
*
* @return The $fulltype$ at the given index
* @return The $type$ at the given index
*
* @throws IndexOutOfBoundsException
* If <tt>index</tt> is negative
@ -592,14 +592,14 @@ public abstract class $Type$Buffer
/**
* Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> Writes the given $fulltype$ into this buffer at the given
* <p> Writes the given $type$ into this buffer at the given
* index. </p>
*
* @param index
* The index at which the $fulltype$ will be written
* The index at which the $type$ will be written
*
* @param $x$
* The $fulltype$ value to be written
* The $type$ value to be written
*
* @return This buffer
*
@ -618,14 +618,14 @@ public abstract class $Type$Buffer
/**
* Relative bulk <i>get</i> method.
*
* <p> This method transfers $fulltype$s from this buffer into the given
* destination array. If there are fewer $fulltype$s remaining in the
* <p> This method transfers $type$s from this buffer into the given
* destination array. If there are fewer $type$s remaining in the
* buffer than are required to satisfy the request, that is, if
* <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
* $fulltype$s are transferred and a {@link BufferUnderflowException} is
* $type$s are transferred and a {@link BufferUnderflowException} is
* thrown.
*
* <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
* <p> Otherwise, this method copies <tt>length</tt> $type$s from this
* buffer into the given array, starting at the current position of this
* buffer and at the given offset in the array. The position of this
* buffer is then incremented by <tt>length</tt>.
@ -638,26 +638,26 @@ public abstract class $Type$Buffer
* for (int i = off; i < off + len; i++)
* dst[i] = src.get(); </pre>
*
* except that it first checks that there are sufficient $fulltype$s in
* except that it first checks that there are sufficient $type$s in
* this buffer and it is potentially much more efficient. </p>
*
* @param dst
* The array into which $fulltype$s are to be written
* The array into which $type$s are to be written
*
* @param offset
* The offset within the array of the first $fulltype$ to be
* The offset within the array of the first $type$ to be
* written; must be non-negative and no larger than
* <tt>dst.length</tt>
*
* @param length
* The maximum number of $fulltype$s to be written to the given
* The maximum number of $type$s to be written to the given
* array; must be non-negative and no larger than
* <tt>dst.length - offset</tt>
*
* @return This buffer
*
* @throws BufferUnderflowException
* If there are fewer than <tt>length</tt> $fulltype$s
* If there are fewer than <tt>length</tt> $type$s
* remaining in this buffer
*
* @throws IndexOutOfBoundsException
@ -677,7 +677,7 @@ public abstract class $Type$Buffer
/**
* Relative bulk <i>get</i> method.
*
* <p> This method transfers $fulltype$s from this buffer into the given
* <p> This method transfers $type$s from this buffer into the given
* destination array. An invocation of this method of the form
* <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
*
@ -687,7 +687,7 @@ public abstract class $Type$Buffer
* @return This buffer
*
* @throws BufferUnderflowException
* If there are fewer than <tt>length</tt> $fulltype$s
* If there are fewer than <tt>length</tt> $type$s
* remaining in this buffer
*/
public $Type$Buffer get($type$[] dst) {
@ -700,15 +700,15 @@ public abstract class $Type$Buffer
/**
* Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> This method transfers the $fulltype$s remaining in the given source
* buffer into this buffer. If there are more $fulltype$s remaining in the
* <p> This method transfers the $type$s remaining in the given source
* buffer into this buffer. If there are more $type$s remaining in the
* source buffer than in this buffer, that is, if
* <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
* then no $fulltype$s are transferred and a {@link
* then no $type$s are transferred and a {@link
* BufferOverflowException} is thrown.
*
* <p> Otherwise, this method copies
* <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
* <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $type$s from the given
* buffer into this buffer, starting at each buffer's current position.
* The positions of both buffers are then incremented by <i>n</i>.
*
@ -723,14 +723,14 @@ public abstract class $Type$Buffer
* buffer and it is potentially much more efficient. </p>
*
* @param src
* The source buffer from which $fulltype$s are to be read;
* The source buffer from which $type$s are to be read;
* must not be this buffer
*
* @return This buffer
*
* @throws BufferOverflowException
* If there is insufficient space in this buffer
* for the remaining $fulltype$s in the source buffer
* for the remaining $type$s in the source buffer
*
* @throws IllegalArgumentException
* If the source buffer is this buffer
@ -752,14 +752,14 @@ public abstract class $Type$Buffer
/**
* Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> This method transfers $fulltype$s into this buffer from the given
* source array. If there are more $fulltype$s to be copied from the array
* <p> This method transfers $type$s into this buffer from the given
* source array. If there are more $type$s to be copied from the array
* than remain in this buffer, that is, if
* <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
* $fulltype$s are transferred and a {@link BufferOverflowException} is
* $type$s are transferred and a {@link BufferOverflowException} is
* thrown.
*
* <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
* <p> Otherwise, this method copies <tt>length</tt> $type$s from the
* given array into this buffer, starting at the given offset in the array
* and at the current position of this buffer. The position of this buffer
* is then incremented by <tt>length</tt>.
@ -776,14 +776,14 @@ public abstract class $Type$Buffer
* buffer and it is potentially much more efficient. </p>
*
* @param src
* The array from which $fulltype$s are to be read
* The array from which $type$s are to be read
*
* @param offset
* The offset within the array of the first $fulltype$ to be read;
* The offset within the array of the first $type$ to be read;
* must be non-negative and no larger than <tt>array.length</tt>
*
* @param length
* The number of $fulltype$s to be read from the given array;
* The number of $type$s to be read from the given array;
* must be non-negative and no larger than
* <tt>array.length - offset</tt>
*
@ -813,7 +813,7 @@ public abstract class $Type$Buffer
* Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> This method transfers the entire content of the given source
* $fulltype$ array into this buffer. An invocation of this method of the
* $type$ array into this buffer. An invocation of this method of the
* form <tt>dst.put(a)</tt> behaves in exactly the same way as the
* invocation
*
@ -837,15 +837,15 @@ public abstract class $Type$Buffer
/**
* Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> This method transfers $fulltype$s from the given string into this
* buffer. If there are more $fulltype$s to be copied from the string than
* <p> This method transfers $type$s from the given string into this
* buffer. If there are more $type$s to be copied from the string than
* remain in this buffer, that is, if
* <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
* then no $fulltype$s are transferred and a {@link
* then no $type$s are transferred and a {@link
* BufferOverflowException} is thrown.
*
* <p> Otherwise, this method copies
* <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
* <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $type$s
* from the given string into this buffer, starting at the given
* <tt>start</tt> index and at the current position of this buffer. The
* position of this buffer is then incremented by <i>n</i>.
@ -862,15 +862,15 @@ public abstract class $Type$Buffer
* buffer and it is potentially much more efficient. </p>
*
* @param src
* The string from which $fulltype$s are to be read
* The string from which $type$s are to be read
*
* @param start
* The offset within the string of the first $fulltype$ to be read;
* The offset within the string of the first $type$ to be read;
* must be non-negative and no larger than
* <tt>string.length()</tt>
*
* @param end
* The offset within the string of the last $fulltype$ to be read,
* The offset within the string of the last $type$ to be read,
* plus one; must be non-negative and no larger than
* <tt>string.length()</tt>
*
@ -921,7 +921,7 @@ public abstract class $Type$Buffer
// -- Other stuff --
/**
* Tells whether or not this buffer is backed by an accessible $fulltype$
* Tells whether or not this buffer is backed by an accessible $type$
* array.
*
* <p> If this method returns <tt>true</tt> then the {@link #array() array}
@ -936,7 +936,7 @@ public abstract class $Type$Buffer
}
/**
* Returns the $fulltype$ array that backs this
* Returns the $type$ array that backs this
* buffer&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> Modifications to this buffer's content will cause the returned
@ -993,17 +993,17 @@ public abstract class $Type$Buffer
/**
* Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> The $fulltype$s between the buffer's current position and its limit,
* <p> The $type$s between the buffer's current position and its limit,
* if any, are copied to the beginning of the buffer. That is, the
* $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
* to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
* to index one, and so forth until the $fulltype$ at index
* $type$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
* to index zero, the $type$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
* to index one, and so forth until the $type$ at index
* <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
* <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
* The buffer's position is then set to <i>n+1</i> and its limit is set to
* its capacity. The mark, if defined, is discarded.
*
* <p> The buffer's position is set to the number of $fulltype$s copied,
* <p> The buffer's position is set to the number of $type$s copied,
* rather than to zero, so that an invocation of this method can be
* followed immediately by an invocation of another relative <i>put</i>
* method. </p>
@ -1032,7 +1032,7 @@ public abstract class $Type$Buffer
public abstract $Type$Buffer compact();
/**
* Tells whether or not this $fulltype$ buffer is direct. </p>
* Tells whether or not this $type$ buffer is direct. </p>
*
* @return <tt>true</tt> if, and only if, this buffer is direct
*/
@ -1098,6 +1098,13 @@ public abstract class $Type$Buffer
*
* <li><p> The two sequences of remaining elements, considered
* independently of their starting positions, are pointwise equal.
#if[floatingPointType]
* This method considers two $type$ elements {@code a} and {@code b}
* to be equal if
* {@code (a == b) || ($Fulltype$.isNaN(a) && $Fulltype$.isNaN(b))}.
* The values {@code -0.0} and {@code +0.0} are considered to be
* equal, unlike {@link $Fulltype$#equals(Object)}.
#end[floatingPointType]
* </p></li>
*
* </ol>
@ -1118,24 +1125,37 @@ public abstract class $Type$Buffer
if (this.remaining() != that.remaining())
return false;
int p = this.position();
for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
$type$ v1 = this.get(i);
$type$ v2 = that.get(j);
if (v1 != v2) {
if ((v1 != v1) && (v2 != v2)) // For float and double
continue;
for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
if (!equals(this.get(i), that.get(j)))
return false;
}
}
return true;
}
private static boolean equals($type$ x, $type$ y) {
#if[floatingPointType]
return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y));
#else[floatingPointType]
return x == y;
#end[floatingPointType]
}
/**
* Compares this buffer to another.
*
* <p> Two $type$ buffers are compared by comparing their sequences of
* remaining elements lexicographically, without regard to the starting
* position of each sequence within its corresponding buffer.
#if[floatingPointType]
* Pairs of {@code $type$} elements are compared as if by invoking
* {@link $Fulltype$#compare($type$,$type$)}, except that
* {@code -0.0} and {@code 0.0} are considered to be equal.
* {@code $Fulltype$.NaN} is considered by this method to be equal
* to itself and greater than all other {@code $type$} values
* (including {@code $Fulltype$.POSITIVE_INFINITY}).
#else[floatingPointType]
* Pairs of {@code $type$} elements are compared as if by invoking
* {@link $Fulltype$#compare($type$,$type$)}.
#end[floatingPointType]
*
* <p> A $type$ buffer is not comparable to any other type of object.
*
@ -1145,20 +1165,23 @@ public abstract class $Type$Buffer
public int compareTo($Type$Buffer that) {
int n = this.position() + Math.min(this.remaining(), that.remaining());
for (int i = this.position(), j = that.position(); i < n; i++, j++) {
$type$ v1 = this.get(i);
$type$ v2 = that.get(j);
if (v1 == v2)
continue;
if ((v1 != v1) && (v2 != v2)) // For float and double
continue;
if (v1 < v2)
return -1;
return +1;
int cmp = compare(this.get(i), that.get(j));
if (cmp != 0)
return cmp;
}
return this.remaining() - that.remaining();
}
private static int compare($type$ x, $type$ y) {
#if[floatingPointType]
return ((x < y) ? -1 :
(x > y) ? +1 :
(x == y) ? 0 :
$Fulltype$.isNaN(x) ? ($Fulltype$.isNaN(y) ? 0 : +1) : -1);
#else[floatingPointType]
return $Fulltype$.compare(x, y);
#end[floatingPointType]
}
// -- Other char stuff --
@ -1326,7 +1349,7 @@ public abstract class $Type$Buffer
}
/**
* Appends the specified $fulltype$ to this
* Appends the specified $type$ to this
* buffer&nbsp;&nbsp;<i>(optional operation)</i>.
*
* <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
@ -1336,7 +1359,7 @@ public abstract class $Type$Buffer
* dst.put($x$) </pre>
*
* @param $x$
* The 16-bit $fulltype$ to append
* The 16-bit $type$ to append
*
* @return This buffer
*
@ -1362,10 +1385,10 @@ public abstract class $Type$Buffer
/**
* Retrieves this buffer's byte order.
*
* <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
* <p> The byte order of $a$ $type$ buffer created by allocation or by
* wrapping an existing <tt>$type$</tt> array is the {@link
* ByteOrder#nativeOrder </code>native order<code>} of the underlying
* hardware. The byte order of $a$ $fulltype$ buffer created as a <a
* hardware. The byte order of $a$ $type$ buffer created as a <a
* href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
* byte buffer at the moment that the view is created. </p>
*

View File

@ -73,7 +73,7 @@ public abstract class Activatable extends RemoteServer {
* can be handled properly.
*
* <p>This method invokes the {@link
* exportObject(Remote,String,MarshalledObject,boolean,port)
* #exportObject(Remote,String,MarshalledObject,boolean,int)
* exportObject} method with this object, and the specified location,
* data, restart mode, and port. Subsequent calls to {@link #getID}
* will return the activation identifier returned from the call to
@ -120,7 +120,7 @@ public abstract class Activatable extends RemoteServer {
* can be handled properly.
*
* <p>This method invokes the {@link
* exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
* #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
* exportObject} method with this object, and the specified location,
* data, restart mode, port, and client and server socket factories.
* Subsequent calls to {@link #getID} will return the activation
@ -312,7 +312,7 @@ public abstract class Activatable extends RemoteServer {
* separately, so that exceptions can be handled properly.
*
* <p>This method invokes the {@link
* exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
* #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
* exportObject} method with the specified object, location, data,
* restart mode, and port, and <code>null</code> for both client and
* server socket factories, and then returns the resulting activation

View File

@ -187,7 +187,7 @@ public final class LocateRegistry {
* host that accepts requests on the specified <code>port</code>.
*
* <p>The <code>Registry</code> instance is exported as if the static
* {@link UnicastRemoteObject.exportObject(Remote,int)
* {@link UnicastRemoteObject#exportObject(Remote,int)
* UnicastRemoteObject.exportObject} method is invoked, passing the
* <code>Registry</code> instance and the specified <code>port</code> as
* arguments, except that the <code>Registry</code> instance is
@ -213,7 +213,7 @@ public final class LocateRegistry {
*
* <p>The <code>Registry</code> instance is exported as if
* the static {@link
* UnicastRemoteObject.exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
* UnicastRemoteObject#exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
* UnicastRemoteObject.exportObject} method is invoked, passing the
* <code>Registry</code> instance, the specified <code>port</code>, the
* specified <code>RMIClientSocketFactory</code>, and the specified

View File

@ -138,7 +138,6 @@ public class RemoteObjectInvocationHandler
* instance
* @throws Throwable the exception to throw from the method invocation
* on the proxy instance
* @see
**/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable

View File

@ -216,7 +216,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
/**
* Returns the reason that the validation failed. The reason is
* associated with the index of the certificate returned by
* {@link getIndex}.
* {@link #getIndex}.
*
* @return the reason that the validation failed, or
* <code>BasicReason.UNSPECIFIED</code> if a reason has not been

View File

@ -121,9 +121,9 @@ public final class Bidi {
*
* @param paragraph a paragraph of text with optional character and paragraph attribute information
*
* @see TextAttribute#BIDI_EMBEDDING
* @see TextAttribute#NUMERIC_SHAPING
* @see TextAttribute#RUN_DIRECTION
* @see java.awt.font.TextAttribute#BIDI_EMBEDDING
* @see java.awt.font.TextAttribute#NUMERIC_SHAPING
* @see java.awt.font.TextAttribute#RUN_DIRECTION
*/
public Bidi(AttributedCharacterIterator paragraph) {
if (paragraph == null) {

View File

@ -119,7 +119,7 @@ public final class Objects {
*
* @param values the values to be hashed
* @return a hash value of the sequence of input values
* @see Arrays#hashCode
* @see Arrays#hashCode(Object[])
* @see List#hashCode
*/
public static int hash(Object... values) {

View File

@ -51,7 +51,7 @@ import java.lang.management.PlatformManagedObject;
* The {@link PlatformManagedObject#getObjectName} method
* can be used to obtain its {@code ObjectName}.
*
* @See java.lang.management.PlatformManagedObject
* @see java.lang.management.PlatformManagedObject
*
* @author Mandy Chung
* @since 1.7

View File

@ -296,7 +296,7 @@ public abstract class AccessibleContext {
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see #AccessibleText.AccessibleTextSequence
* @see AccessibleTextSequence
*/
public static final String ACCESSIBLE_TEXT_PROPERTY
= "AccessibleText";
@ -311,7 +311,7 @@ public abstract class AccessibleContext {
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see #AccessibleText.AccessibleTextSequence
* @see AccessibleTextSequence
*
* @since 1.5
*/
@ -334,7 +334,7 @@ public abstract class AccessibleContext {
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see #AccessibleText.AccessibleAttributeSequence
* @see AccessibleAttributeSequence
*
* @since 1.5
*/

View File

@ -45,7 +45,6 @@ import javax.swing.text.*;
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
* @see AccessibleText.AccessibleTextChunk
*
* @author Peter Korn
* @author Lynn Monsanto

View File

@ -32,16 +32,11 @@ package javax.accessibility;
* the standard mechanism for an assistive technology to determine the
* key bindings which exist for this object.
* Any object that has such key bindings should support this
* interface. Applications can determine if an object supports the
* AccessibleKeyBinding interface by first obtaining its AccessibleContext
* (see @link Accessible} and then calling the
* {@link AccessibleContext#getAccessibleKeyBinding} method. If the return
* value is not null, the object supports this interface.
* interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleKeyBinding
*
* @author Lynn Monsanto
* @since 1.4
@ -58,21 +53,7 @@ public interface AccessibleKeyBinding {
/**
* Returns a key binding for this object. The value returned is an
* java.lang.Object which must be cast to appropriate type depending
* on the underlying implementation of the key. For example, if the
* Object returned is a javax.swing.KeyStroke, the user of this
* method should do the following:
* <nf><code>
* Component c = <get the component that has the key bindings>
* AccessibleContext ac = c.getAccessibleContext();
* AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
* for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
* Object o = akb.getAccessibleKeyBinding(i);
* if (o instanceof javax.swing.KeyStroke) {
* javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
* <do something with the key binding>
* }
* }
* </code></nf>
* on the underlying implementation of the key.
*
* @param i zero-based index of the key bindings
* @return a javax.lang.Object which specifies the key binding

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -103,11 +103,12 @@ public interface GSSName {
* follows: service@hostname.<p>
*
* It represents the following Oid value:<br>
* <code>{ 1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 2(gss-host-based-services) }</code>
* <code>{ iso(1) member-body(2) United
* States(840) mit(113554) infosys(1) gssapi(2) generic(1) service_name(4)
* }</code>
*/
public static final Oid NT_HOSTBASED_SERVICE
= Oid.getInstance("1.3.6.1.5.6.2");
= Oid.getInstance("1.2.840.113554.1.2.1.4");
/**
* Name type to indicate a named user on a local system.<p>

View File

@ -326,7 +326,7 @@ public final class DOMXMLSignature extends DOMStructure
}
// generate references and signature value
List allReferences = new ArrayList(si.getReferences());
List allReferences = new ArrayList();
// traverse the Signature and register all objects with IDs that
// may contain References
@ -356,6 +356,9 @@ public final class DOMXMLSignature extends DOMStructure
}
}
}
// always add SignedInfo references after Manifest references so
// that Manifest reference are digested first
allReferences.addAll(si.getReferences());
// generate/digest each reference
for (int i = 0, size = allReferences.size(); i < size; i++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -89,6 +89,11 @@ public class GSSManagerImpl extends GSSManager {
Oid[] retVal = new Oid[mechs.length];
int pos = 0;
// Compatibility with RFC 2853 old NT_HOSTBASED_SERVICE value.
if (nameType.equals(GSSNameImpl.oldHostbasedServiceName)) {
nameType = GSSName.NT_HOSTBASED_SERVICE;
}
// Iterate thru all mechs in GSS
for (int i = 0; i < mechs.length; i++) {
// what nametypes does this mech support?

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -81,6 +81,29 @@ import sun.security.util.DerOutputStream;
public class GSSNameImpl implements GSSName {
/**
* The old Oid used in RFC 2853. Now supported as
* input parameters in:
*
* 1. The four overloaded GSSManager.createName(*) methods
* 2. GSSManager.getMechsForName(Oid)
*
* Note that even if a GSSName is created with this old Oid,
* its internal name type and getStringNameType() output are
* always the new value.
*/
final static Oid oldHostbasedServiceName;
static {
Oid tmp = null;
try {
tmp = new Oid("1.3.6.1.5.6.2");
} catch (Exception e) {
// should never happen
}
oldHostbasedServiceName = tmp;
}
private GSSManagerImpl gssManager = null;
/*
@ -134,6 +157,9 @@ public class GSSNameImpl implements GSSName {
Oid mech)
throws GSSException {
if (oldHostbasedServiceName.equals(appNameType)) {
appNameType = GSSName.NT_HOSTBASED_SERVICE;
}
if (appName == null)
throw new GSSExceptionImpl(GSSException.BAD_NAME,
"Cannot import null name");

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -66,9 +66,6 @@ public class GSSUtil {
public static final Oid NT_GSS_KRB5_PRINCIPAL =
GSSUtil.createOid("1.2.840.113554.1.2.2.1");
public static final Oid NT_HOSTBASED_SERVICE2 =
GSSUtil.createOid("1.2.840.113554.1.2.1.4");
private static final String DEFAULT_HANDLER =
"auth.login.defaultCallbackHandler";

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,8 +55,7 @@ public class GSSNameElement implements GSSNameSpi {
static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {
if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType) ||
GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) {
if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
Oid[] supportedNTs = null;
try {
supportedNTs = stub.inquireNamesForMech();
@ -83,15 +82,9 @@ public class GSSNameElement implements GSSNameSpi {
if (supportedNTs[i].equals(nameType)) return nameType;
}
// Special handling the specified name type
if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
SunNativeProvider.debug("Override " + nameType +
" with mechanism default(null)");
return null; // Use mechanism specific default
} else {
SunNativeProvider.debug("Override " + nameType +
" with " + GSSUtil.NT_HOSTBASED_SERVICE2);
return GSSUtil.NT_HOSTBASED_SERVICE2;
}
SunNativeProvider.debug("Override " + nameType +
" with mechanism default(null)");
return null; // Use mechanism specific default
}
}
return nameType;

View File

@ -109,6 +109,7 @@ public class Config {
public static synchronized void refresh() throws KrbException {
singleton = new Config();
KeyTab.refresh();
KrbKdcReq.KdcAccessibility.reset();
}

View File

@ -511,6 +511,23 @@ public class EncryptionKey
return findKey(etype, null, keys);
}
/**
* Determines if a kvno matches another kvno. Used in the method
* findKey(type, kvno, keys). Always returns true if either input
* is null or zero, in case any side does not have kvno info available.
*
* Note: zero is included because N/A is not a legal value for kvno
* in javax.security.auth.kerberos.KerberosKey. Therefore, the info
* that the kvno is N/A might be lost when converting between this
* class and KerberosKey.
*/
private static boolean versionMatches(Integer v1, Integer v2) {
if (v1 == null || v1 == 0 || v2 == null || v2 == 0) {
return true;
}
return v1.equals(v2);
}
/**
* Find a key with given etype and kvno
* @param kvno if null, return any (first?) key
@ -525,15 +542,20 @@ public class EncryptionKey
}
int ktype;
boolean etypeFound = false;
for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getEType();
if (EType.isSupported(ktype)) {
Integer kv = keys[i].getKeyVersionNumber();
if (etype == ktype && (kvno == null || kvno.equals(kv))) {
return keys[i];
if (etype == ktype) {
etypeFound = true;
if (versionMatches(kvno, kv)) {
return keys[i];
}
}
}
}
// Key not found.
// allow DES key to be used for the DES etypes
if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
@ -543,12 +565,16 @@ public class EncryptionKey
if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
Integer kv = keys[i].getKeyVersionNumber();
if (kvno == null || kvno.equals(kv)) {
etypeFound = true;
if (versionMatches(kvno, kv)) {
return new EncryptionKey(etype, keys[i].getBytes());
}
}
}
}
if (etypeFound) {
throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
}
return null;
}
}

View File

@ -31,25 +31,26 @@
package sun.security.krb5;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.Locale;
import sun.security.krb5.internal.Krb5;
import sun.security.krb5.internal.UDPClient;
import sun.security.krb5.internal.TCPClient;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
public abstract class KrbKdcReq {
/**
* Default port for a KDC.
*/
private static final int DEFAULT_KDC_PORT = Krb5.KDC_INET_DEFAULT_PORT;
// Currently there is no option to specify retries
// in the kerberos configuration file
@ -66,7 +67,48 @@ public abstract class KrbKdcReq {
private static int udpPrefLimit = -1;
private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy";
/**
* What to do when a KDC is unavailable, specified in the
* java.security file with key krb5.kdc.bad.policy.
* Possible values can be TRY_LAST or TRY_LESS
*/
private enum BpType {
NONE, TRY_LAST, TRY_LESS
}
private static int tryLessMaxRetries = 1;
private static int tryLessTimeout = 5000;
private static final BpType badPolicy;
static {
String value = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(BAD_POLICY_KEY);
}
});
if (value != null) {
value = value.toLowerCase(Locale.ENGLISH);
String[] ss = value.split(":");
if ("tryless".equals(ss[0])) {
if (ss.length > 1) {
String[] params = ss[1].split(",");
tryLessMaxRetries = Integer.parseInt(params[0]);
if (params.length > 1) {
tryLessTimeout = Integer.parseInt(params[1]);
}
}
badPolicy = BpType.TRY_LESS;
} else if ("trylast".equals(ss[0])) {
badPolicy = BpType.TRY_LAST;
} else {
badPolicy = BpType.NONE;
}
} else {
badPolicy = BpType.NONE;
}
/*
* Get default timeout.
@ -131,22 +173,16 @@ public abstract class KrbKdcReq {
}
}
/*
* Get timeout.
*/
int timeout = getKdcTimeout(realm);
String kdcList = cfg.getKDCList(realm);
if (kdcList == null) {
throw new KrbException("Cannot get kdc for realm " + realm);
}
String tempKdc = null; // may include the port number also
StringTokenizer st = new StringTokenizer(kdcList);
while (st.hasMoreTokens()) {
tempKdc = st.nextToken();
for (String tmp: KdcAccessibility.list(kdcList)) {
tempKdc = tmp;
try {
send(realm,tempKdc,useTCP);
KdcAccessibility.removeBad(tempKdc);
break;
} catch (Exception e) {
if (DEBUG) {
@ -154,6 +190,7 @@ public abstract class KrbKdcReq {
tempKdc);
e.printStackTrace(System.out);
}
KdcAccessibility.addBad(tempKdc);
savedException = e;
}
}
@ -174,16 +211,21 @@ public abstract class KrbKdcReq {
if (obuf == null)
return;
PrivilegedActionException savedException = null;
int port = Krb5.KDC_INET_DEFAULT_PORT;
/*
* Get timeout.
*/
int port = Krb5.KDC_INET_DEFAULT_PORT;
int retries = DEFAULT_KDC_RETRY_LIMIT;
int timeout = getKdcTimeout(realm);
/*
* Get port number for this KDC.
*/
if (badPolicy == BpType.TRY_LESS &&
KdcAccessibility.isBad(tempKdc)) {
if (retries > tryLessMaxRetries) {
retries = tryLessMaxRetries; // less retries
}
if (timeout > tryLessTimeout) {
timeout = tryLessTimeout; // less time
}
}
String kdc = null;
String portStr = null;
@ -225,12 +267,12 @@ public abstract class KrbKdcReq {
+ port + ", timeout="
+ timeout
+ ", number of retries ="
+ DEFAULT_KDC_RETRY_LIMIT
+ retries
+ ", #bytes=" + obuf.length);
}
KdcCommunication kdcCommunication =
new KdcCommunication(kdc, port, useTCP, timeout, obuf);
new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf);
try {
ibuf = AccessController.doPrivileged(kdcCommunication);
if (DEBUG) {
@ -258,14 +300,16 @@ public abstract class KrbKdcReq {
private int port;
private boolean useTCP;
private int timeout;
private int retries;
private byte[] obuf;
public KdcCommunication(String kdc, int port, boolean useTCP,
int timeout, byte[] obuf) {
int timeout, int retries, byte[] obuf) {
this.kdc = kdc;
this.port = port;
this.useTCP = useTCP;
this.timeout = timeout;
this.retries = retries;
this.obuf = obuf;
}
@ -294,7 +338,7 @@ public abstract class KrbKdcReq {
} else {
// For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to
// get the response
for (int i=1; i <= DEFAULT_KDC_RETRY_LIMIT; i++) {
for (int i=1; i <= retries; i++) {
UDPClient kdcClient = new UDPClient(kdc, port, timeout);
if (DEBUG) {
@ -310,7 +354,7 @@ public abstract class KrbKdcReq {
* Send the data to the kdc.
*/
kdcClient.send(obuf);
kdcClient.send(obuf);
/*
* And get a response.
@ -323,7 +367,7 @@ public abstract class KrbKdcReq {
System.out.println ("SocketTimeOutException with " +
"attempt: " + i);
}
if (i == DEFAULT_KDC_RETRY_LIMIT) {
if (i == retries) {
ibuf = null;
throw se;
}
@ -385,4 +429,67 @@ public abstract class KrbKdcReq {
return -1;
}
/**
* Maintains a KDC accessible list. Unavailable KDCs are put into a
* blacklist, when a KDC in the blacklist is available, it's removed
* from there. No insertion order in the blacklist.
*
* There are two methods to deal with KDCs in the blacklist. 1. Only try
* them when there's no KDC not on the blacklist. 2. Still try them, but
* with lesser number of retries and smaller timeout value.
*/
static class KdcAccessibility {
// Known bad KDCs
private static Set<String> bads = new HashSet<String>();
private static synchronized void addBad(String kdc) {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: add " + kdc);
}
bads.add(kdc);
}
private static synchronized void removeBad(String kdc) {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: remove " + kdc);
}
bads.remove(kdc);
}
private static synchronized boolean isBad(String kdc) {
return bads.contains(kdc);
}
public static synchronized void reset() {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: reset");
}
bads.clear();
}
// Returns a preferred KDC list by putting the bad ones at the end
private static synchronized String[] list(String kdcList) {
StringTokenizer st = new StringTokenizer(kdcList);
List<String> list = new ArrayList<String>();
if (badPolicy == BpType.TRY_LAST) {
List<String> badkdcs = new ArrayList<String>();
while (st.hasMoreTokens()) {
String t = st.nextToken();
if (bads.contains(t)) badkdcs.add(t);
else list.add(t);
}
// Bad KDCs are put at last
list.addAll(badkdcs);
} else {
// All KDCs are returned in their original order,
// This include TRY_LESS and NONE
while (st.hasMoreTokens()) {
list.add(st.nextToken());
}
}
return list.toArray(new String[list.size()]);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,11 +50,12 @@ import sun.security.krb5.internal.EncTicketPart;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.jgss.krb5.Krb5Util;
import sun.security.krb5.KrbException;
import sun.security.krb5.internal.Krb5;
import sun.security.ssl.Debug;
import sun.security.ssl.HandshakeInStream;
import sun.security.ssl.HandshakeOutStream;
import sun.security.ssl.KerberosClientKeyExchange;
import sun.security.ssl.ProtocolVersion;
/**
@ -188,7 +189,14 @@ public final class KerberosClientKeyExchangeImpl
// See if we have the right key to decrypt the ticket to get
// the session key.
int encPartKeyType = encPart.getEType();
KerberosKey dkey = findKey(encPartKeyType, serverKeys);
Integer encPartKeyVersion = encPart.getKeyVersionNumber();
KerberosKey dkey = null;
try {
dkey = findKey(encPartKeyType, encPartKeyVersion, serverKeys);
} catch (KrbException ke) { // a kvno mismatch
throw new IOException(
"Cannot find key matching version number", ke);
}
if (dkey == null) {
// %%% Should print string repr of etype
throw new IOException(
@ -355,12 +363,34 @@ public final class KerberosClientKeyExchangeImpl
return localPrincipal;
}
private static KerberosKey findKey(int etype, KerberosKey[] keys) {
/**
* Determines if a kvno matches another kvno. Used in the method
* findKey(etype, version, keys). Always returns true if either input
* is null or zero, in case any side does not have kvno info available.
*
* Note: zero is included because N/A is not a legal value for kvno
* in javax.security.auth.kerberos.KerberosKey. Therefore, the info
* that the kvno is N/A might be lost when converting between
* EncryptionKey and KerberosKey.
*/
private static boolean versionMatches(Integer v1, int v2) {
if (v1 == null || v1 == 0 || v2 == 0) {
return true;
}
return v1.equals(v2);
}
private static KerberosKey findKey(int etype, Integer version,
KerberosKey[] keys) throws KrbException {
int ktype;
boolean etypeFound = false;
for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getKeyType();
if (etype == ktype) {
return keys[i];
etypeFound = true;
if (versionMatches(version, keys[i].getVersionNumber())) {
return keys[i];
}
}
}
// Key not found.
@ -370,14 +400,20 @@ public final class KerberosClientKeyExchangeImpl
for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getKeyType();
if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
return new KerberosKey(keys[i].getPrincipal(),
keys[i].getEncoded(),
etype,
keys[i].getVersionNumber());
ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
etypeFound = true;
if (versionMatches(version, keys[i].getVersionNumber())) {
return new KerberosKey(keys[i].getPrincipal(),
keys[i].getEncoded(),
etype,
keys[i].getVersionNumber());
}
}
}
}
if (etypeFound) {
throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
}
return null;
}
}

View File

@ -55,10 +55,10 @@ security.provider.9=sun.security.smartcardio.SunPCSC
#
# Select the source of seed data for SecureRandom. By default an
# attempt is made to use the entropy gathering device specified by
# attempt is made to use the entropy gathering device specified by
# the securerandom.source property. If an exception occurs when
# accessing the URL then the traditional system/thread activity
# algorithm is used.
# accessing the URL then the traditional system/thread activity
# algorithm is used.
#
# On Solaris and Linux systems, if file:/dev/urandom is specified and it
# exists, a special SecureRandom implementation is activated by default.
@ -72,7 +72,7 @@ securerandom.source=file:/dev/urandom
# The entropy gathering device is described as a URL and can also
# be specified with the system property "java.security.egd". For example,
# -Djava.security.egd=file:/dev/urandom
# Specifying this system property will override the securerandom.source
# Specifying this system property will override the securerandom.source
# setting.
#
@ -149,7 +149,7 @@ package.access=sun.,com.sun.imageio.
security.overridePropertiesFile=true
#
# Determines the default key and trust manager factory algorithms for
# Determines the default key and trust manager factory algorithms for
# the javax.net.ssl package.
#
ssl.KeyManagerFactory.algorithm=SunX509
@ -168,10 +168,10 @@ ssl.TrustManagerFactory.algorithm=PKIX
# is to cache for 30 seconds.
#
# NOTE: setting this to anything other than the default value can have
# serious security implications. Do not set it unless
# serious security implications. Do not set it unless
# you are sure you are not exposed to DNS spoofing attack.
#
#networkaddress.cache.ttl=-1
#networkaddress.cache.ttl=-1
# The Java-level namelookup cache policy for failed lookups:
#
@ -183,7 +183,7 @@ ssl.TrustManagerFactory.algorithm=PKIX
# the WINS name service in addition to DNS, name service lookups
# that fail may take a noticeably long time to return (approx. 5 seconds).
# For this reason the default caching policy is to maintain these
# results for 10 seconds.
# results for 10 seconds.
#
#
networkaddress.cache.negative.ttl=10
@ -192,7 +192,7 @@ networkaddress.cache.negative.ttl=10
# Properties to configure OCSP for certificate revocation checking
#
# Enable OCSP
# Enable OCSP
#
# By default, OCSP is not used for certificate revocation checking.
# This property enables the use of OCSP when set to the value "true".
@ -201,7 +201,7 @@ networkaddress.cache.negative.ttl=10
#
# Example,
# ocsp.enable=true
#
# Location of the OCSP responder
#
@ -213,15 +213,15 @@ networkaddress.cache.negative.ttl=10
#
# Example,
# ocsp.responderURL=http://ocsp.example.net:80
#
# Subject name of the OCSP responder's certificate
#
# By default, the certificate of the OCSP responder is that of the issuer
# of the certificate being validated. This property identifies the certificate
# of the OCSP responder when the default does not apply. Its value is a string
# distinguished name (defined in RFC 2253) which identifies a certificate in
# the set of certificates supplied during cert path validation. In cases where
# of the OCSP responder when the default does not apply. Its value is a string
# distinguished name (defined in RFC 2253) which identifies a certificate in
# the set of certificates supplied during cert path validation. In cases where
# the subject name alone is not sufficient to uniquely identify the certificate
# then both the "ocsp.responderCertIssuerName" and
# "ocsp.responderCertSerialNumber" properties must be used instead. When this
@ -237,14 +237,14 @@ networkaddress.cache.negative.ttl=10
# of the certificate being validated. This property identifies the certificate
# of the OCSP responder when the default does not apply. Its value is a string
# distinguished name (defined in RFC 2253) which identifies a certificate in
# the set of certificates supplied during cert path validation. When this
# property is set then the "ocsp.responderCertSerialNumber" property must also
# be set. When the "ocsp.responderCertSubjectName" property is set then this
# the set of certificates supplied during cert path validation. When this
# property is set then the "ocsp.responderCertSerialNumber" property must also
# be set. When the "ocsp.responderCertSubjectName" property is set then this
# property is ignored.
#
# Example,
# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
#
# Serial number of the OCSP responder's certificate
#
@ -259,4 +259,31 @@ networkaddress.cache.negative.ttl=10
#
# Example,
# ocsp.responderCertSerialNumber=2A:FF:00
#
# Policy for failed Kerberos KDC lookups:
#
# When a KDC is unavailable (network error, service failure, etc), it is
# put inside a blacklist and accessed less often for future requests. The
# value (case-insensitive) for this policy can be:
#
# tryLast
# KDCs in the blacklist are always tried after those not on the list.
#
# tryLess[:max_retries,timeout]
# KDCs in the blacklist are still tried by their order in the configuration,
# but with smaller max_retries and timeout values. max_retries and timeout
# are optional numerical parameters (default 1 and 5000, which means once
# and 5 seconds). Please notes that if any of the values defined here is
# more than what is defined in krb5.conf, it will be ignored.
#
# Whenever a KDC is detected as available, it is removed from the blacklist.
# The blacklist is reset when krb5.conf is reloaded. You can add
# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
# reloaded whenever a JAAS authentication is attempted.
#
# Example,
# krb5.kdc.bad.policy = tryLast
# krb5.kdc.bad.policy = tryLess:2,2000
krb5.kdc.bad.policy = tryLast

View File

@ -94,18 +94,6 @@ Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
return (jdouble) jcbrt((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_ceil(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jceil((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_floor(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jfloor((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
{

View File

@ -121,6 +121,9 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (newfd == -1) {
NET_ThrowSocketException(env, "Socket Closed");
if (bufP != BUF) {
free(bufP);
}
return -1;
}
}

View File

@ -291,7 +291,7 @@ TESTEXIT = \
fi ; \
testExitCode=`$(CAT) $(EXITCODE)`; \
$(ECHO) "EXIT CODE: $${testExitCode}"; \
exit ${testExitCode}
exit $${testExitCode}
BUNDLE_UP_AND_EXIT = \
( \
@ -300,7 +300,7 @@ BUNDLE_UP_AND_EXIT = \
$(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
$(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
if [ -r "$${_summary}" ] ; then \
$(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \
$(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \
$(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
$(EGREP) ' Passed\.' $(RUNLIST) \
| $(EGREP) -v ' Error\.' \
@ -370,7 +370,8 @@ ifndef USE_JTREG_SAMEVM
endif
# With samevm, you cannot use -javaoptions?
ifeq ($(USE_JTREG_SAMEVM),true)
EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
JTREG_SAMEVM_OPTION = -samevm
EXTRA_JTREG_OPTIONS += $(JTREG_SAMEVM_OPTION) $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%)
else
JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
@ -418,8 +419,9 @@ $(ECHO) "Running tests in othervm mode: $(call TestDirs, $?)"
$(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
endef
define SummaryInfo
$(ECHO) "Summary for: $?"
$(ECHO) "########################################################"
$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
$(ECHO) "########################################################"
endef
# ------------------------------------------------------------------
@ -446,10 +448,14 @@ JDK_ALL_TARGETS += jdk_beans2
jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
java/beans/PropertyEditor
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_beans3
jdk_beans3: java/beans/XMLEncoder
$(call RunOthervmBatch)
# All beans tests
jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3
@$(SummaryInfo)
@ -475,6 +481,7 @@ JDK_ALL_TARGETS += jdk_management2
jdk_management2: com/sun/jmx com/sun/management sun/management
$(call RunOthervmBatch)
# All management tests
jdk_management: jdk_management1 jdk_management2
@$(SummaryInfo)
@ -506,10 +513,14 @@ JDK_ALL_TARGETS += jdk_nio2
jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_nio3
jdk_nio3: com/sun/nio sun/nio
$(call RunOthervmBatch)
# All nio tests
jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
@$(SummaryInfo)
@ -529,10 +540,14 @@ jdk_security1: java/security
JDK_ALL_TARGETS += jdk_security2
jdk_security2: javax/crypto com/sun/crypto
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_security3
jdk_security3: com/sun/security lib/security javax/security sun/security
$(call RunOthervmBatch)
# All security tests
jdk_security: jdk_security1 jdk_security2 jdk_security3
@$(SummaryInfo)
@ -547,15 +562,18 @@ JDK_ALL_TARGETS += jdk_text
jdk_text: java/text sun/text
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_tools1
jdk_tools1: com/sun/jdi
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_tools2
jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
$(call RunOthervmBatch)
# All tools tests
jdk_tools: jdk_tools1 jdk_tools2
@$(SummaryInfo)
@ -567,7 +585,9 @@ jdk_util: java/util sun/util
# ------------------------------------------------------------------
# Run all tests
jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS))
FILTER_OUT_LIST=jdk_awt jdk_rmi jdk_swing
JDK_ALL_STABLE_TARGETS := $(filter-out $(FILTER_OUT_LIST), $(JDK_ALL_TARGETS))
jdk_all: $(JDK_ALL_STABLE_TARGETS)
@$(SummaryInfo)
# These are all phony targets
@ -581,16 +601,22 @@ JTREG = $(JT_HOME)/win32/bin/jtreg
JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
# Only run automatic tests
JTREG_BASIC_OPTIONS += -a
# Always turn on assertions
JTREG_ASSERT_OPTION = -ea -esa
JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
# Report details on all failed or error tests, times too
JTREG_BASIC_OPTIONS += -v:fail,error,time
# Retain all files for failing tests
JTREG_BASIC_OPTIONS += -retain:fail,error
# Ignore tests are not run and completely silent about it
JTREG_BASIC_OPTIONS += -ignore:quiet
# Multiple by 2 the timeout numbers
JTREG_BASIC_OPTIONS += -timeoutFactor:2
JTREG_IGNORE_OPTION = -ignore:quiet
JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
# Multiple by 4 the timeout numbers
JTREG_TIMEOUT_OPTION = -timeoutFactor:4
JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
# Boost the max memory for jtreg to avoid gc thrashing
JTREG_BASIC_OPTIONS += -J-Xmx512m
JTREG_MEMORY_OPTION = -J-Xmx512m
JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
# Make sure jtreg exists
$(JTREG): $(JT_HOME)

View File

@ -431,6 +431,11 @@ java/lang/ClassLoader/deadlock/TestCrossDelegate.sh generic-all
# jdk_management
# Fails on Windows 2000, Test failed for iiop java.lang.NullPointerException
# at org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(Unknown Source)
# at com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:653)
javax/management/remote/mandatory/connection/ReconnectTest.java generic-all
# Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke
javax/management/remote/mandatory/threads/ExecutorTest.java generic-all
@ -494,10 +499,6 @@ javax/management/monitor/AttributeArbitraryDataTypeTest.java generic-all
# Problems with rounding add failures on solaris-sparcv9 and -server
java/math/BigDecimal/AddTests.java solaris-sparcv9
# Problems on windows with samevm, missing inputstream close()?
# Also times out on solaris-sparcv9 -server
java/math/BigInteger/BigIntegerTest.java generic-all
# Should be samevm? But seems problematic with samevm on windows
java/math/BigInteger/ModPow65537.java generic-all
@ -581,6 +582,14 @@ javax/print/attribute/MediaMappingsTest.java generic-all
# Suspect many of these tests auffer from using fixed ports, no concrete
# evidence.
# Dies on Solaris 10 sparc and sparcv9, Linux -ea -esa with
# Interrupted or IO exception, maybe writing to non-unique named file?
com/sun/net/httpserver/bugs/B6373555.java generic-all
# Dies on pretty much all platforms when run with -ea -esa, Assertion error
java/net/CookieHandler/TestHttpCookie.java generic-all
java/net/URLClassLoader/closetest/CloseTest.java generic-all
# Fails on OpenSolaris, BindException unexpected
java/net/BindException/Test.java generic-all
@ -717,6 +726,9 @@ sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java generic-all
# Connection refused, windows samevm
sun/net/www/protocol/http/DigestTest.java generic-all
# Fails on Fedora 9 32bit & 64bit & Solaris 10, wrong proxy for http://localhost/index.html
java/net/ProxySelector/B6737819.java generic-all
############################################################################
# jdk_nio
@ -724,6 +736,33 @@ sun/net/www/protocol/http/DigestTest.java generic-all
# Suspect many of these tests auffer from using fixed ports, no concrete
# evidence.
# Fails with -ea -esa, Assertion error, but only on Solaris 10 machines?
com/sun/nio/sctp/SctpChannel/Send.java generic-all
com/sun/nio/sctp/SctpChannel/Shutdown.java generic-all
# Fails on Windows 2000, Can't delete test directory .\x.SetLastModified.dir
# at SetLastModified.main(SetLastModified.java:107)
java/io/File/SetLastModified.java generic-all
# Fails on Solaris 10 x64, address already in use
java/nio/channels/DatagramChannel/SRTest.java generic-all
# Fails on Solaris 10 x86, times out
java/nio/channels/DatagramChannel/Sender.java generic-all
# Fails on Fedora 9 x86, address in use
java/nio/channels/Selector/SelectWrite.java generic-all
# Fails on Fedora 9 32bit times out
java/nio/channels/DatagramChannel/EmptyBuffer.java generic-all
# Fails on Windows 2000, ExceptionInInitializerError
# in WindowsAsynchronousServerSocketChannelImpl.java:316
java/nio/channels/AsynchronousChannelGroup/Unbounded.java generic-all
# Fails on Windows 2000, times out
java/nio/channels/FileChannel/Transfer.java generic-all
# Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses
# from a channel that is bound to the wildcard address
com/sun/nio/sctp/SctpChannel/Bind.java generic-all
@ -893,6 +932,48 @@ java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java generic-all
# jdk_security
# Fails with -ea -esa, but only on Solaris sparc? Suspect it is timing out
sun/security/tools/keytool/standard.sh generic-all
# Fails on Solaris 10 X64, address already in use
sun/security/krb5/auto/HttpNegotiateServer.java generic-all
# Fails on almost all platforms
# java.lang.UnsupportedClassVersionError: SerialTest :
# Unsupported major.minor version 51.0
# at java.lang.ClassLoader.defineClass1(Native Method)
sun/security/util/Oid/S11N.sh generic-all
# Fails on Fedora 9 32bit
# GSSException: Failure unspecified at GSS-API level (Mechanism level:
# Invalid argument (400) - Cannot find key of appropriate type to decrypt
# AP REP - DES CBC mode with MD5)
# at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:778)
sun/security/krb5/auto/NonMutualSpnego.java generic-all
# Fails on Solaris 10 sparc, GSSException: Failure unspecified at GSS-API level
# Also fails on Windows 2000 similar way
sun/security/krb5/auto/ok-as-delegate.sh generic-all
# Fails on Windows 2000, GSSException: Failure unspecified at GSS-API level
# (Mechanism level: Request is a replay (34))
sun/security/krb5/auto/ok-as-delegate-xrealm.sh generic-all
# Fails on Windows 2000, ExceptionInInitializerError
sun/security/mscapi/AccessKeyStore.sh generic-all
# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
sun/security/pkcs11/KeyAgreement/TestDH.java generic-all
# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
sun/security/pkcs11/fips/ClientJSSEServerJSSE.java generic-all
# Fails on Solaris 10, KrbException: Additional pre-authentication required (25)
sun/security/krb5/auto/basic.sh generic-all
# Fails on Fedora 9 64bit, PKCS11Exception: CKR_DEVICE_ERROR
sun/security/pkcs11/KeyAgreement/TestDH.java generic-all
# Run too slow on Solaris 10 sparc
sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc
sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc
@ -1088,6 +1169,16 @@ java/text/Bidi/Bug6665028.java linux-x64
# So most if not all tools tests are now being run with "othervm" mode.
# Some of these tools tests have a tendency to use fixed ports, bad idea.
# Fails with -ea -esa on Solaris, Assertion error (Solaris specific test)
com/sun/tracing/BasicFunctionality.java generic-all
# Fails on Fedora 9 32bit, jps output differs problem
sun/tools/jstatd/jstatdDefaults.sh generic-all
# Fails on Linux Fedora 9 32bit, Could not read data for remote JVM 16133
# jstat output differs from expected output
sun/tools/jstatd/jstatdExternalRegistry.sh generic-all
# Output of jps differs from expected output.
# Invalid argument count on solaris-sparc and x64
sun/tools/jstatd/jstatdPort.sh generic-all
@ -1099,6 +1190,11 @@ sun/tools/jps/jps-lm.sh generic-all
sun/tools/jps/jps-Vvml_2.sh generic-all
sun/tools/jps/jps-m_2.sh generic-all
# Fails on Solaris 10 sparcv9, shell exits with 1
# Turning off use of shared archive because of choice of garbage collector or large pages
# Could not synchronize with target
sun/tools/jps/jps-v_1.sh generic-all
# Fails on OpenSolaris "Could not synchronize with target"
sun/tools/jps/jps-Defaults.sh generic-all
sun/tools/jps/jps-V_2.sh generic-all
@ -1160,6 +1256,12 @@ tools/jar/index/MetaInf.java windows-all
# jdk_util
# Fails with -ea -esa on all platforms with Assertion error
java/util/ResourceBundle/Test4300693.java generic-all
# Failing on all -client 32bit platforms starting with b77? See 6908348.
java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all
# Assert error, failures, on Linux Fedora 9 -server
# Windows samevm failure, assert error "Passed = 134, failed = 2"
java/util/Arrays/ArrayObjectMethods.java generic-all

View File

@ -31,6 +31,9 @@
* @build VMConnection
* @run main/othervm NoLaunchOptionTest
*/
import java.net.ServerSocket;
public class NoLaunchOptionTest extends Object {
private Process subprocess;
private int subprocessStatus;
@ -121,12 +124,19 @@ public class NoLaunchOptionTest extends Object {
}
public static void main(String[] args) throws Exception {
// find a free port
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
ss.close();
String address = String.valueOf(port);
String javaExe = System.getProperty("java.home") +
java.io.File.separator + "bin" +
java.io.File.separator + "java";
String targetClass = "NotAClass";
String cmds [] = {javaExe,
"-agentlib:jdwp=transport=dt_socket,address=8000," +
"-agentlib:jdwp=transport=dt_socket,address=" +
address + "," +
"onthrow=java.lang.ClassNotFoundException,suspend=n",
targetClass};
NoLaunchOptionTest myTest = new NoLaunchOptionTest();

View File

@ -32,6 +32,9 @@
* @run compile -g VMConnection.java
* @run main/othervm OptionTest
*/
import java.net.ServerSocket;
public class OptionTest extends Object {
private Process subprocess;
private int subprocessStatus;
@ -122,12 +125,18 @@ public class OptionTest extends Object {
}
public static void main(String[] args) throws Exception {
// find a free port
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
ss.close();
String address = String.valueOf(port);
String javaExe = System.getProperty("java.home") +
java.io.File.separator + "bin" +
java.io.File.separator + "java";
String targetClass = "HelloWorld";
String baseOptions = "transport=dt_socket" +
",address=8000" +
",address=" + address +
",server=y" +
",suspend=n";

View File

@ -0,0 +1,201 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6908131
* @summary Check for correct implementation of Math.ceil and Math.floor
*/
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;
public class CeilAndFloorTests {
private static int testCeilCase(double input, double expected) {
int failures = 0;
failures += Tests.test("Math.ceil", input, Math.ceil(input), expected);
failures += Tests.test("StrictMath.ceil", input, StrictMath.ceil(input), expected);
return failures;
}
private static int testFloorCase(double input, double expected) {
int failures = 0;
failures += Tests.test("Math.floor", input, Math.floor(input), expected);
failures += Tests.test("StrictMath.floor", input, StrictMath.floor(input), expected);
return failures;
}
private static int nearIntegerTests() {
int failures = 0;
double [] fixedPoints = {
-0.0,
0.0,
-1.0,
1.0,
-0x1.0p52,
0x1.0p52,
-Double.MAX_VALUE,
Double.MAX_VALUE,
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.NaN,
};
for(double fixedPoint : fixedPoints) {
failures += testCeilCase(fixedPoint, fixedPoint);
failures += testFloorCase(fixedPoint, fixedPoint);
}
for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
double powerOfTwo = Math.scalb(1.0, i);
double neighborDown = FpUtils.nextDown(powerOfTwo);
double neighborUp = Math.nextUp(powerOfTwo);
if (i < 0) {
failures += testCeilCase( powerOfTwo, 1.0);
failures += testCeilCase(-powerOfTwo, -0.0);
failures += testFloorCase( powerOfTwo, 0.0);
failures += testFloorCase(-powerOfTwo, -1.0);
failures += testCeilCase( neighborDown, 1.0);
failures += testCeilCase(-neighborDown, -0.0);
failures += testFloorCase( neighborUp, 0.0);
failures += testFloorCase(-neighborUp, -1.0);
} else {
failures += testCeilCase(powerOfTwo, powerOfTwo);
failures += testFloorCase(powerOfTwo, powerOfTwo);
if (neighborDown==Math.rint(neighborDown)) {
failures += testCeilCase( neighborDown, neighborDown);
failures += testCeilCase(-neighborDown, -neighborDown);
failures += testFloorCase( neighborDown, neighborDown);
failures += testFloorCase(-neighborDown,-neighborDown);
} else {
failures += testCeilCase( neighborDown, powerOfTwo);
failures += testFloorCase(-neighborDown, -powerOfTwo);
}
if (neighborUp==Math.rint(neighborUp)) {
failures += testCeilCase(neighborUp, neighborUp);
failures += testCeilCase(-neighborUp, -neighborUp);
failures += testFloorCase(neighborUp, neighborUp);
failures += testFloorCase(-neighborUp, -neighborUp);
} else {
failures += testFloorCase(neighborUp, powerOfTwo);
failures += testCeilCase(-neighborUp, -powerOfTwo);
}
}
}
for(int i = -(0x10000); i <= 0x10000; i++) {
double d = (double) i;
double neighborDown = FpUtils.nextDown(d);
double neighborUp = Math.nextUp(d);
failures += testCeilCase( d, d);
failures += testCeilCase(-d, -d);
failures += testFloorCase( d, d);
failures += testFloorCase(-d, -d);
if (Math.abs(d) > 1.0) {
failures += testCeilCase( neighborDown, d);
failures += testCeilCase(-neighborDown, -d+1);
failures += testFloorCase( neighborUp, d);
failures += testFloorCase(-neighborUp, -d-1);
}
}
return failures;
}
public static int roundingTests() {
int failures = 0;
double [][] testCases = {
{ Double.MIN_VALUE, 1.0},
{-Double.MIN_VALUE, -0.0},
{ FpUtils.nextDown(DoubleConsts.MIN_NORMAL), 1.0},
{-FpUtils.nextDown(DoubleConsts.MIN_NORMAL), -0.0},
{ DoubleConsts.MIN_NORMAL, 1.0},
{-DoubleConsts.MIN_NORMAL, -0.0},
{ 0.1, 1.0},
{-0.1, -0.0},
{ 0.5, 1.0},
{-0.5, -0.0},
{ 1.5, 2.0},
{-1.5, -1.0},
{ 2.5, 3.0},
{-2.5, -2.0},
{ FpUtils.nextDown(1.0), 1.0},
{ FpUtils.nextDown(-1.0), -1.0},
{ Math.nextUp(1.0), 2.0},
{ Math.nextUp(-1.0), -0.0},
{ 0x1.0p51, 0x1.0p51},
{-0x1.0p51, -0x1.0p51},
{ FpUtils.nextDown(0x1.0p51), 0x1.0p51},
{-Math.nextUp(0x1.0p51), -0x1.0p51},
{ Math.nextUp(0x1.0p51), 0x1.0p51+1},
{-FpUtils.nextDown(0x1.0p51), -0x1.0p51+1},
{ FpUtils.nextDown(0x1.0p52), 0x1.0p52},
{-Math.nextUp(0x1.0p52), -0x1.0p52-1.0},
{ Math.nextUp(0x1.0p52), 0x1.0p52+1.0},
{-FpUtils.nextDown(0x1.0p52), -0x1.0p52+1.0},
};
for(double[] testCase : testCases) {
failures += testCeilCase(testCase[0], testCase[1]);
failures += testFloorCase(-testCase[0], -testCase[1]);
}
return failures;
}
public static void main(String... args) {
int failures = 0;
failures += nearIntegerTests();
failures += roundingTests();
if (failures > 0) {
System.err.println("Testing {Math, StrictMath}.ceil incurred "
+ failures + " failures.");
throw new RuntimeException();
}
}
}

View File

@ -642,37 +642,71 @@ public class BigIntegerTest {
for(int i = 0; i < bitPatterns.length; i++) {
BigInteger b1 = new BigInteger(bitPatterns[i], 16);
BigInteger b2 = null;
File f = new File("serialtest");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(b1);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
BigInteger b2 = (BigInteger)ois.readObject();
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
try {
oos.writeObject(b1);
oos.flush();
} finally {
oos.close();
}
if (!b1.equals(b2) ||
!b1.equals(b1.or(b2))) {
failCount++;
System.err.println("Serialized failed for hex " +
b1.toString(16));
FileInputStream fis = new FileInputStream(f);
try {
ObjectInputStream ois = new ObjectInputStream(fis);
try {
b2 = (BigInteger)ois.readObject();
} finally {
ois.close();
}
} finally {
fis.close();
}
if (!b1.equals(b2) ||
!b1.equals(b1.or(b2))) {
failCount++;
System.err.println("Serialized failed for hex " +
b1.toString(16));
}
} finally {
fos.close();
}
f.delete();
}
for(int i=0; i<10; i++) {
BigInteger b1 = fetchNumber(rnd.nextInt(100));
BigInteger b2 = null;
File f = new File("serialtest");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(b1);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
BigInteger b2 = (BigInteger)ois.readObject();
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
try {
oos.writeObject(b1);
oos.flush();
} finally {
oos.close();
}
FileInputStream fis = new FileInputStream(f);
try {
ObjectInputStream ois = new ObjectInputStream(fis);
try {
b2 = (BigInteger)ois.readObject();
} finally {
ois.close();
}
} finally {
fis.close();
}
} finally {
fos.close();
}
if (!b1.equals(b2) ||
!b1.equals(b1.or(b2)))

View File

@ -38,6 +38,26 @@ public class Basic$Type$
extends Basic
{
private static final $type$[] VALUES = {
$Fulltype$.MIN_VALUE,
($type$) -1,
($type$) 0,
($type$) 1,
$Fulltype$.MAX_VALUE,
#if[float]
$Fulltype$.NEGATIVE_INFINITY,
$Fulltype$.POSITIVE_INFINITY,
$Fulltype$.NaN,
($type$) -0.0,
#end[float]
#if[double]
$Fulltype$.NEGATIVE_INFINITY,
$Fulltype$.POSITIVE_INFINITY,
$Fulltype$.NaN,
($type$) -0.0,
#end[double]
};
private static void relGet($Type$Buffer b) {
int n = b.capacity();
$type$ v;
@ -309,6 +329,12 @@ public class Basic$Type$
#end[byte]
private static void fail(String problem,
$Type$Buffer xb, $Type$Buffer yb,
$type$ x, $type$ y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
try {
@ -522,6 +548,42 @@ public class Basic$Type$
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for ($type$ x : VALUES) {
$Type$Buffer xb = $Type$Buffer.wrap(new $type$[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for ($type$ y : VALUES) {
$Type$Buffer yb = $Type$Buffer.wrap(new $type$[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != $Fulltype$.compare(x, y)) {
#if[float]
if (x == 0.0 && y == 0.0) continue;
#end[float]
#if[double]
if (x == 0.0 && y == 0.0) continue;
#end[double]
fail("Incorrect results for $Type$Buffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for $Type$Buffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicByte
extends Basic
{
private static final byte[] VALUES = {
Byte.MIN_VALUE,
(byte) -1,
(byte) 0,
(byte) 1,
Byte.MAX_VALUE,
};
private static void relGet(ByteBuffer b) {
int n = b.capacity();
byte v;
@ -309,6 +329,12 @@ public class BasicByte
private static void fail(String problem,
ByteBuffer xb, ByteBuffer yb,
byte x, byte y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
try {
@ -522,6 +548,42 @@ public class BasicByte
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (byte x : VALUES) {
ByteBuffer xb = ByteBuffer.wrap(new byte[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (byte y : VALUES) {
ByteBuffer yb = ByteBuffer.wrap(new byte[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Byte.compare(x, y)) {
fail("Incorrect results for ByteBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for ByteBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicChar
extends Basic
{
private static final char[] VALUES = {
Character.MIN_VALUE,
(char) -1,
(char) 0,
(char) 1,
Character.MAX_VALUE,
};
private static void relGet(CharBuffer b) {
int n = b.capacity();
char v;
@ -308,6 +328,12 @@ public class BasicChar
private static void fail(String problem,
CharBuffer xb, CharBuffer yb,
char x, char y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicChar
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (char x : VALUES) {
CharBuffer xb = CharBuffer.wrap(new char[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (char y : VALUES) {
CharBuffer yb = CharBuffer.wrap(new char[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Character.compare(x, y)) {
fail("Incorrect results for CharBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for CharBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicDouble
extends Basic
{
private static final double[] VALUES = {
Double.MIN_VALUE,
(double) -1,
(double) 0,
(double) 1,
Double.MAX_VALUE,
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.NaN,
(double) -0.0,
};
private static void relGet(DoubleBuffer b) {
int n = b.capacity();
double v;
@ -308,6 +328,12 @@ public class BasicDouble
private static void fail(String problem,
DoubleBuffer xb, DoubleBuffer yb,
double x, double y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicDouble
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (double x : VALUES) {
DoubleBuffer xb = DoubleBuffer.wrap(new double[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (double y : VALUES) {
DoubleBuffer yb = DoubleBuffer.wrap(new double[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Double.compare(x, y)) {
if (x == 0.0 && y == 0.0) continue;
fail("Incorrect results for DoubleBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for DoubleBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicFloat
extends Basic
{
private static final float[] VALUES = {
Float.MIN_VALUE,
(float) -1,
(float) 0,
(float) 1,
Float.MAX_VALUE,
Float.NEGATIVE_INFINITY,
Float.POSITIVE_INFINITY,
Float.NaN,
(float) -0.0,
};
private static void relGet(FloatBuffer b) {
int n = b.capacity();
float v;
@ -308,6 +328,12 @@ public class BasicFloat
private static void fail(String problem,
FloatBuffer xb, FloatBuffer yb,
float x, float y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicFloat
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (float x : VALUES) {
FloatBuffer xb = FloatBuffer.wrap(new float[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (float y : VALUES) {
FloatBuffer yb = FloatBuffer.wrap(new float[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Float.compare(x, y)) {
if (x == 0.0 && y == 0.0) continue;
fail("Incorrect results for FloatBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for FloatBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicInt
extends Basic
{
private static final int[] VALUES = {
Integer.MIN_VALUE,
(int) -1,
(int) 0,
(int) 1,
Integer.MAX_VALUE,
};
private static void relGet(IntBuffer b) {
int n = b.capacity();
int v;
@ -308,6 +328,12 @@ public class BasicInt
private static void fail(String problem,
IntBuffer xb, IntBuffer yb,
int x, int y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicInt
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (int x : VALUES) {
IntBuffer xb = IntBuffer.wrap(new int[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (int y : VALUES) {
IntBuffer yb = IntBuffer.wrap(new int[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Integer.compare(x, y)) {
fail("Incorrect results for IntBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for IntBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicLong
extends Basic
{
private static final long[] VALUES = {
Long.MIN_VALUE,
(long) -1,
(long) 0,
(long) 1,
Long.MAX_VALUE,
};
private static void relGet(LongBuffer b) {
int n = b.capacity();
long v;
@ -308,6 +328,12 @@ public class BasicLong
private static void fail(String problem,
LongBuffer xb, LongBuffer yb,
long x, long y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicLong
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (long x : VALUES) {
LongBuffer xb = LongBuffer.wrap(new long[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (long y : VALUES) {
LongBuffer yb = LongBuffer.wrap(new long[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Long.compare(x, y)) {
fail("Incorrect results for LongBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for LongBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -38,6 +38,26 @@ public class BasicShort
extends Basic
{
private static final short[] VALUES = {
Short.MIN_VALUE,
(short) -1,
(short) 0,
(short) 1,
Short.MAX_VALUE,
};
private static void relGet(ShortBuffer b) {
int n = b.capacity();
short v;
@ -308,6 +328,12 @@ public class BasicShort
private static void fail(String problem,
ShortBuffer xb, ShortBuffer yb,
short x, short y) {
fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
}
private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
boolean caught = false;
@ -522,6 +548,42 @@ public class BasicShort
if (b.compareTo(b2) <= 0)
fail("Comparison to lesser buffer <= 0", b, b2);
// Check equals and compareTo with interesting values
for (short x : VALUES) {
ShortBuffer xb = ShortBuffer.wrap(new short[] { x });
if (xb.compareTo(xb) != 0) {
fail("compareTo not reflexive", xb, xb, x, x);
}
if (! xb.equals(xb)) {
fail("equals not reflexive", xb, xb, x, x);
}
for (short y : VALUES) {
ShortBuffer yb = ShortBuffer.wrap(new short[] { y });
if (xb.compareTo(yb) != - yb.compareTo(xb)) {
fail("compareTo not anti-symmetric",
xb, yb, x, y);
}
if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
fail("compareTo inconsistent with equals",
xb, yb, x, y);
}
if (xb.compareTo(yb) != Short.compare(x, y)) {
fail("Incorrect results for ShortBuffer.compareTo",
xb, yb, x, y);
}
if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
fail("Incorrect results for ShortBuffer.equals",
xb, yb, x, y);
}
}
}
// Sub, dup
relPut(b);

View File

@ -36,5 +36,3 @@ gen int Int Integer
gen long Long Long
gen float Float Float
gen double Double Double
rm -rf build

View File

@ -146,13 +146,13 @@ public class CancelledProducerConsumerLoops {
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
/* TODO: unbounded queue implementations are prone to OOME
oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
oneRun(new LTQasSQ<Integer>(), pairs, iters);
oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
/* PriorityBlockingQueue is unbounded
oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
*/
}

View File

@ -26,6 +26,7 @@
* @bug 4624534
* @summary Make sure jar certificates work for Turkish locale
* @author kladko
* @run main/othervm TurkCert
*/
import java.util.*;

View File

@ -23,7 +23,7 @@
/**
* @test
* @bug 4635230 6283345 6303830 6824440
* @bug 4635230 6283345 6303830 6824440 6867348
* @summary Basic unit tests for generating XML Signatures with JSR 105
* @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
* X509KeySelector.java GenerationTests.java
@ -126,13 +126,14 @@ public class GenerationTests {
test_create_signature_x509_is();
test_create_signature_x509_ski();
test_create_signature_x509_sn();
// test_create_signature();
test_create_signature();
test_create_exc_signature();
test_create_sign_spec();
test_create_signature_enveloping_sha256_dsa();
test_create_signature_enveloping_sha384_rsa_sha256();
test_create_signature_enveloping_sha512_rsa_sha384();
test_create_signature_enveloping_sha512_rsa_sha512();
test_create_signature_reference_dependency();
}
private static void setup() throws Exception {
@ -410,6 +411,55 @@ public class GenerationTests {
System.out.println();
}
static void test_create_signature_reference_dependency() throws Exception {
System.out.println("* Generating signature-reference-dependency.xml");
// create references
List<Reference> refs = Collections.singletonList
(fac.newReference("#object-1", sha1));
// create SignedInfo
SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs);
// create objects
List<XMLStructure> objs = new ArrayList<XMLStructure>();
// Object 1
List<Reference> manRefs = Collections.singletonList
(fac.newReference("#object-2", sha1));
objs.add(fac.newXMLObject(Collections.singletonList
(fac.newManifest(manRefs, "manifest-1")), "object-1", null, null));
// Object 2
Document doc = db.newDocument();
Element nc = doc.createElementNS(null, "NonCommentandus");
nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
nc.appendChild(doc.createComment(" Commentandum "));
objs.add(fac.newXMLObject(Collections.singletonList
(new DOMStructure(nc)), "object-2", null, null));
// create XMLSignature
XMLSignature sig = fac.newXMLSignature(si, rsa, objs, "signature", null);
DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc);
sig.sign(dsc);
// dumpDocument(doc, new PrintWriter(System.out));
DOMValidateContext dvc = new DOMValidateContext
(kvks, doc.getDocumentElement());
XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
if (sig.equals(sig2) == false) {
throw new Exception
("Unmarshalled signature is not equal to generated signature");
}
if (sig2.validate(dvc) == false) {
throw new Exception("Validation of generated signature failed");
}
System.out.println();
}
static void test_create_signature() throws Exception {
System.out.println("* Generating signature.xml");
@ -645,6 +695,7 @@ public class GenerationTests {
envDoc.getElementsByTagName("YoursSincerely").item(0);
DOMSignContext dsc = new DOMSignContext(signingKey, ys);
dsc.setURIDereferencer(httpUd);
sig.sign(dsc);
@ -660,6 +711,7 @@ public class GenerationTests {
DOMValidateContext dvc = new DOMValidateContext
(new X509KeySelector(ks), sigElement);
dvc.setURIDereferencer(httpUd);
File f = new File(
System.getProperty("dir.test.vector.baltimore") +
System.getProperty("file.separator") +

View File

@ -0,0 +1,113 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.security.krb5.Config;
public class BadKdc {
// Matches the krb5 debug output:
// >>> KDCCommunication: kdc=kdc.rabbit.hole UDP:14319, timeout=2000,...
// ^ kdc# ^ timeout
static final Pattern re = Pattern.compile(
">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " +
"timeout=(\\d)000,");
public static void go(int[]... expected)
throws Exception {
System.setProperty("sun.security.krb5.debug", "true");
// Make sure KDCs' ports starts with 1 and 2 and 3,
// useful for checking debug output.
int p1 = 10000 + new java.util.Random().nextInt(10000);
int p2 = 20000 + new java.util.Random().nextInt(10000);
int p3 = 30000 + new java.util.Random().nextInt(10000);
FileWriter fw = new FileWriter("alternative-krb5.conf");
fw.write("[libdefaults]\n" +
"default_realm = " + OneKDC.REALM + "\n" +
"kdc_timeout = 2000\n");
fw.write("[realms]\n" + OneKDC.REALM + " = {\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" +
"}\n");
fw.close();
System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
Config.refresh();
// Turn on k3 only
KDC k3 = on(p3);
test(expected[0]);
test(expected[1]);
Config.refresh();
test(expected[2]);
k3.terminate(); // shutdown k3
on(p2); // k2 is on
test(expected[3]);
on(p1); // k1 and k2 is on
test(expected[4]);
}
private static KDC on(int p) throws Exception {
KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true);
k.addPrincipal(OneKDC.USER, OneKDC.PASS);
k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
return k;
}
/**
* One round of test for max_retries and timeout.
* @param timeout the expected timeout
* @param expected the expected kdc# timeout kdc# timeout...
*/
private static void test(int... expected) throws Exception {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
PrintStream oldout = System.out;
System.setOut(new PrintStream(bo));
Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
System.setOut(oldout);
String[] lines = new String(bo.toByteArray()).split("\n");
System.out.println("----------------- TEST -----------------");
int count = 0;
for (String line: lines) {
Matcher m = re.matcher(line);
if (m.find()) {
System.out.println(line);
if (Integer.parseInt(m.group(1)) != expected[count++] ||
Integer.parseInt(m.group(2)) != expected[count++]) {
throw new Exception("Fail here");
}
}
}
if (count != expected.length) {
throw new Exception("Less rounds");
}
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6843127
* @run main/timeout=300 BadKdc1
* @summary krb5 should not try to access unavailable kdc too often
*/
import java.io.*;
import java.security.Security;
public class BadKdc1 {
public static void main(String[] args)
throws Exception {
Security.setProperty("krb5.kdc.bad.policy", "tryLess");
BadKdc.go(
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
// The above line means try kdc1 for 2 seconds, then kdc1
// for 2 seconds,..., finally kdc3 for 2 seconds.
new int[]{1,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
// refresh
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
// k3 off, k2 on
new int[]{1,2,2,2,1,2,2,2}, // 1
// k1 on
new int[]{1,2,1,2} // empty
);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6843127
* @run main/timeout=300 BadKdc2
* @summary krb5 should not try to access unavailable kdc too often
*/
import java.io.*;
import java.security.Security;
public class BadKdc2 {
public static void main(String[] args)
throws Exception {
Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000");
BadKdc.go(
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
new int[]{1,1,1,1,2,1,2,1,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
// refresh
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
// k3 off, k2 on
new int[]{1,1,1,1,2,1,1,1,1,1,2,2}, // 1
// k1 on
new int[]{1,1,1,2} // empty
);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6843127
* @run main/timeout=300 BadKdc3
* @summary krb5 should not try to access unavailable kdc too often
*/
import java.io.*;
import java.security.Security;
public class BadKdc3 {
public static void main(String[] args)
throws Exception {
Security.setProperty("krb5.kdc.bad.policy", "tryLast");
BadKdc.go(
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
new int[]{3,2,3,2}, // 1, 2
// refresh
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
// k3 off, k2 on
new int[]{3,2,3,2,3,2,1,2,1,2,1,2,2,2,2,2}, // 1, 3
// k1 on
new int[]{2,2,2,2} // 1, 3
);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6843127
* @run main/timeout=300 BadKdc4
* @summary krb5 should not try to access unavailable kdc too often
*/
import java.io.*;
import java.security.Security;
public class BadKdc4 {
public static void main(String[] args)
throws Exception {
Security.setProperty("krb5.kdc.bad.policy", "");
BadKdc.go(
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
// refresh
new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
// k3 off, k2 on
new int[]{1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2},
// k1 on
new int[]{1,2,1,2}
);
}
}

View File

@ -141,6 +141,10 @@ public class KDC {
// Options
private Map<Option,Object> options = new HashMap<Option,Object>();
private Thread thread1, thread2, thread3;
DatagramSocket u1 = null;
ServerSocket t1 = null;
/**
* Option names, to be expanded forever.
*/
@ -480,8 +484,9 @@ public class KDC {
Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE);
stringToKey.setAccessible(true);
Integer kvno = null;
// For service whose password ending with a number, use it as kvno
if (p.toString().indexOf('/') >= 0) {
// For service whose password ending with a number, use it as kvno.
// Kvno must be postive.
if (p.toString().indexOf('/') > 0) {
char[] pass = getPassword(p, server);
if (Character.isDigit(pass[pass.length-1])) {
kvno = pass[pass.length-1] - '0';
@ -940,8 +945,6 @@ public class KDC {
* @throws java.io.IOException for any communication error
*/
protected void startServer(int port, boolean asDaemon) throws IOException {
DatagramSocket u1 = null;
ServerSocket t1 = null;
if (port > 0) {
u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
t1 = new ServerSocket(port);
@ -966,7 +969,7 @@ public class KDC {
this.port = port;
// The UDP consumer
Thread thread = new Thread() {
thread1 = new Thread() {
public void run() {
while (true) {
try {
@ -982,11 +985,11 @@ public class KDC {
}
}
};
thread.setDaemon(asDaemon);
thread.start();
thread1.setDaemon(asDaemon);
thread1.start();
// The TCP consumer
thread = new Thread() {
thread2 = new Thread() {
public void run() {
while (true) {
try {
@ -1004,11 +1007,11 @@ public class KDC {
}
}
};
thread.setDaemon(asDaemon);
thread.start();
thread2.setDaemon(asDaemon);
thread2.start();
// The dispatcher
thread = new Thread() {
thread3 = new Thread() {
public void run() {
while (true) {
try {
@ -1018,10 +1021,21 @@ public class KDC {
}
}
};
thread.setDaemon(true);
thread.start();
thread3.setDaemon(true);
thread3.start();
}
public void terminate() {
try {
thread1.stop();
thread2.stop();
thread3.stop();
u1.close();
t1.close();
} catch (Exception e) {
// OK
}
}
/**
* Helper class to encapsulate a job in a KDC.
*/

View File

@ -24,15 +24,20 @@
/*
* @test
* @bug 6893158
* @bug 6907425
* @summary AP_REQ check should use key version number
*/
import org.ietf.jgss.GSSException;
import sun.security.jgss.GSSUtil;
import sun.security.krb5.KrbException;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.internal.ktab.KeyTab;
import sun.security.krb5.internal.Krb5;
public class MoreKvno {
static PrincipalName p;
public static void main(String[] args)
throws Exception {
@ -41,21 +46,40 @@ public class MoreKvno {
// Rewrite keytab, 3 set of keys with different kvno
KeyTab ktab = KeyTab.create(OneKDC.KTAB);
PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
ktab.addEntry(p, "pass0".toCharArray(), 0);
ktab.addEntry(p, "pass2".toCharArray(), 2);
p = new PrincipalName(
OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
ktab.addEntry(p, "pass1".toCharArray(), 1);
ktab.addEntry(p, "pass3".toCharArray(), 3);
ktab.addEntry(p, "pass2".toCharArray(), 2);
ktab.save();
kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray());
go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept");
kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray());
char[] pass = "pass2".toCharArray();
kdc.addPrincipal(OneKDC.SERVER, pass);
go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
pass = "pass3".toCharArray();
kdc.addPrincipal(OneKDC.SERVER, pass);
// "server" initiate also, check pass2 is used at authentication
go(OneKDC.SERVER, "server");
go(OneKDC.SERVER, "server", pass);
try {
pass = "pass4".toCharArray();
kdc.addPrincipal(OneKDC.SERVER, pass);
go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
throw new Exception("This test should fail");
} catch (GSSException gsse) {
KrbException ke = (KrbException)gsse.getCause();
if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) {
throw new Exception("Not expected failure code: " +
ke.returnCode());
}
}
}
static void go(String server, String entry) throws Exception {
static void go(String server, String entry, char[] pass) throws Exception {
Context c, s;
// Part 1: Test keytab
c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
s = Context.fromJAAS(entry);
@ -66,5 +90,17 @@ public class MoreKvno {
s.dispose();
c.dispose();
// Part 2: Test username/password pair
c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
s = Context.fromUserPass(p.getNameString(), pass, true);
c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
Context.handshake(c, s);
s.dispose();
c.dispose();
}
}

View File

@ -24,8 +24,6 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Security;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/*
* @test
* @bug 6894643
* @bug 6894643 6913636
* @summary Test JSSE Kerberos ciphersuite
*/
import java.io.*;
@ -32,12 +32,13 @@ import javax.net.ssl.*;
import java.security.Principal;
import java.util.Date;
import sun.security.jgss.GSSUtil;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.internal.ktab.KeyTab;
public class SSL {
private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
private static final int LOOP_LIMIT = 1;
private static final char[] PASS = "secret".toCharArray();
private static int loopCount = 0;
private static volatile String server;
private static volatile int port;
@ -54,12 +55,39 @@ public class SSL {
kdc.addPrincipal(OneKDC.USER, OneKDC.PASS);
kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
kdc.addPrincipal("host/" + server, PASS);
KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
// Add 3 versions of keys into keytab
KeyTab ktab = KeyTab.create(OneKDC.KTAB);
PrincipalName service = new PrincipalName(
"host/" + server, PrincipalName.KRB_NT_SRV_HST);
ktab.addEntry(service, "pass1".toCharArray(), 1);
ktab.addEntry(service, "pass2".toCharArray(), 2);
ktab.addEntry(service, "pass3".toCharArray(), 3);
ktab.save();
// and use the middle one as the real key
kdc.addPrincipal("host/" + server, "pass2".toCharArray());
// JAAS config entry name ssl
System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
File f = new File(OneKDC.JAAS_CONF);
FileOutputStream fos = new FileOutputStream(f);
fos.write((
"ssl {\n" +
" com.sun.security.auth.module.Krb5LoginModule required\n" +
" principal=\"host/" + server + "\"\n" +
" useKeyTab=true\n" +
" keyTab=" + OneKDC.KTAB + "\n" +
" isInitiator=false\n" +
" storeKey=true;\n};\n"
).getBytes());
fos.close();
f.deleteOnExit();
final Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
final Context s = Context.fromUserPass("host/" + server, PASS, true);
final Context s = Context.fromJAAS("ssl");
c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);

View File

@ -0,0 +1,80 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6895424
* @summary RFC 5653
*/
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;
import sun.security.jgss.GSSUtil;
public class Test5653 {
public static void main(String[] args)
throws Exception {
Oid oldOid = new Oid("1.3.6.1.5.6.2");
new OneKDC(null).writeJAASConf();
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
GSSManager m = GSSManager.getInstance();
boolean found = false;
// Test 1: the getMechsForName() method accepts it.
for (Oid tmp: m.getMechsForName(oldOid)) {
if (tmp.equals(GSSUtil.GSS_KRB5_MECH_OID)) {
found = true;
break;
}
}
if (!found) {
throw new Exception("Cannot found krb5 mech for old name type");
}
// Test 2: the createName() method accepts it.
GSSName name = m.createName("server@host.rabbit.hole", oldOid);
// Test 3: its getStringNameType() output is correct
if (!name.getStringNameType().equals(GSSName.NT_HOSTBASED_SERVICE)) {
throw new Exception("GSSName not correct name type");
}
// Test 4: everything still works.
GSSContext c1 = m.createContext(
name,
GSSUtil.GSS_KRB5_MECH_OID,
null,
GSSContext.DEFAULT_LIFETIME);
byte[] token = c1.initSecContext(new byte[0], 0, 0);
Context s;
s = Context.fromJAAS("server");
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
s.x().acceptSecContext(token, 0, token.length);
}
}

View File

@ -1,5 +1,5 @@
#
# Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2004-2009 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -21,8 +21,8 @@
# have any questions.
#
# @test
# @bug 4811968
# @summary Serialization compatibility with old versions
# @bug 4811968 6908628
# @summary Serialization compatibility with old versions (and fix)
# @author Weijun Wang
#
# set a few environment variables so that the shell-script can run stand-alone
@ -99,7 +99,8 @@ esac
# the test code
${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}SerialTest.java || exit 10
${TESTJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \
-d . ${TESTSRC}${FS}SerialTest.java || exit 10
OLDJAVA="
/java/re/j2se/1.6.0/latest/binaries/${PF}
@ -161,4 +162,10 @@ rm -f tmp.oid.serial
rm -f tmp.oid.serial.old
rm -f SerialTest.class
for oldj in ${OLDJAVA}; do
if [ ! -d ${oldj} ]; then
echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr
fi
done
exit 0

View File

@ -166,8 +166,10 @@ public class HatRun {
jre_home );
String cdir = System.getProperty("test.classes", ".");
String os_arch = System.getProperty("os.arch");
boolean d64 = os_arch.equals("sparcv9") ||
os_arch.equals("amd64");
String os_name = System.getProperty("os.name");
boolean d64 = os_name.equals("SunOS") && (
os_arch.equals("sparcv9") ||
os_arch.equals("amd64"));
String isa_dir = d64?(File.separator+os_arch):"";
String java = jre_home
+ File.separator + "bin" + isa_dir