--- a/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61
8d9d430b4244b95f5cf1ebe719f834a1ac5d6cd5 jdk8-b62
21ee1dd7b809639284900a128b9b656a592ebc7a jdk8-b63
+70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64
--- a/.hgtags-top-repo Wed Nov 14 10:20:25 2012 -0800
+++ b/.hgtags-top-repo Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
20ff117b509075c3aec4ee3a57990ecd5db5df9c jdk8-b61
8a3fe0ae06a8cc21347da5a18384b0aa6c2349f5 jdk8-b62
3229597524cab4239325bc3602df6c486397a511 jdk8-b63
+1c8370a55b305d35353346202bde042ba9e8a9fd jdk8-b64
--- a/corba/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/corba/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
0e08ba7648fb3faa0986cb217887d7c4990977f3 jdk8-b61
08afb9c6f44f11c3595b01fd0985db64b29834dd jdk8-b62
6ccbf67b68bfed1ab9c44ab8748a5bdc7df33506 jdk8-b63
+54d599a5b4aad83c235d590652fc81f41c2824fb jdk8-b64
--- a/hotspot/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -291,3 +291,5 @@
dc16fe422c535ecd4e9f80fb814a1bb9704da6f5 hs25-b07
acabb5c282f59be7e3238920b2ea06b684ab68f7 jdk8-b63
8cb93eadfb6dcab88d91b8e2cd3e0e07d0ac4048 hs25-b08
+5920f72e799c8133d1066c4a62fa1fafcb729966 jdk8-b64
+b4ee7b773144a88af8b6b92e4384dea82cb948d8 hs25-b09
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Thu Nov 15 00:54:54 2012 +0000
@@ -121,7 +121,7 @@
Address addr = cache.getValue(getAddress());
return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr);
}
- public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); }
+ public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
public int getLength() { return (int)length.getValue(getAddress()); }
public Oop getResolvedReferences() {
Address handle = resolvedReferences.getValue(getAddress());
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu Nov 15 00:54:54 2012 +0000
@@ -177,7 +177,7 @@
bci. It is required that there is currently a bytecode at this
bci. */
public int getOrigBytecodeAt(int bci) {
- BreakpointInfo bp = ((InstanceKlass) getMethodHolder()).getBreakpoints();
+ BreakpointInfo bp = getMethodHolder().getBreakpoints();
for (; bp != null; bp = bp.getNext()) {
if (bp.match(this, bci)) {
return bp.getOrigBytecode();
@@ -238,7 +238,7 @@
}
// Method holder (the Klass holding this method)
- public Klass getMethodHolder() { return getConstants().getPoolHolder(); }
+ public InstanceKlass getMethodHolder() { return getConstants().getPoolHolder(); }
// Access flags
public boolean isPublic() { return getAccessFlagsObj().isPublic(); }
--- a/hotspot/make/hotspot_version Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/make/hotspot_version Thu Nov 15 00:54:54 2012 +0000
@@ -35,7 +35,7 @@
HS_MAJOR_VER=25
HS_MINOR_VER=0
-HS_BUILD_NUMBER=08
+HS_BUILD_NUMBER=09
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
--- a/hotspot/make/linux/makefiles/defs.make Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/make/linux/makefiles/defs.make Thu Nov 15 00:54:54 2012 +0000
@@ -170,68 +170,70 @@
# overridden in some situations, e.g., a BUILD_FLAVOR != product
# build.
- ifeq ($(BUILD_FLAVOR), product)
- FULL_DEBUG_SYMBOLS ?= 1
- ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
- else
- # debug variants always get Full Debug Symbols (if available)
- ENABLE_FULL_DEBUG_SYMBOLS = 1
- endif
- _JUNK_ := $(shell \
- echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
- # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
+ # Due to the multiple sub-make processes that occur this logic gets
+ # executed multiple times. We reduce the noise by at least checking that
+ # BUILD_FLAVOR has been set.
+ ifneq ($(BUILD_FLAVOR),)
+ ifeq ($(BUILD_FLAVOR), product)
+ FULL_DEBUG_SYMBOLS ?= 1
+ ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+ else
+ # debug variants always get Full Debug Symbols (if available)
+ ENABLE_FULL_DEBUG_SYMBOLS = 1
+ endif
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+ # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
- ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
- # Default OBJCOPY comes from GNU Binutils on Linux:
- DEF_OBJCOPY=/usr/bin/objcopy
- ifdef CROSS_COMPILE_ARCH
- # don't try to generate .debuginfo files when cross compiling
- _JUNK_ := $(shell \
- echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
- "skipping .debuginfo generation.")
- OBJCOPY=
- else
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ # Default OBJCOPY comes from GNU Binutils on Linux
+ ifeq ($(CROSS_COMPILE_ARCH),)
+ DEF_OBJCOPY=/usr/bin/objcopy
+ else
+ # Assume objcopy is part of the cross-compilation toolset
+ ifneq ($(ALT_COMPILER_PATH),)
+ DEF_OBJCOPY=$(ALT_COMPILER_PATH)/objcopy
+ endif
+ endif
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
ifneq ($(ALT_OBJCOPY),)
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
endif
- endif
- else
- OBJCOPY=
- endif
- ifeq ($(OBJCOPY),)
- _JUNK_ := $(shell \
- echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
- ENABLE_FULL_DEBUG_SYMBOLS=0
- _JUNK_ := $(shell \
- echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
- else
- _JUNK_ := $(shell \
- echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
+ ifeq ($(OBJCOPY),)
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files. You may need to set ALT_OBJCOPY.")
+ ENABLE_FULL_DEBUG_SYMBOLS=0
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+ else
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
- # Library stripping policies for .debuginfo configs:
- # all_strip - strips everything from the library
- # min_strip - strips most stuff from the library; leaves minimum symbols
- # no_strip - does not strip the library at all
- #
- # Oracle security policy requires "all_strip". A waiver was granted on
- # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
- #
- # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
- #
- STRIP_POLICY ?= min_strip
+ # Library stripping policies for .debuginfo configs:
+ # all_strip - strips everything from the library
+ # min_strip - strips most stuff from the library; leaves minimum symbols
+ # no_strip - does not strip the library at all
+ #
+ # Oracle security policy requires "all_strip". A waiver was granted on
+ # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
+ #
+ # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
+ #
+ STRIP_POLICY ?= min_strip
- _JUNK_ := $(shell \
- echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
- ZIP_DEBUGINFO_FILES ?= 1
+ ZIP_DEBUGINFO_FILES ?= 1
- _JUNK_ := $(shell \
- echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
- endif
-endif
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
+ endif
+ endif # ENABLE_FULL_DEBUG_SYMBOLS=1
+ endif # BUILD_FLAVOR
+endif # JDK_6_OR_EARLIER
JDK_INCLUDE_SUBDIR=linux
--- a/hotspot/make/linux/makefiles/vm.make Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/make/linux/makefiles/vm.make Thu Nov 15 00:54:54 2012 +0000
@@ -336,24 +336,23 @@
fi \
fi \
}
-ifeq ($(CROSS_COMPILE_ARCH),)
- ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO)
$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@
- ifeq ($(STRIP_POLICY),all_strip)
+ ifeq ($(STRIP_POLICY),all_strip)
$(QUIETLY) $(STRIP) $@
- else
- ifeq ($(STRIP_POLICY),min_strip)
+ else
+ ifeq ($(STRIP_POLICY),min_strip)
$(QUIETLY) $(STRIP) -g $@
- # implied else here is no stripping at all
- endif
+ # implied else here is no stripping at all
endif
+ endif
$(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
- ifeq ($(ZIP_DEBUGINFO_FILES),1)
+ ifeq ($(ZIP_DEBUGINFO_FILES),1)
$(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
$(RM) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
[ -f $(LIBJVM_G_DIZ) ] || { ln -s $(LIBJVM_DIZ) $(LIBJVM_G_DIZ); }
- endif
endif
endif
--- a/hotspot/make/solaris/makefiles/defs.make Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/make/solaris/makefiles/defs.make Thu Nov 15 00:54:54 2012 +0000
@@ -109,60 +109,63 @@
# overridden in some situations, e.g., a BUILD_FLAVOR != product
# build.
- ifeq ($(BUILD_FLAVOR), product)
- FULL_DEBUG_SYMBOLS ?= 1
- ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
- else
- # debug variants always get Full Debug Symbols (if available)
- ENABLE_FULL_DEBUG_SYMBOLS = 1
- endif
- _JUNK_ := $(shell \
- echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
- # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
-
- ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
- # Default OBJCOPY comes from the SUNWbinutils package:
- DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
- OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
- ifneq ($(ALT_OBJCOPY),)
- _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
- OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
+ # Due to the multiple sub-make processes that occur this logic gets
+ # executed multiple times. We reduce the noise by at least checking that
+ # BUILD_FLAVOR has been set.
+ ifneq ($(BUILD_FLAVOR),)
+ ifeq ($(BUILD_FLAVOR), product)
+ FULL_DEBUG_SYMBOLS ?= 1
+ ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+ else
+ # debug variants always get Full Debug Symbols (if available)
+ ENABLE_FULL_DEBUG_SYMBOLS = 1
endif
- else
- OBJCOPY=
- endif
-
- ifeq ($(OBJCOPY),)
- _JUNK_ := $(shell \
- echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
- ENABLE_FULL_DEBUG_SYMBOLS=0
_JUNK_ := $(shell \
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
- else
- _JUNK_ := $(shell \
- echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
+ # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
+
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ # Default OBJCOPY comes from the SUNWbinutils package:
+ DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
+ OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
+ ifneq ($(ALT_OBJCOPY),)
+ _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
+ OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
+ endif
+
+ ifeq ($(OBJCOPY),)
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
+ ENABLE_FULL_DEBUG_SYMBOLS=0
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+ else
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
- # Library stripping policies for .debuginfo configs:
- # all_strip - strips everything from the library
- # min_strip - strips most stuff from the library; leaves minimum symbols
- # no_strip - does not strip the library at all
- #
- # Oracle security policy requires "all_strip". A waiver was granted on
- # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
- #
- # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
- #
- STRIP_POLICY ?= min_strip
+ # Library stripping policies for .debuginfo configs:
+ # all_strip - strips everything from the library
+ # min_strip - strips most stuff from the library; leaves minimum symbols
+ # no_strip - does not strip the library at all
+ #
+ # Oracle security policy requires "all_strip". A waiver was granted on
+ # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
+ #
+ # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
+ #
+ STRIP_POLICY ?= min_strip
- _JUNK_ := $(shell \
- echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
- ZIP_DEBUGINFO_FILES ?= 1
+ ZIP_DEBUGINFO_FILES ?= 1
- _JUNK_ := $(shell \
- echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
- endif
-endif
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
+ endif
+ endif # ENABLE_FULL_DEBUG_SYMBOLS=1
+ endif # BUILD_FLAVOR
+endif # JDK_6_OR_EARLIER
JDK_INCLUDE_SUBDIR=solaris
--- a/hotspot/make/windows/makefiles/defs.make Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/make/windows/makefiles/defs.make Thu Nov 15 00:54:54 2012 +0000
@@ -131,23 +131,29 @@
# overridden in some situations, e.g., a BUILD_FLAVOR != product
# build.
-ifeq ($(BUILD_FLAVOR), product)
- FULL_DEBUG_SYMBOLS ?= 1
- ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
-else
- # debug variants always get Full Debug Symbols (if available)
- ENABLE_FULL_DEBUG_SYMBOLS = 1
+# Due to the multiple sub-make processes that occur this logic gets
+# executed multiple times. We reduce the noise by at least checking that
+# BUILD_FLAVOR has been set.
+ifneq ($(BUILD_FLAVOR),)
+ ifeq ($(BUILD_FLAVOR), product)
+ FULL_DEBUG_SYMBOLS ?= 1
+ ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+ else
+ # debug variants always get Full Debug Symbols (if available)
+ ENABLE_FULL_DEBUG_SYMBOLS = 1
+ endif
+ _JUNK_ := $(shell \
+ echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+ MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
+
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ ZIP_DEBUGINFO_FILES ?= 1
+ else
+ ZIP_DEBUGINFO_FILES=0
+ endif
+ MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
endif
-_JUNK_ := $(shell \
- echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
-MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
-ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
- ZIP_DEBUGINFO_FILES ?= 1
-else
- ZIP_DEBUGINFO_FILES=0
-endif
-MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
MAKE_ARGS += RM="$(RM)"
MAKE_ARGS += ZIPEXE=$(ZIPEXE)
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -2322,7 +2322,7 @@
// Pre-load a static method's oop into O1. Used both by locking code and
// the normal JNI call code.
if (method->is_static() && !is_critical_native) {
- __ set_oop_constant(JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()), O1);
+ __ set_oop_constant(JNIHandles::make_local(method->method_holder()->java_mirror()), O1);
// Now handlize the static class mirror in O1. It's known not-null.
__ st_ptr(O1, SP, klass_offset + STACK_BIAS);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1936,7 +1936,7 @@
if (method->is_static() && !is_critical_native) {
// load opp into a register
- __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
+ __ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
// Now handlize the static class mirror it's known not-null.
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -2179,7 +2179,7 @@
if (method->is_static() && !is_critical_native) {
// load oop into a register
- __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
+ __ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
// Now handlize the static class mirror it's known not-null.
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -488,8 +488,8 @@
}
// The AES intrinsic stubs require AES instruction support (of course)
- // but also require AVX mode for misaligned SSE access
- if (UseAES && (UseAVX > 0)) {
+ // but also require AVX and sse3 modes for instructions it use.
+ if (UseAES && (UseAVX > 0) && (UseSSE > 2)) {
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
UseAESIntrinsics = true;
}
--- a/hotspot/src/share/tools/hsdis/hsdis-demo.c Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/tools/hsdis/hsdis-demo.c Thu Nov 15 00:54:54 2012 +0000
@@ -85,9 +85,11 @@
#include "dlfcn.h"
-#define DECODE_INSTRUCTIONS_NAME "decode_instructions_virtual"
+#define DECODE_INSTRUCTIONS_VIRTUAL_NAME "decode_instructions_virtual"
+#define DECODE_INSTRUCTIONS_NAME "decode_instructions"
#define HSDIS_NAME "hsdis"
static void* decode_instructions_pv = 0;
+static void* decode_instructions_sv = 0;
static const char* hsdis_path[] = {
HSDIS_NAME"-"LIBARCH LIB_EXT,
"./" HSDIS_NAME"-"LIBARCH LIB_EXT,
@@ -101,11 +103,12 @@
void* dllib = NULL;
const char* *next_in_path = hsdis_path;
while (1) {
- decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
- if (decode_instructions_pv != NULL)
+ decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
+ decode_instructions_sv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
+ if (decode_instructions_pv != NULL || decode_instructions_sv != NULL)
return NULL;
if (dllib != NULL)
- return "plugin does not defined "DECODE_INSTRUCTIONS_NAME;
+ return "plugin does not defined "DECODE_INSTRUCTIONS_VIRTUAL_NAME" and "DECODE_INSTRUCTIONS_NAME;
for (dllib = NULL; dllib == NULL; ) {
const char* next_lib = (*next_in_path++);
if (next_lib == NULL)
@@ -213,20 +216,44 @@
printf("%s: %s\n", err, dlerror());
exit(1);
}
- printf("Decoding from %p to %p...\n", from, to);
- decode_instructions_ftype decode_instructions
- = (decode_instructions_ftype) decode_instructions_pv;
+ decode_func_vtype decode_instructions_v
+ = (decode_func_vtype) decode_instructions_pv;
+ decode_func_stype decode_instructions_s
+ = (decode_func_stype) decode_instructions_sv;
void* res;
- if (raw && xml) {
- res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
- } else if (raw) {
- res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
- } else {
- res = (*decode_instructions)(from, to, (unsigned char*)from, to - from,
- handle_event, (void*) event_cookie,
- fprintf_callback, stdout,
- options);
+ if (decode_instructions_pv != NULL) {
+ printf("\nDecoding from %p to %p...with %s\n", from, to, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
+ if (raw) {
+ res = (*decode_instructions_v)(from, to,
+ (unsigned char*)from, to - from,
+ simple_handle_event, stdout,
+ NULL, stdout,
+ options, 0);
+ } else {
+ res = (*decode_instructions_v)(from, to,
+ (unsigned char*)from, to - from,
+ handle_event, (void*) event_cookie,
+ fprintf_callback, stdout,
+ options, 0);
+ }
+ if (res != (void*)to)
+ printf("*** Result was %p!\n", res);
}
- if (res != (void*)to)
- printf("*** Result was %p!\n", res);
+ void* sres;
+ if (decode_instructions_sv != NULL) {
+ printf("\nDecoding from %p to %p...with old decode_instructions\n", from, to, DECODE_INSTRUCTIONS_NAME);
+ if (raw) {
+ sres = (*decode_instructions_s)(from, to,
+ simple_handle_event, stdout,
+ NULL, stdout,
+ options);
+ } else {
+ sres = (*decode_instructions_s)(from, to,
+ handle_event, (void*) event_cookie,
+ fprintf_callback, stdout,
+ options);
+ }
+ if (sres != (void *)to)
+ printf("*** Result of decode_instructions %p!\n", sres);
+ }
}
--- a/hotspot/src/share/tools/hsdis/hsdis.c Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/tools/hsdis/hsdis.c Thu Nov 15 00:54:54 2012 +0000
@@ -99,7 +99,7 @@
unsigned char* buffer, uintptr_t length,
event_callback_t event_callback_arg, void* event_stream_arg,
printf_callback_t printf_callback_arg, void* printf_stream_arg,
- const char* options) {
+ const char* options, int newline) {
struct hsdis_app_data app_data;
memset(&app_data, 0, sizeof(app_data));
app_data.start_va = start_va;
@@ -110,7 +110,7 @@
app_data.event_stream = event_stream_arg;
app_data.printf_callback = printf_callback_arg;
app_data.printf_stream = printf_stream_arg;
- app_data.do_newline = false;
+ app_data.do_newline = newline == 0 ? false : true;
return decode(&app_data, options);
}
@@ -132,7 +132,7 @@
event_stream_arg,
printf_callback_arg,
printf_stream_arg,
- options);
+ options, false);
}
static void* decode(struct hsdis_app_data* app_data, const char* options) {
@@ -173,7 +173,7 @@
if (!app_data->losing) {
const char* insn_close = format_insn_close("/insn", &app_data->dinfo,
buf, sizeof(buf));
- (*event_callback)(event_stream, insn_close, (void*) p) != NULL;
+ (*event_callback)(event_stream, insn_close, (void*) p);
if (app_data->do_newline) {
/* follow each complete insn by a nice newline */
@@ -182,13 +182,14 @@
}
}
- (*event_callback)(event_stream, "/insns", (void*) p);
+ if (app_data->losing) (*event_callback)(event_stream, "/insns", (void*) p);
return (void*) p;
}
}
/* take the address of the function, for luck, and also test the typedef: */
-const decode_instructions_ftype decode_instructions_address = &decode_instructions_virtual;
+const decode_func_vtype decode_func_virtual_address = &decode_instructions_virtual;
+const decode_func_stype decode_func_address = &decode_instructions;
static const char* format_insn_close(const char* close,
disassemble_info* dinfo,
--- a/hotspot/src/share/tools/hsdis/hsdis.h Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/tools/hsdis/hsdis.h Thu Nov 15 00:54:54 2012 +0000
@@ -47,6 +47,9 @@
where tag is a simple identifier, signifying (as in XML) a element start,
element end, and standalone element. (To render as XML, add angle brackets.)
*/
+#ifndef SHARED_TOOLS_HSDIS_H
+#define SHARED_TOOLS_HSDIS_H
+
extern
#ifdef DLL_EXPORT
DLL_EXPORT
@@ -57,16 +60,37 @@
void* event_stream,
int (*printf_callback)(void*, const char*, ...),
void* printf_stream,
- const char* options);
+ const char* options,
+ int newline /* bool value for nice new line */);
+
+/* This is the compatability interface for older versions of hotspot */
+extern
+#ifdef DLL_ENTRY
+ DLL_ENTRY
+#endif
+void* decode_instructions(void* start_pv, void* end_pv,
+ void* (*event_callback)(void*, const char*, void*),
+ void* event_stream,
+ int (*printf_callback)(void*, const char*, ...),
+ void* printf_stream,
+ const char* options);
/* convenience typedefs */
typedef void* (*decode_instructions_event_callback_ftype) (void*, const char*, void*);
typedef int (*decode_instructions_printf_callback_ftype) (void*, const char*, ...);
-typedef void* (*decode_instructions_ftype) (uintptr_t start_va, uintptr_t end_va,
- unsigned char* buffer, uintptr_t length,
- decode_instructions_event_callback_ftype event_callback,
- void* event_stream,
- decode_instructions_printf_callback_ftype printf_callback,
- void* printf_stream,
- const char* options);
+typedef void* (*decode_func_vtype) (uintptr_t start_va, uintptr_t end_va,
+ unsigned char* buffer, uintptr_t length,
+ decode_instructions_event_callback_ftype event_callback,
+ void* event_stream,
+ decode_instructions_printf_callback_ftype printf_callback,
+ void* printf_stream,
+ const char* options,
+ int newline);
+typedef void* (*decode_func_stype) (void* start_pv, void* end_pv,
+ decode_instructions_event_callback_ftype event_callback,
+ void* event_stream,
+ decode_instructions_printf_callback_ftype printf_callback,
+ void* printf_stream,
+ const char* options);
+#endif /* SHARED_TOOLS_HSDIS_H */
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -768,8 +768,8 @@
Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
if (m != NULL &&
(bc == Bytecodes::_invokestatic
- ? InstanceKlass::cast(m->method_holder())->is_not_initialized()
- : !InstanceKlass::cast(m->method_holder())->is_loaded())) {
+ ? m->method_holder()->is_not_initialized()
+ : !m->method_holder()->is_loaded())) {
m = NULL;
}
if (m != NULL) {
@@ -1056,7 +1056,7 @@
method_name,
entry_bci);
}
- InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
+ method->method_holder()->add_osr_nmethod(nm);
}
}
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -105,7 +105,7 @@
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
}
- if (InstanceKlass::cast(h_m()->method_holder())->is_linked()) {
+ if (h_m()->method_holder()->is_linked()) {
_can_be_statically_bound = h_m()->can_be_statically_bound();
} else {
// Have to use a conservative value in this case.
@@ -188,7 +188,7 @@
// Revert any breakpoint bytecodes in ci's copy
if (me->number_of_breakpoints() > 0) {
- BreakpointInfo* bp = InstanceKlass::cast(me->method_holder())->breakpoints();
+ BreakpointInfo* bp = me->method_holder()->breakpoints();
for (; bp != NULL; bp = bp->next()) {
if (bp->match(me)) {
code_at_put(bp->bci(), bp->orig_bytecode());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/bytecodeAssembler.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "classfile/bytecodeAssembler.hpp"
+#include "interpreter/bytecodes.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/constantPool.hpp"
+
+#ifdef TARGET_ARCH_x86
+# include "bytes_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "bytes_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "bytes_zero.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "bytes_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "bytes_ppc.hpp"
+#endif
+
+u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) {
+ u2 index;
+ u2* probe = _indices.get(bcpe);
+ if (probe == NULL) {
+ index = _entries.length();
+ _entries.append(bcpe);
+ _indices.put(bcpe, index);
+ } else {
+ index = *probe;
+ }
+ return index + _orig->length();
+}
+
+ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
+ if (_entries.length() == 0) {
+ return _orig;
+ }
+
+ ConstantPool* cp = ConstantPool::allocate(
+ _orig->pool_holder()->class_loader_data(),
+ _orig->length() + _entries.length(), CHECK_NULL);
+
+ cp->set_pool_holder(_orig->pool_holder());
+ _orig->copy_cp_to(1, _orig->length() - 1, cp, 1, CHECK_NULL);
+
+ for (int i = 0; i < _entries.length(); ++i) {
+ BytecodeCPEntry entry = _entries.at(i);
+ int idx = i + _orig->length();
+ switch (entry._tag) {
+ case BytecodeCPEntry::UTF8:
+ cp->symbol_at_put(idx, entry._u.utf8);
+ entry._u.utf8->increment_refcount();
+ break;
+ case BytecodeCPEntry::KLASS:
+ cp->unresolved_klass_at_put(
+ idx, cp->symbol_at(entry._u.klass));
+ break;
+ case BytecodeCPEntry::STRING:
+ cp->unresolved_string_at_put(
+ idx, cp->symbol_at(entry._u.string));
+ break;
+ case BytecodeCPEntry::NAME_AND_TYPE:
+ cp->name_and_type_at_put(idx,
+ entry._u.name_and_type.name_index,
+ entry._u.name_and_type.type_index);
+ break;
+ case BytecodeCPEntry::METHODREF:
+ cp->method_at_put(idx,
+ entry._u.methodref.class_index,
+ entry._u.methodref.name_and_type_index);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+ }
+ return cp;
+}
+
+void BytecodeAssembler::append(u1 imm_u1) {
+ _code->append(imm_u1);
+}
+
+void BytecodeAssembler::append(u2 imm_u2) {
+ _code->append(0);
+ _code->append(0);
+ Bytes::put_Java_u2(_code->adr_at(_code->length() - 2), imm_u2);
+}
+
+void BytecodeAssembler::append(u4 imm_u4) {
+ _code->append(0);
+ _code->append(0);
+ _code->append(0);
+ _code->append(0);
+ Bytes::put_Java_u4(_code->adr_at(_code->length() - 4), imm_u4);
+}
+
+void BytecodeAssembler::xload(u4 index, u1 onebyteop, u1 twobyteop) {
+ if (index < 4) {
+ _code->append(onebyteop + index);
+ } else {
+ _code->append(twobyteop);
+ _code->append((u2)index);
+ }
+}
+
+void BytecodeAssembler::dup() {
+ _code->append(Bytecodes::_dup);
+}
+
+void BytecodeAssembler::_new(Symbol* sym) {
+ u2 cpool_index = _cp->klass(sym);
+ _code->append(Bytecodes::_new);
+ append(cpool_index);
+}
+
+void BytecodeAssembler::load_string(Symbol* sym) {
+ u2 cpool_index = _cp->string(sym);
+ if (cpool_index < 0x100) {
+ ldc(cpool_index);
+ } else {
+ ldc_w(cpool_index);
+ }
+}
+
+void BytecodeAssembler::ldc(u1 index) {
+ _code->append(Bytecodes::_ldc);
+ append(index);
+}
+
+void BytecodeAssembler::ldc_w(u2 index) {
+ _code->append(Bytecodes::_ldc_w);
+ append(index);
+}
+
+void BytecodeAssembler::athrow() {
+ _code->append(Bytecodes::_athrow);
+}
+
+void BytecodeAssembler::iload(u4 index) {
+ xload(index, Bytecodes::_iload_0, Bytecodes::_iload);
+}
+
+void BytecodeAssembler::lload(u4 index) {
+ xload(index, Bytecodes::_lload_0, Bytecodes::_lload);
+}
+
+void BytecodeAssembler::fload(u4 index) {
+ xload(index, Bytecodes::_fload_0, Bytecodes::_fload);
+}
+
+void BytecodeAssembler::dload(u4 index) {
+ xload(index, Bytecodes::_dload_0, Bytecodes::_dload);
+}
+
+void BytecodeAssembler::aload(u4 index) {
+ xload(index, Bytecodes::_aload_0, Bytecodes::_aload);
+}
+
+void BytecodeAssembler::load(BasicType bt, u4 index) {
+ switch (bt) {
+ case T_BOOLEAN:
+ case T_CHAR:
+ case T_BYTE:
+ case T_SHORT:
+ case T_INT: iload(index); break;
+ case T_FLOAT: fload(index); break;
+ case T_DOUBLE: dload(index); break;
+ case T_LONG: lload(index); break;
+ case T_OBJECT:
+ case T_ARRAY: aload(index); break;
+ default:
+ ShouldNotReachHere();
+ }
+}
+
+void BytecodeAssembler::checkcast(Symbol* sym) {
+ u2 cpool_index = _cp->klass(sym);
+ _code->append(Bytecodes::_checkcast);
+ append(cpool_index);
+}
+
+void BytecodeAssembler::invokespecial(Method* method) {
+ invokespecial(method->klass_name(), method->name(), method->signature());
+}
+
+void BytecodeAssembler::invokespecial(Symbol* klss, Symbol* name, Symbol* sig) {
+ u2 methodref_index = _cp->methodref(klss, name, sig);
+ _code->append(Bytecodes::_invokespecial);
+ append(methodref_index);
+}
+
+void BytecodeAssembler::invokevirtual(Method* method) {
+ invokevirtual(method->klass_name(), method->name(), method->signature());
+}
+
+void BytecodeAssembler::invokevirtual(Symbol* klss, Symbol* name, Symbol* sig) {
+ u2 methodref_index = _cp->methodref(klss, name, sig);
+ _code->append(Bytecodes::_invokevirtual);
+ append(methodref_index);
+}
+
+void BytecodeAssembler::ireturn() {
+ _code->append(Bytecodes::_ireturn);
+}
+
+void BytecodeAssembler::lreturn() {
+ _code->append(Bytecodes::_lreturn);
+}
+
+void BytecodeAssembler::freturn() {
+ _code->append(Bytecodes::_freturn);
+}
+
+void BytecodeAssembler::dreturn() {
+ _code->append(Bytecodes::_dreturn);
+}
+
+void BytecodeAssembler::areturn() {
+ _code->append(Bytecodes::_areturn);
+}
+
+void BytecodeAssembler::_return() {
+ _code->append(Bytecodes::_return);
+}
+
+void BytecodeAssembler::_return(BasicType bt) {
+ switch (bt) {
+ case T_BOOLEAN:
+ case T_CHAR:
+ case T_BYTE:
+ case T_SHORT:
+ case T_INT: ireturn(); break;
+ case T_FLOAT: freturn(); break;
+ case T_DOUBLE: dreturn(); break;
+ case T_LONG: lreturn(); break;
+ case T_OBJECT:
+ case T_ARRAY: areturn(); break;
+ case T_VOID: _return(); break;
+ default:
+ ShouldNotReachHere();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
+#define SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
+
+#include "memory/allocation.hpp"
+#include "oops/method.hpp"
+#include "oops/symbol.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/resourceHash.hpp"
+
+
+/**
+ * Bytecode Assembler
+ *
+ * These classes are used to synthesize code for creating new methods from
+ * within the VM. This is only a partial implementation of an assembler;
+ * only the bytecodes that are needed by clients are implemented at this time.
+ * This is used during default method analysis to create overpass methods
+ * and add them to a call during parsing. Other uses (such as creating
+ * bridges) may come later. Any missing bytecodes can be implemented on an
+ * as-need basis.
+ */
+
+class BytecodeBuffer : public GrowableArray<u1> {
+ public:
+ BytecodeBuffer() : GrowableArray<u1>(20) {}
+};
+
+// Entries in a yet-to-be-created constant pool. Limited types for now.
+class BytecodeCPEntry VALUE_OBJ_CLASS_SPEC {
+ public:
+ enum tag {
+ ERROR_TAG,
+ UTF8,
+ KLASS,
+ STRING,
+ NAME_AND_TYPE,
+ METHODREF
+ };
+
+ u1 _tag;
+ union {
+ Symbol* utf8;
+ u2 klass;
+ u2 string;
+ struct {
+ u2 name_index;
+ u2 type_index;
+ } name_and_type;
+ struct {
+ u2 class_index;
+ u2 name_and_type_index;
+ } methodref;
+ uintptr_t hash;
+ } _u;
+
+ BytecodeCPEntry() : _tag(ERROR_TAG) { _u.hash = 0; }
+ BytecodeCPEntry(u1 tag) : _tag(tag) { _u.hash = 0; }
+
+ static BytecodeCPEntry utf8(Symbol* symbol) {
+ BytecodeCPEntry bcpe(UTF8);
+ bcpe._u.utf8 = symbol;
+ return bcpe;
+ }
+
+ static BytecodeCPEntry klass(u2 index) {
+ BytecodeCPEntry bcpe(KLASS);
+ bcpe._u.klass = index;
+ return bcpe;
+ }
+
+ static BytecodeCPEntry string(u2 index) {
+ BytecodeCPEntry bcpe(STRING);
+ bcpe._u.string = index;
+ return bcpe;
+ }
+
+ static BytecodeCPEntry name_and_type(u2 name, u2 type) {
+ BytecodeCPEntry bcpe(NAME_AND_TYPE);
+ bcpe._u.name_and_type.name_index = name;
+ bcpe._u.name_and_type.type_index = type;
+ return bcpe;
+ }
+
+ static BytecodeCPEntry methodref(u2 class_index, u2 nat) {
+ BytecodeCPEntry bcpe(METHODREF);
+ bcpe._u.methodref.class_index = class_index;
+ bcpe._u.methodref.name_and_type_index = nat;
+ return bcpe;
+ }
+
+ static bool equals(BytecodeCPEntry const& e0, BytecodeCPEntry const& e1) {
+ return e0._tag == e1._tag && e0._u.hash == e1._u.hash;
+ }
+
+ static unsigned hash(BytecodeCPEntry const& e0) {
+ return (unsigned)(e0._tag ^ e0._u.hash);
+ }
+};
+
+class BytecodeConstantPool : ResourceObj {
+ private:
+ typedef ResourceHashtable<BytecodeCPEntry, u2,
+ &BytecodeCPEntry::hash, &BytecodeCPEntry::equals> IndexHash;
+
+ ConstantPool* _orig;
+ GrowableArray<BytecodeCPEntry> _entries;
+ IndexHash _indices;
+
+ u2 find_or_add(BytecodeCPEntry const& bcpe);
+
+ public:
+
+ BytecodeConstantPool(ConstantPool* orig) : _orig(orig) {}
+
+ BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); }
+
+ InstanceKlass* pool_holder() const {
+ return InstanceKlass::cast(_orig->pool_holder());
+ }
+
+ u2 utf8(Symbol* sym) {
+ return find_or_add(BytecodeCPEntry::utf8(sym));
+ }
+
+ u2 klass(Symbol* class_name) {
+ return find_or_add(BytecodeCPEntry::klass(utf8(class_name)));
+ }
+
+ u2 string(Symbol* str) {
+ return find_or_add(BytecodeCPEntry::string(utf8(str)));
+ }
+
+ u2 name_and_type(Symbol* name, Symbol* sig) {
+ return find_or_add(BytecodeCPEntry::name_and_type(utf8(name), utf8(sig)));
+ }
+
+ u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig) {
+ return find_or_add(BytecodeCPEntry::methodref(
+ klass(class_name), name_and_type(name, sig)));
+ }
+
+ ConstantPool* create_constant_pool(TRAPS) const;
+};
+
+// Partial bytecode assembler - only what we need for creating
+// overpass methods for default methods is implemented
+class BytecodeAssembler : StackObj {
+ private:
+ BytecodeBuffer* _code;
+ BytecodeConstantPool* _cp;
+
+ void append(u1 imm_u1);
+ void append(u2 imm_u2);
+ void append(u4 imm_u4);
+
+ void xload(u4 index, u1 quick, u1 twobyte);
+
+ public:
+ BytecodeAssembler(BytecodeBuffer* buffer, BytecodeConstantPool* cp)
+ : _code(buffer), _cp(cp) {}
+
+ void aload(u4 index);
+ void areturn();
+ void athrow();
+ void checkcast(Symbol* sym);
+ void dload(u4 index);
+ void dreturn();
+ void dup();
+ void fload(u4 index);
+ void freturn();
+ void iload(u4 index);
+ void invokespecial(Method* method);
+ void invokespecial(Symbol* cls, Symbol* name, Symbol* sig);
+ void invokevirtual(Method* method);
+ void invokevirtual(Symbol* cls, Symbol* name, Symbol* sig);
+ void ireturn();
+ void ldc(u1 index);
+ void ldc_w(u2 index);
+ void lload(u4 index);
+ void lreturn();
+ void _new(Symbol* sym);
+ void _return();
+
+ void load_string(Symbol* sym);
+ void load(BasicType bt, u4 index);
+ void _return(BasicType bt);
+};
+
+#endif // SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -27,6 +27,8 @@
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
+#include "classfile/defaultMethods.hpp"
+#include "classfile/genericSignatures.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -84,6 +86,9 @@
// - to check NameAndType_info signatures more aggressively
#define JAVA_7_VERSION 51
+// Extension method support.
+#define JAVA_8_VERSION 52
+
void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
@@ -785,6 +790,7 @@
ClassLoaderData* loader_data,
Handle protection_domain,
Symbol* class_name,
+ bool* has_default_methods,
TRAPS) {
ClassFileStream* cfs = stream();
assert(length > 0, "only called for length>0");
@@ -821,6 +827,9 @@
if (!Klass::cast(interf())->is_interface()) {
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
}
+ if (InstanceKlass::cast(interf())->has_default_methods()) {
+ *has_default_methods = true;
+ }
interfaces->at_put(index, interf());
}
@@ -1928,7 +1937,8 @@
if (method_attribute_name == vmSymbols::tag_code()) {
// Parse Code attribute
if (_need_verify) {
- guarantee_property(!access_flags.is_native() && !access_flags.is_abstract(),
+ guarantee_property(
+ !access_flags.is_native() && !access_flags.is_abstract(),
"Code attribute in native or abstract methods in class file %s",
CHECK_(nullHandle));
}
@@ -2125,7 +2135,9 @@
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
- parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle));
+ parse_annotations(runtime_visible_annotations,
+ runtime_visible_annotations_length, cp, &parsed_annotations,
+ CHECK_(nullHandle));
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = method_attribute_length;
@@ -2169,12 +2181,10 @@
}
// All sizing information for a Method* is finally available, now create it
- Method* m = Method::allocate(loader_data, code_length, access_flags,
- linenumber_table_length,
- total_lvt_length,
- exception_table_length,
- checked_exceptions_length,
- CHECK_(nullHandle));
+ Method* m = Method::allocate(
+ loader_data, code_length, access_flags, linenumber_table_length,
+ total_lvt_length, exception_table_length, checked_exceptions_length,
+ ConstMethod::NORMAL, CHECK_(nullHandle));
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
@@ -2204,7 +2214,6 @@
// Fill in code attribute information
m->set_max_stack(max_stack);
m->set_max_locals(max_locals);
-
m->constMethod()->set_stackmap_data(stackmap_data);
// Copy byte codes
@@ -2356,6 +2365,7 @@
Array<AnnotationArray*>** methods_annotations,
Array<AnnotationArray*>** methods_parameter_annotations,
Array<AnnotationArray*>** methods_default_annotations,
+ bool* has_default_methods,
TRAPS) {
ClassFileStream* cfs = stream();
AnnotationArray* method_annotations = NULL;
@@ -2382,6 +2392,10 @@
if (method->is_final()) {
*has_final_method = true;
}
+ if (is_interface && !method->is_abstract() && !method->is_static()) {
+ // default method
+ *has_default_methods = true;
+ }
methods->at_put(index, method());
if (*methods_annotations == NULL) {
*methods_annotations =
@@ -2907,6 +2921,34 @@
}
+#ifndef PRODUCT
+static void parseAndPrintGenericSignatures(
+ instanceKlassHandle this_klass, TRAPS) {
+ assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise");
+ ResourceMark rm;
+
+ if (this_klass->generic_signature() != NULL) {
+ using namespace generic;
+ ClassDescriptor* spec = ClassDescriptor::parse_generic_signature(this_klass(), CHECK);
+
+ tty->print_cr("Parsing %s", this_klass->generic_signature()->as_C_string());
+ spec->print_on(tty);
+
+ for (int i = 0; i < this_klass->methods()->length(); ++i) {
+ Method* m = this_klass->methods()->at(i);
+ MethodDescriptor* method_spec = MethodDescriptor::parse_generic_signature(m, spec);
+ Symbol* sig = m->generic_signature();
+ if (sig == NULL) {
+ sig = m->signature();
+ }
+ tty->print_cr("Parsing %s", sig->as_C_string());
+ method_spec->print_on(tty);
+ }
+ }
+}
+#endif // ndef PRODUCT
+
+
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
Handle class_loader,
Handle protection_domain,
@@ -2923,6 +2965,8 @@
unsigned char *cached_class_file_bytes = NULL;
jint cached_class_file_length;
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
+ bool has_default_methods = false;
+ ResourceMark rm(THREAD);
ClassFileStream* cfs = stream();
// Timing
@@ -3138,7 +3182,9 @@
if (itfs_len == 0) {
local_interfaces = Universe::the_empty_klass_array();
} else {
- local_interfaces = parse_interfaces(cp, itfs_len, loader_data, protection_domain, _class_name, CHECK_(nullHandle));
+ local_interfaces = parse_interfaces(
+ cp, itfs_len, loader_data, protection_domain, _class_name,
+ &has_default_methods, CHECK_(nullHandle));
}
u2 java_fields_count = 0;
@@ -3164,6 +3210,7 @@
&methods_annotations,
&methods_parameter_annotations,
&methods_default_annotations,
+ &has_default_methods,
CHECK_(nullHandle));
// Additional attributes
@@ -3193,6 +3240,11 @@
super_klass = instanceKlassHandle(THREAD, kh());
}
if (super_klass.not_null()) {
+
+ if (super_klass->has_default_methods()) {
+ has_default_methods = true;
+ }
+
if (super_klass->is_interface()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
@@ -3229,14 +3281,11 @@
int itable_size = 0;
int num_miranda_methods = 0;
- klassVtable::compute_vtable_size_and_num_mirandas(vtable_size,
- num_miranda_methods,
- super_klass(),
- methods,
- access_flags,
- class_loader,
- class_name,
- local_interfaces,
+ GrowableArray<Method*> all_mirandas(20);
+
+ klassVtable::compute_vtable_size_and_num_mirandas(
+ &vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
+ access_flags, class_loader, class_name, local_interfaces,
CHECK_(nullHandle));
// Size of Java itable (in words)
@@ -3656,6 +3705,7 @@
this_klass->set_minor_version(minor_version);
this_klass->set_major_version(major_version);
+ this_klass->set_has_default_methods(has_default_methods);
// Set up Method*::intrinsic_id as soon as we know the names of methods.
// (We used to do this lazily, but now we query it in Rewriter,
@@ -3673,6 +3723,16 @@
cached_class_file_length);
}
+ // Fill in field values obtained by parse_classfile_attributes
+ if (parsed_annotations.has_any_annotations())
+ parsed_annotations.apply_to(this_klass);
+ // Create annotations
+ if (_annotations != NULL && this_klass->annotations() == NULL) {
+ Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
+ this_klass->set_annotations(anno);
+ }
+ apply_parsed_class_attributes(this_klass);
+
// Miranda methods
if ((num_miranda_methods > 0) ||
// if this class introduced new miranda methods or
@@ -3682,18 +3742,6 @@
this_klass->set_has_miranda_methods(); // then set a flag
}
- // Fill in field values obtained by parse_classfile_attributes
- if (parsed_annotations.has_any_annotations()) {
- parsed_annotations.apply_to(this_klass);
- }
- // Create annotations
- if (_annotations != NULL && this_klass->annotations() == NULL) {
- Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
- this_klass->set_annotations(anno);
- }
- apply_parsed_class_attributes(this_klass);
-
- // Compute transitive closure of interfaces this class implements
this_klass->set_transitive_interfaces(transitive_interfaces);
// Fill in information needed to compute superclasses.
@@ -3702,6 +3750,7 @@
// Initialize itable offset tables
klassItable::setup_itable_offset_table(this_klass);
+ // Compute transitive closure of interfaces this class implements
// Do final class setup
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
@@ -3726,6 +3775,21 @@
check_illegal_static_method(this_klass, CHECK_(nullHandle));
}
+
+#ifdef ASSERT
+ if (ParseAllGenericSignatures) {
+ parseAndPrintGenericSignatures(this_klass, CHECK_(nullHandle));
+ }
+#endif
+
+ // Generate any default methods - default methods are interface methods
+ // that have a default implementation. This is new with Lambda project.
+ if (has_default_methods && !access_flags.is_interface() &&
+ local_interfaces->length() > 0) {
+ DefaultMethods::generate_default_methods(
+ this_klass(), &all_mirandas, CHECK_(nullHandle));
+ }
+
// Allocate mirror and initialize static fields
java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
@@ -3744,6 +3808,7 @@
false /* not shared class */);
if (TraceClassLoading) {
+ ResourceMark rm;
// print in a single call to reduce interleaving of output
if (cfs->source() != NULL) {
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
@@ -3758,13 +3823,13 @@
tty->print("[Loaded %s]\n", this_klass->external_name());
}
} else {
- ResourceMark rm;
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
InstanceKlass::cast(class_loader->klass())->external_name());
}
}
if (TraceClassResolution) {
+ ResourceMark rm;
// print out the superclass.
const char * from = Klass::cast(this_klass())->external_name();
if (this_klass->java_super() != NULL) {
@@ -3785,6 +3850,7 @@
#ifndef PRODUCT
if( PrintCompactFieldsSavings ) {
+ ResourceMark rm;
if( nonstatic_field_size < orig_nonstatic_field_size ) {
tty->print("[Saved %d of %d bytes in %s]\n",
(orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
@@ -3811,7 +3877,6 @@
return this_klass;
}
-
unsigned int
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
unsigned int nonstatic_oop_map_count,
@@ -4128,7 +4193,7 @@
}
// continue to look from super_m's holder's super.
- k = InstanceKlass::cast(super_m->method_holder())->super();
+ k = super_m->method_holder()->super();
continue;
}
@@ -4263,13 +4328,16 @@
const bool is_strict = (flags & JVM_ACC_STRICT) != 0;
const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0;
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
+ const bool major_gte_8 = _major_version >= JAVA_8_VERSION;
const bool is_initializer = (name == vmSymbols::object_initializer_name());
bool is_illegal = false;
if (is_interface) {
- if (!is_abstract || !is_public || is_static || is_final ||
- is_native || (major_gte_15 && (is_synchronized || is_strict))) {
+ if (!is_public || is_static || is_final || is_native ||
+ ((is_synchronized || is_strict) && major_gte_15 &&
+ (!major_gte_8 || is_abstract)) ||
+ (!major_gte_8 && !is_abstract)) {
is_illegal = true;
}
} else { // not interface
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -151,6 +151,7 @@
ClassLoaderData* loader_data,
Handle protection_domain,
Symbol* class_name,
+ bool* has_default_methods,
TRAPS);
void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
@@ -188,6 +189,7 @@
Array<AnnotationArray*>** methods_annotations,
Array<AnnotationArray*>** methods_parameter_annotations,
Array<AnnotationArray*>** methods_default_annotations,
+ bool* has_default_method,
TRAPS);
Array<int>* sort_methods(ClassLoaderData* loader_data,
Array<Method*>* methods,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,1387 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/bytecodeAssembler.hpp"
+#include "classfile/defaultMethods.hpp"
+#include "classfile/genericSignatures.hpp"
+#include "classfile/symbolTable.hpp"
+#include "memory/allocation.hpp"
+#include "memory/metadataFactory.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/signature.hpp"
+#include "runtime/thread.hpp"
+#include "oops/instanceKlass.hpp"
+#include "oops/klass.hpp"
+#include "oops/method.hpp"
+#include "utilities/accessFlags.hpp"
+#include "utilities/exceptions.hpp"
+#include "utilities/ostream.hpp"
+#include "utilities/pair.hpp"
+#include "utilities/resourceHash.hpp"
+
+typedef enum { QUALIFIED, DISQUALIFIED } QualifiedState;
+
+// Because we use an iterative algorithm when iterating over the type
+// hierarchy, we can't use traditional scoped objects which automatically do
+// cleanup in the destructor when the scope is exited. PseudoScope (and
+// PseudoScopeMark) provides a similar functionality, but for when you want a
+// scoped object in non-stack memory (such as in resource memory, as we do
+// here). You've just got to remember to call 'destroy()' on the scope when
+// leaving it (and marks have to be explicitly added).
+class PseudoScopeMark : public ResourceObj {
+ public:
+ virtual void destroy() = 0;
+};
+
+class PseudoScope : public ResourceObj {
+ private:
+ GrowableArray<PseudoScopeMark*> _marks;
+ public:
+
+ static PseudoScope* cast(void* data) {
+ return static_cast<PseudoScope*>(data);
+ }
+
+ void add_mark(PseudoScopeMark* psm) {
+ _marks.append(psm);
+ }
+
+ void destroy() {
+ for (int i = 0; i < _marks.length(); ++i) {
+ _marks.at(i)->destroy();
+ }
+ }
+};
+
+class ContextMark : public PseudoScopeMark {
+ private:
+ generic::Context::Mark _mark;
+ public:
+ ContextMark(const generic::Context::Mark& cm) : _mark(cm) {}
+ virtual void destroy() { _mark.destroy(); }
+};
+
+#ifndef PRODUCT
+static void print_slot(outputStream* str, Symbol* name, Symbol* signature) {
+ ResourceMark rm;
+ str->print("%s%s", name->as_C_string(), signature->as_C_string());
+}
+
+static void print_method(outputStream* str, Method* mo, bool with_class=true) {
+ ResourceMark rm;
+ if (with_class) {
+ str->print("%s.", mo->klass_name()->as_C_string());
+ }
+ print_slot(str, mo->name(), mo->signature());
+}
+#endif // ndef PRODUCT
+
+/**
+ * Perform a depth-first iteration over the class hierarchy, applying
+ * algorithmic logic as it goes.
+ *
+ * This class is one half of the inheritance hierarchy analysis mechanism.
+ * It is meant to be used in conjunction with another class, the algorithm,
+ * which is indicated by the ALGO template parameter. This class can be
+ * paired with any algorithm class that provides the required methods.
+ *
+ * This class contains all the mechanics for iterating over the class hierarchy
+ * starting at a particular root, without recursing (thus limiting stack growth
+ * from this point). It visits each superclass (if present) and superinterface
+ * in a depth-first manner, with callbacks to the ALGO class as each class is
+ * encountered (visit()), The algorithm can cut-off further exploration of a
+ * particular branch by returning 'false' from a visit() call.
+ *
+ * The ALGO class, must provide a visit() method, which each of which will be
+ * called once for each node in the inheritance tree during the iteration. In
+ * addition, it can provide a memory block via new_node_data(InstanceKlass*),
+ * which it can use for node-specific storage (and access via the
+ * current_data() and data_at_depth(int) methods).
+ *
+ * Bare minimum needed to be an ALGO class:
+ * class Algo : public HierarchyVisitor<Algo> {
+ * void* new_node_data(InstanceKlass* cls) { return NULL; }
+ * void free_node_data(void* data) { return; }
+ * bool visit() { return true; }
+ * };
+ */
+template <class ALGO>
+class HierarchyVisitor : StackObj {
+ private:
+
+ class Node : public ResourceObj {
+ public:
+ InstanceKlass* _class;
+ bool _super_was_visited;
+ int _interface_index;
+ void* _algorithm_data;
+
+ Node(InstanceKlass* cls, void* data, bool visit_super)
+ : _class(cls), _super_was_visited(!visit_super),
+ _interface_index(0), _algorithm_data(data) {}
+
+ int number_of_interfaces() { return _class->local_interfaces()->length(); }
+ int interface_index() { return _interface_index; }
+ void set_super_visited() { _super_was_visited = true; }
+ void increment_visited_interface() { ++_interface_index; }
+ void set_all_interfaces_visited() {
+ _interface_index = number_of_interfaces();
+ }
+ bool has_visited_super() { return _super_was_visited; }
+ bool has_visited_all_interfaces() {
+ return interface_index() >= number_of_interfaces();
+ }
+ InstanceKlass* interface_at(int index) {
+ return InstanceKlass::cast(_class->local_interfaces()->at(index));
+ }
+ InstanceKlass* next_super() { return _class->java_super(); }
+ InstanceKlass* next_interface() {
+ return interface_at(interface_index());
+ }
+ };
+
+ bool _cancelled;
+ GrowableArray<Node*> _path;
+
+ Node* current_top() const { return _path.top(); }
+ bool has_more_nodes() const { return !_path.is_empty(); }
+ void push(InstanceKlass* cls, void* data) {
+ assert(cls != NULL, "Requires a valid instance class");
+ Node* node = new Node(cls, data, has_super(cls));
+ _path.push(node);
+ }
+ void pop() { _path.pop(); }
+
+ void reset_iteration() {
+ _cancelled = false;
+ _path.clear();
+ }
+ bool is_cancelled() const { return _cancelled; }
+
+ static bool has_super(InstanceKlass* cls) {
+ return cls->super() != NULL && !cls->is_interface();
+ }
+
+ Node* node_at_depth(int i) const {
+ return (i >= _path.length()) ? NULL : _path.at(_path.length() - i - 1);
+ }
+
+ protected:
+
+ // Accessors available to the algorithm
+ int current_depth() const { return _path.length() - 1; }
+
+ InstanceKlass* class_at_depth(int i) {
+ Node* n = node_at_depth(i);
+ return n == NULL ? NULL : n->_class;
+ }
+ InstanceKlass* current_class() { return class_at_depth(0); }
+
+ void* data_at_depth(int i) {
+ Node* n = node_at_depth(i);
+ return n == NULL ? NULL : n->_algorithm_data;
+ }
+ void* current_data() { return data_at_depth(0); }
+
+ void cancel_iteration() { _cancelled = true; }
+
+ public:
+
+ void run(InstanceKlass* root) {
+ ALGO* algo = static_cast<ALGO*>(this);
+
+ reset_iteration();
+
+ void* algo_data = algo->new_node_data(root);
+ push(root, algo_data);
+ bool top_needs_visit = true;
+
+ do {
+ Node* top = current_top();
+ if (top_needs_visit) {
+ if (algo->visit() == false) {
+ // algorithm does not want to continue along this path. Arrange
+ // it so that this state is immediately popped off the stack
+ top->set_super_visited();
+ top->set_all_interfaces_visited();
+ }
+ top_needs_visit = false;
+ }
+
+ if (top->has_visited_super() && top->has_visited_all_interfaces()) {
+ algo->free_node_data(top->_algorithm_data);
+ pop();
+ } else {
+ InstanceKlass* next = NULL;
+ if (top->has_visited_super() == false) {
+ next = top->next_super();
+ top->set_super_visited();
+ } else {
+ next = top->next_interface();
+ top->increment_visited_interface();
+ }
+ assert(next != NULL, "Otherwise we shouldn't be here");
+ algo_data = algo->new_node_data(next);
+ push(next, algo_data);
+ top_needs_visit = true;
+ }
+ } while (!is_cancelled() && has_more_nodes());
+ }
+};
+
+#ifndef PRODUCT
+class PrintHierarchy : public HierarchyVisitor<PrintHierarchy> {
+ public:
+
+ bool visit() {
+ InstanceKlass* cls = current_class();
+ streamIndentor si(tty, current_depth() * 2);
+ tty->indent().print_cr("%s", cls->name()->as_C_string());
+ return true;
+ }
+
+ void* new_node_data(InstanceKlass* cls) { return NULL; }
+ void free_node_data(void* data) { return; }
+};
+#endif // ndef PRODUCT
+
+// Used to register InstanceKlass objects and all related metadata structures
+// (Methods, ConstantPools) as "in-use" by the current thread so that they can't
+// be deallocated by class redefinition while we're using them. The classes are
+// de-registered when this goes out of scope.
+//
+// Once a class is registered, we need not bother with methodHandles or
+// constantPoolHandles for it's associated metadata.
+class KeepAliveRegistrar : public StackObj {
+ private:
+ Thread* _thread;
+ GrowableArray<ConstantPool*> _keep_alive;
+
+ public:
+ KeepAliveRegistrar(Thread* thread) : _thread(thread), _keep_alive(20) {
+ assert(thread == Thread::current(), "Must be current thread");
+ }
+
+ ~KeepAliveRegistrar() {
+ for (int i = _keep_alive.length() - 1; i >= 0; --i) {
+ ConstantPool* cp = _keep_alive.at(i);
+ int idx = _thread->metadata_handles()->find_from_end(cp);
+ assert(idx > 0, "Must be in the list");
+ _thread->metadata_handles()->remove_at(idx);
+ }
+ }
+
+ // Register a class as 'in-use' by the thread. It's fine to register a class
+ // multiple times (though perhaps inefficient)
+ void register_class(InstanceKlass* ik) {
+ ConstantPool* cp = ik->constants();
+ _keep_alive.push(cp);
+ _thread->metadata_handles()->push(cp);
+ }
+};
+
+class KeepAliveVisitor : public HierarchyVisitor<KeepAliveVisitor> {
+ private:
+ KeepAliveRegistrar* _registrar;
+
+ public:
+ KeepAliveVisitor(KeepAliveRegistrar* registrar) : _registrar(registrar) {}
+
+ void* new_node_data(InstanceKlass* cls) { return NULL; }
+ void free_node_data(void* data) { return; }
+
+ bool visit() {
+ _registrar->register_class(current_class());
+ return true;
+ }
+};
+
+// A method family contains a set of all methods that implement a single
+// language-level method. Because of erasure, these methods may have different
+// signatures. As members of the set are collected while walking over the
+// hierarchy, they are tagged with a qualification state. The qualification
+// state for an erased method is set to disqualified if there exists a path
+// from the root of hierarchy to the method that contains an interleaving
+// language-equivalent method defined in an interface.
+class MethodFamily : public ResourceObj {
+ private:
+
+ generic::MethodDescriptor* _descriptor; // language-level description
+ GrowableArray<Pair<Method*,QualifiedState> > _members;
+ ResourceHashtable<Method*, int> _member_index;
+
+ Method* _selected_target; // Filled in later, if a unique target exists
+ Symbol* _exception_message; // If no unique target is found
+
+ bool contains_method(Method* method) {
+ int* lookup = _member_index.get(method);
+ return lookup != NULL;
+ }
+
+ void add_method(Method* method, QualifiedState state) {
+ Pair<Method*,QualifiedState> entry(method, state);
+ _member_index.put(method, _members.length());
+ _members.append(entry);
+ }
+
+ void disqualify_method(Method* method) {
+ int* index = _member_index.get(method);
+ assert(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
+ _members.at(*index).second = DISQUALIFIED;
+ }
+
+ Symbol* generate_no_defaults_message(TRAPS) const;
+ Symbol* generate_abstract_method_message(Method* method, TRAPS) const;
+ Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
+
+ public:
+
+ MethodFamily(generic::MethodDescriptor* canonical_desc)
+ : _descriptor(canonical_desc), _selected_target(NULL),
+ _exception_message(NULL) {}
+
+ generic::MethodDescriptor* descriptor() const { return _descriptor; }
+
+ bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) {
+ return descriptor()->covariant_match(md, ctx);
+ }
+
+ void set_target_if_empty(Method* m) {
+ if (_selected_target == NULL && !m->is_overpass()) {
+ _selected_target = m;
+ }
+ }
+
+ void record_qualified_method(Method* m) {
+ // If the method already exists in the set as qualified, this operation is
+ // redundant. If it already exists as disqualified, then we leave it as
+ // disqualfied. Thus we only add to the set if it's not already in the
+ // set.
+ if (!contains_method(m)) {
+ add_method(m, QUALIFIED);
+ }
+ }
+
+ void record_disqualified_method(Method* m) {
+ // If not in the set, add it as disqualified. If it's already in the set,
+ // then set the state to disqualified no matter what the previous state was.
+ if (!contains_method(m)) {
+ add_method(m, DISQUALIFIED);
+ } else {
+ disqualify_method(m);
+ }
+ }
+
+ bool has_target() const { return _selected_target != NULL; }
+ bool throws_exception() { return _exception_message != NULL; }
+
+ Method* get_selected_target() { return _selected_target; }
+ Symbol* get_exception_message() { return _exception_message; }
+
+ // Either sets the target or the exception error message
+ void determine_target(InstanceKlass* root, TRAPS) {
+ if (has_target() || throws_exception()) {
+ return;
+ }
+
+ GrowableArray<Method*> qualified_methods;
+ for (int i = 0; i < _members.length(); ++i) {
+ Pair<Method*,QualifiedState> entry = _members.at(i);
+ if (entry.second == QUALIFIED) {
+ qualified_methods.append(entry.first);
+ }
+ }
+
+ if (qualified_methods.length() == 0) {
+ _exception_message = generate_no_defaults_message(CHECK);
+ } else if (qualified_methods.length() == 1) {
+ Method* method = qualified_methods.at(0);
+ if (method->is_abstract()) {
+ _exception_message = generate_abstract_method_message(method, CHECK);
+ } else {
+ _selected_target = qualified_methods.at(0);
+ }
+ } else {
+ _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
+ }
+
+ assert((has_target() ^ throws_exception()) == 1,
+ "One and only one must be true");
+ }
+
+ bool contains_signature(Symbol* query) {
+ for (int i = 0; i < _members.length(); ++i) {
+ if (query == _members.at(i).first->signature()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const {
+ print_on(str, 0);
+ }
+
+ void print_on(outputStream* str, int indent) const {
+ streamIndentor si(str, indent * 2);
+
+ generic::Context ctx(NULL); // empty, as _descriptor already canonicalized
+ TempNewSymbol family = descriptor()->reify_signature(&ctx, Thread::current());
+ str->indent().print_cr("Logical Method %s:", family->as_C_string());
+
+ streamIndentor si2(str);
+ for (int i = 0; i < _members.length(); ++i) {
+ str->indent();
+ print_method(str, _members.at(i).first);
+ if (_members.at(i).second == DISQUALIFIED) {
+ str->print(" (disqualified)");
+ }
+ str->print_cr("");
+ }
+
+ if (_selected_target != NULL) {
+ print_selected(str, 1);
+ }
+ }
+
+ void print_selected(outputStream* str, int indent) const {
+ assert(has_target(), "Should be called otherwise");
+ streamIndentor si(str, indent * 2);
+ str->indent().print("Selected method: ");
+ print_method(str, _selected_target);
+ str->print_cr("");
+ }
+
+ void print_exception(outputStream* str, int indent) {
+ assert(throws_exception(), "Should be called otherwise");
+ streamIndentor si(str, indent * 2);
+ str->indent().print_cr("%s", _exception_message->as_C_string());
+ }
+#endif // ndef PRODUCT
+};
+
+Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
+ return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
+}
+
+Symbol* MethodFamily::generate_abstract_method_message(Method* method, TRAPS) const {
+ Symbol* klass = method->klass_name();
+ Symbol* name = method->name();
+ Symbol* sig = method->signature();
+ stringStream ss;
+ ss.print("Method ");
+ ss.write((const char*)klass->bytes(), klass->utf8_length());
+ ss.print(".");
+ ss.write((const char*)name->bytes(), name->utf8_length());
+ ss.write((const char*)sig->bytes(), sig->utf8_length());
+ ss.print(" is abstract");
+ return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
+}
+
+Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
+ stringStream ss;
+ ss.print("Conflicting default methods:");
+ for (int i = 0; i < methods->length(); ++i) {
+ Method* method = methods->at(i);
+ Symbol* klass = method->klass_name();
+ Symbol* name = method->name();
+ ss.print(" ");
+ ss.write((const char*)klass->bytes(), klass->utf8_length());
+ ss.print(".");
+ ss.write((const char*)name->bytes(), name->utf8_length());
+ }
+ return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
+}
+
+class StateRestorer;
+
+// StatefulMethodFamily is a wrapper around MethodFamily that maintains the
+// qualification state during hierarchy visitation, and applies that state
+// when adding members to the MethodFamily.
+class StatefulMethodFamily : public ResourceObj {
+ friend class StateRestorer;
+ private:
+ MethodFamily* _method;
+ QualifiedState _qualification_state;
+
+ void set_qualification_state(QualifiedState state) {
+ _qualification_state = state;
+ }
+
+ public:
+ StatefulMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) {
+ _method = new MethodFamily(md->canonicalize(ctx));
+ _qualification_state = QUALIFIED;
+ }
+
+ void set_target_if_empty(Method* m) { _method->set_target_if_empty(m); }
+
+ MethodFamily* get_method_family() { return _method; }
+
+ bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) {
+ return _method->descriptor_matches(md, ctx);
+ }
+
+ StateRestorer* record_method_and_dq_further(Method* mo);
+};
+
+class StateRestorer : public PseudoScopeMark {
+ private:
+ StatefulMethodFamily* _method;
+ QualifiedState _state_to_restore;
+ public:
+ StateRestorer(StatefulMethodFamily* dm, QualifiedState state)
+ : _method(dm), _state_to_restore(state) {}
+ ~StateRestorer() { destroy(); }
+ void restore_state() { _method->set_qualification_state(_state_to_restore); }
+ virtual void destroy() { restore_state(); }
+};
+
+StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
+ StateRestorer* mark = new StateRestorer(this, _qualification_state);
+ if (_qualification_state == QUALIFIED) {
+ _method->record_qualified_method(mo);
+ } else {
+ _method->record_disqualified_method(mo);
+ }
+ // Everything found "above"??? this method in the hierarchy walk is set to
+ // disqualified
+ set_qualification_state(DISQUALIFIED);
+ return mark;
+}
+
+class StatefulMethodFamilies : public ResourceObj {
+ private:
+ GrowableArray<StatefulMethodFamily*> _methods;
+
+ public:
+ StatefulMethodFamily* find_matching(
+ generic::MethodDescriptor* md, generic::Context* ctx) {
+ for (int i = 0; i < _methods.length(); ++i) {
+ StatefulMethodFamily* existing = _methods.at(i);
+ if (existing->descriptor_matches(md, ctx)) {
+ return existing;
+ }
+ }
+ return NULL;
+ }
+
+ StatefulMethodFamily* find_matching_or_create(
+ generic::MethodDescriptor* md, generic::Context* ctx) {
+ StatefulMethodFamily* method = find_matching(md, ctx);
+ if (method == NULL) {
+ method = new StatefulMethodFamily(md, ctx);
+ _methods.append(method);
+ }
+ return method;
+ }
+
+ void extract_families_into(GrowableArray<MethodFamily*>* array) {
+ for (int i = 0; i < _methods.length(); ++i) {
+ array->append(_methods.at(i)->get_method_family());
+ }
+ }
+};
+
+// Represents a location corresponding to a vtable slot for methods that
+// neither the class nor any of it's ancestors provide an implementaion.
+// Default methods may be present to fill this slot.
+class EmptyVtableSlot : public ResourceObj {
+ private:
+ Symbol* _name;
+ Symbol* _signature;
+ int _size_of_parameters;
+ MethodFamily* _binding;
+
+ public:
+ EmptyVtableSlot(Method* method)
+ : _name(method->name()), _signature(method->signature()),
+ _size_of_parameters(method->size_of_parameters()), _binding(NULL) {}
+
+ Symbol* name() const { return _name; }
+ Symbol* signature() const { return _signature; }
+ int size_of_parameters() const { return _size_of_parameters; }
+
+ void bind_family(MethodFamily* lm) { _binding = lm; }
+ bool is_bound() { return _binding != NULL; }
+ MethodFamily* get_binding() { return _binding; }
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const {
+ print_slot(str, name(), signature());
+ }
+#endif // ndef PRODUCT
+};
+
+static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
+ InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
+
+ assert(klass != NULL, "Must be valid class");
+
+ GrowableArray<EmptyVtableSlot*>* slots = new GrowableArray<EmptyVtableSlot*>();
+
+ // All miranda methods are obvious candidates
+ for (int i = 0; i < mirandas->length(); ++i) {
+ EmptyVtableSlot* slot = new EmptyVtableSlot(mirandas->at(i));
+ slots->append(slot);
+ }
+
+ // Also any overpasses in our superclasses, that we haven't implemented.
+ // (can't use the vtable because it is not guaranteed to be initialized yet)
+ InstanceKlass* super = klass->java_super();
+ while (super != NULL) {
+ for (int i = 0; i < super->methods()->length(); ++i) {
+ Method* m = super->methods()->at(i);
+ if (m->is_overpass()) {
+ // m is a method that would have been a miranda if not for the
+ // default method processing that occurred on behalf of our superclass,
+ // so it's a method we want to re-examine in this new context. That is,
+ // unless we have a real implementation of it in the current class.
+ Method* impl = klass->lookup_method(m->name(), m->signature());
+ if (impl == NULL || impl->is_overpass()) {
+ slots->append(new EmptyVtableSlot(m));
+ }
+ }
+ }
+ super = super->java_super();
+ }
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr("Slots that need filling:");
+ streamIndentor si(tty);
+ for (int i = 0; i < slots->length(); ++i) {
+ tty->indent();
+ slots->at(i)->print_on(tty);
+ tty->print_cr("");
+ }
+ }
+#endif // ndef PRODUCT
+ return slots;
+}
+
+// Iterates over the type hierarchy looking for all methods with a specific
+// method name. The result of this is a set of method families each of
+// which is populated with a set of methods that implement the same
+// language-level signature.
+class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
+ private:
+ // Context data
+ Thread* THREAD;
+ generic::DescriptorCache* _cache;
+ Symbol* _method_name;
+ generic::Context* _ctx;
+ StatefulMethodFamilies _families;
+
+ public:
+
+ FindMethodsByName(generic::DescriptorCache* cache, Symbol* name,
+ generic::Context* ctx, Thread* thread) :
+ _cache(cache), _method_name(name), _ctx(ctx), THREAD(thread) {}
+
+ void get_discovered_families(GrowableArray<MethodFamily*>* methods) {
+ _families.extract_families_into(methods);
+ }
+
+ void* new_node_data(InstanceKlass* cls) { return new PseudoScope(); }
+ void free_node_data(void* node_data) {
+ PseudoScope::cast(node_data)->destroy();
+ }
+
+ bool visit() {
+ PseudoScope* scope = PseudoScope::cast(current_data());
+ InstanceKlass* klass = current_class();
+ InstanceKlass* sub = current_depth() > 0 ? class_at_depth(1) : NULL;
+
+ ContextMark* cm = new ContextMark(_ctx->mark());
+ scope->add_mark(cm); // will restore context when scope is freed
+
+ _ctx->apply_type_arguments(sub, klass, THREAD);
+
+ int start, end = 0;
+ start = klass->find_method_by_name(_method_name, &end);
+ if (start != -1) {
+ for (int i = start; i < end; ++i) {
+ Method* m = klass->methods()->at(i);
+ // This gets the method's parameter list with its generic type
+ // parameters resolved
+ generic::MethodDescriptor* md = _cache->descriptor_for(m, THREAD);
+
+ // Find all methods on this hierarchy that match this method
+ // (name, signature). This class collects other families of this
+ // method name.
+ StatefulMethodFamily* family =
+ _families.find_matching_or_create(md, _ctx);
+
+ if (klass->is_interface()) {
+ // ???
+ StateRestorer* restorer = family->record_method_and_dq_further(m);
+ scope->add_mark(restorer);
+ } else {
+ // This is the rule that methods in classes "win" (bad word) over
+ // methods in interfaces. This works because of single inheritance
+ family->set_target_if_empty(m);
+ }
+ }
+ }
+ return true;
+ }
+};
+
+#ifndef PRODUCT
+static void print_families(
+ GrowableArray<MethodFamily*>* methods, Symbol* match) {
+ streamIndentor si(tty, 4);
+ if (methods->length() == 0) {
+ tty->indent();
+ tty->print_cr("No Logical Method found");
+ }
+ for (int i = 0; i < methods->length(); ++i) {
+ tty->indent();
+ MethodFamily* lm = methods->at(i);
+ if (lm->contains_signature(match)) {
+ tty->print_cr("<Matching>");
+ } else {
+ tty->print_cr("<Non-Matching>");
+ }
+ lm->print_on(tty, 1);
+ }
+}
+#endif // ndef PRODUCT
+
+static void merge_in_new_methods(InstanceKlass* klass,
+ GrowableArray<Method*>* new_methods, TRAPS);
+static void create_overpasses(
+ GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
+
+// This is the guts of the default methods implementation. This is called just
+// after the classfile has been parsed if some ancestor has default methods.
+//
+// First if finds any name/signature slots that need any implementation (either
+// because they are miranda or a superclass's implementation is an overpass
+// itself). For each slot, iterate over the hierarchy, using generic signature
+// information to partition any methods that match the name into method families
+// where each family contains methods whose signatures are equivalent at the
+// language level (i.e., their reified parameters match and return values are
+// covariant). Check those sets to see if they contain a signature that matches
+// the slot we're looking at (if we're lucky, there might be other empty slots
+// that we can fill using the same analysis).
+//
+// For each slot filled, we generate an overpass method that either calls the
+// unique default method candidate using invokespecial, or throws an exception
+// (in the case of no default method candidates, or more than one valid
+// candidate). These methods are then added to the class's method list. If
+// the method set we're using contains methods (qualified or not) with a
+// different runtime signature than the method we're creating, then we have to
+// create bridges with those signatures too.
+void DefaultMethods::generate_default_methods(
+ InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
+
+ // This resource mark is the bound for all memory allocation that takes
+ // place during default method processing. After this goes out of scope,
+ // all (Resource) objects' memory will be reclaimed. Be careful if adding an
+ // embedded resource mark under here as that memory can't be used outside
+ // whatever scope it's in.
+ ResourceMark rm(THREAD);
+
+ generic::DescriptorCache cache;
+
+ // Keep entire hierarchy alive for the duration of the computation
+ KeepAliveRegistrar keepAlive(THREAD);
+ KeepAliveVisitor loadKeepAlive(&keepAlive);
+ loadKeepAlive.run(klass);
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ ResourceMark rm; // be careful with these!
+ tty->print_cr("Class %s requires default method processing",
+ klass->name()->as_klass_external_name());
+ PrintHierarchy printer;
+ printer.run(klass);
+ }
+#endif // ndef PRODUCT
+
+ GrowableArray<EmptyVtableSlot*>* empty_slots =
+ find_empty_vtable_slots(klass, mirandas, CHECK);
+
+ for (int i = 0; i < empty_slots->length(); ++i) {
+ EmptyVtableSlot* slot = empty_slots->at(i);
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ streamIndentor si(tty, 2);
+ tty->indent().print("Looking for default methods for slot ");
+ slot->print_on(tty);
+ tty->print_cr("");
+ }
+#endif // ndef PRODUCT
+ if (slot->is_bound()) {
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ streamIndentor si(tty, 4);
+ tty->indent().print_cr("Already bound to logical method:");
+ slot->get_binding()->print_on(tty, 1);
+ }
+#endif // ndef PRODUCT
+ continue; // covered by previous processing
+ }
+
+ generic::Context ctx(&cache);
+ FindMethodsByName visitor(&cache, slot->name(), &ctx, CHECK);
+ visitor.run(klass);
+
+ GrowableArray<MethodFamily*> discovered_families;
+ visitor.get_discovered_families(&discovered_families);
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ print_families(&discovered_families, slot->signature());
+ }
+#endif // ndef PRODUCT
+
+ // Find and populate any other slots that match the discovered families
+ for (int j = i; j < empty_slots->length(); ++j) {
+ EmptyVtableSlot* open_slot = empty_slots->at(j);
+
+ if (slot->name() == open_slot->name()) {
+ for (int k = 0; k < discovered_families.length(); ++k) {
+ MethodFamily* lm = discovered_families.at(k);
+
+ if (lm->contains_signature(open_slot->signature())) {
+ lm->determine_target(klass, CHECK);
+ open_slot->bind_family(lm);
+ }
+ }
+ }
+ }
+ }
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr("Creating overpasses...");
+ }
+#endif // ndef PRODUCT
+
+ create_overpasses(empty_slots, klass, CHECK);
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr("Default method processing complete");
+ }
+#endif // ndef PRODUCT
+}
+
+
+/**
+ * Generic analysis was used upon interface '_target' and found a unique
+ * default method candidate with generic signature '_method_desc'. This
+ * method is only viable if it would also be in the set of default method
+ * candidates if we ran a full analysis on the current class.
+ *
+ * The only reason that the method would not be in the set of candidates for
+ * the current class is if that there's another covariantly matching method
+ * which is "more specific" than the found method -- i.e., one could find a
+ * path in the interface hierarchy in which the matching method appears
+ * before we get to '_target'.
+ *
+ * In order to determine this, we examine all of the implemented
+ * interfaces. If we find path that leads to the '_target' interface, then
+ * we examine that path to see if there are any methods that would shadow
+ * the selected method along that path.
+ */
+class ShadowChecker : public HierarchyVisitor<ShadowChecker> {
+ private:
+ generic::DescriptorCache* _cache;
+ Thread* THREAD;
+
+ InstanceKlass* _target;
+
+ Symbol* _method_name;
+ InstanceKlass* _method_holder;
+ generic::MethodDescriptor* _method_desc;
+ bool _found_shadow;
+
+ bool path_has_shadow() {
+ generic::Context ctx(_cache);
+
+ for (int i = current_depth() - 1; i > 0; --i) {
+ InstanceKlass* ik = class_at_depth(i);
+ InstanceKlass* sub = class_at_depth(i + 1);
+ ctx.apply_type_arguments(sub, ik, THREAD);
+
+ if (ik->is_interface()) {
+ int end;
+ int start = ik->find_method_by_name(_method_name, &end);
+ if (start != -1) {
+ for (int j = start; j < end; ++j) {
+ Method* mo = ik->methods()->at(j);
+ generic::MethodDescriptor* md = _cache->descriptor_for(mo, THREAD);
+ if (_method_desc->covariant_match(md, &ctx)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public:
+
+ ShadowChecker(generic::DescriptorCache* cache, Thread* thread,
+ Symbol* name, InstanceKlass* holder, generic::MethodDescriptor* desc,
+ InstanceKlass* target)
+ : _cache(cache), THREAD(thread), _method_name(name), _method_holder(holder),
+ _method_desc(desc), _target(target), _found_shadow(false) {}
+
+ void* new_node_data(InstanceKlass* cls) { return NULL; }
+ void free_node_data(void* data) { return; }
+
+ bool visit() {
+ InstanceKlass* ik = current_class();
+ if (ik == _target && current_depth() == 1) {
+ return false; // This was the specified super -- no need to search it
+ }
+ if (ik == _method_holder || ik == _target) {
+ // We found a path that should be examined to see if it shadows _method
+ if (path_has_shadow()) {
+ _found_shadow = true;
+ cancel_iteration();
+ }
+ return false; // no need to continue up hierarchy
+ }
+ return true;
+ }
+
+ bool found_shadow() { return _found_shadow; }
+};
+
+// This is called during linktime when we find an invokespecial call that
+// refers to a direct superinterface. It indicates that we should find the
+// default method in the hierarchy of that superinterface, and if that method
+// would have been a candidate from the point of view of 'this' class, then we
+// return that method.
+Method* DefaultMethods::find_super_default(
+ Klass* cls, Klass* super, Symbol* method_name, Symbol* sig, TRAPS) {
+
+ ResourceMark rm(THREAD);
+
+ assert(cls != NULL && super != NULL, "Need real classes");
+
+ InstanceKlass* current_class = InstanceKlass::cast(cls);
+ InstanceKlass* direction = InstanceKlass::cast(super);
+
+ // Keep entire hierarchy alive for the duration of the computation
+ KeepAliveRegistrar keepAlive(THREAD);
+ KeepAliveVisitor loadKeepAlive(&keepAlive);
+ loadKeepAlive.run(current_class);
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr("Finding super default method %s.%s%s from %s",
+ direction->name()->as_C_string(),
+ method_name->as_C_string(), sig->as_C_string(),
+ current_class->name()->as_C_string());
+ }
+#endif // ndef PRODUCT
+
+ if (!direction->is_interface()) {
+ // We should not be here
+ return NULL;
+ }
+
+ generic::DescriptorCache cache;
+ generic::Context ctx(&cache);
+
+ // Prime the initial generic context for current -> direction
+ ctx.apply_type_arguments(current_class, direction, CHECK_NULL);
+
+ FindMethodsByName visitor(&cache, method_name, &ctx, CHECK_NULL);
+ visitor.run(direction);
+
+ GrowableArray<MethodFamily*> families;
+ visitor.get_discovered_families(&families);
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ print_families(&families, sig);
+ }
+#endif // ndef PRODUCT
+
+ MethodFamily* selected_family = NULL;
+
+ for (int i = 0; i < families.length(); ++i) {
+ MethodFamily* lm = families.at(i);
+ if (lm->contains_signature(sig)) {
+ lm->determine_target(current_class, CHECK_NULL);
+ selected_family = lm;
+ }
+ }
+
+ if (selected_family->has_target()) {
+ Method* target = selected_family->get_selected_target();
+ InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
+
+ // Verify that the identified method is valid from the context of
+ // the current class
+ ShadowChecker checker(&cache, THREAD, target->name(),
+ holder, selected_family->descriptor(), direction);
+ checker.run(current_class);
+
+ if (checker.found_shadow()) {
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr(" Only candidate found was shadowed.");
+ }
+#endif // ndef PRODUCT
+ THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+ "Accessible default method not found", NULL);
+ } else {
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print(" Returning ");
+ print_method(tty, target, true);
+ tty->print_cr("");
+ }
+#endif // ndef PRODUCT
+ return target;
+ }
+ } else {
+ assert(selected_family->throws_exception(), "must have target or throw");
+ THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+ selected_family->get_exception_message()->as_C_string(), NULL);
+ }
+}
+
+
+static int assemble_redirect(
+ BytecodeConstantPool* cp, BytecodeBuffer* buffer,
+ Symbol* incoming, Method* target, TRAPS) {
+
+ BytecodeAssembler assem(buffer, cp);
+
+ SignatureStream in(incoming, true);
+ SignatureStream out(target->signature(), true);
+ u2 parameter_count = 0;
+
+ assem.aload(parameter_count++); // load 'this'
+
+ while (!in.at_return_type()) {
+ assert(!out.at_return_type(), "Parameter counts do not match");
+ BasicType bt = in.type();
+ assert(out.type() == bt, "Parameter types are not compatible");
+ assem.load(bt, parameter_count);
+ if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
+ assem.checkcast(out.as_symbol(THREAD));
+ } else if (bt == T_LONG || bt == T_DOUBLE) {
+ ++parameter_count; // longs and doubles use two slots
+ }
+ ++parameter_count;
+ in.next();
+ out.next();
+ }
+ assert(out.at_return_type(), "Parameter counts do not match");
+ assert(in.type() == out.type(), "Return types are not compatible");
+
+ if (parameter_count == 1 && (in.type() == T_LONG || in.type() == T_DOUBLE)) {
+ ++parameter_count; // need room for return value
+ }
+ if (target->method_holder()->is_interface()) {
+ assem.invokespecial(target);
+ } else {
+ assem.invokevirtual(target);
+ }
+
+ if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
+ assem.checkcast(in.as_symbol(THREAD));
+ }
+ assem._return(in.type());
+ return parameter_count;
+}
+
+static int assemble_abstract_method_error(
+ BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* message, TRAPS) {
+
+ Symbol* errorName = vmSymbols::java_lang_AbstractMethodError();
+ Symbol* init = vmSymbols::object_initializer_name();
+ Symbol* sig = vmSymbols::string_void_signature();
+
+ BytecodeAssembler assem(buffer, cp);
+
+ assem._new(errorName);
+ assem.dup();
+ assem.load_string(message);
+ assem.invokespecial(errorName, init, sig);
+ assem.athrow();
+
+ return 3; // max stack size: [ exception, exception, string ]
+}
+
+static Method* new_method(
+ BytecodeConstantPool* cp, BytecodeBuffer* bytecodes, Symbol* name,
+ Symbol* sig, AccessFlags flags, int max_stack, int params,
+ ConstMethod::MethodType mt, TRAPS) {
+
+ address code_start = static_cast<address>(bytecodes->adr_at(0));
+ int code_length = bytecodes->length();
+
+ Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
+ code_length, flags, 0, 0, 0, 0, mt, CHECK_NULL);
+
+ m->set_constants(NULL); // This will get filled in later
+ m->set_name_index(cp->utf8(name));
+ m->set_signature_index(cp->utf8(sig));
+ m->set_generic_signature_index(0);
+#ifdef CC_INTERP
+ ResultTypeFinder rtf(sig);
+ m->set_result_index(rtf.type());
+#endif
+ m->set_size_of_parameters(params);
+ m->set_max_stack(max_stack);
+ m->set_max_locals(params);
+ m->constMethod()->set_stackmap_data(NULL);
+ m->set_code(code_start);
+ m->set_force_inline(true);
+
+ return m;
+}
+
+static void switchover_constant_pool(BytecodeConstantPool* bpool,
+ InstanceKlass* klass, GrowableArray<Method*>* new_methods, TRAPS) {
+
+ if (new_methods->length() > 0) {
+ ConstantPool* cp = bpool->create_constant_pool(CHECK);
+ if (cp != klass->constants()) {
+ klass->class_loader_data()->add_to_deallocate_list(klass->constants());
+ klass->set_constants(cp);
+ cp->set_pool_holder(klass);
+
+ for (int i = 0; i < new_methods->length(); ++i) {
+ new_methods->at(i)->set_constants(cp);
+ }
+ for (int i = 0; i < klass->methods()->length(); ++i) {
+ Method* mo = klass->methods()->at(i);
+ mo->set_constants(cp);
+ }
+ }
+ }
+}
+
+// A "bridge" is a method created by javac to bridge the gap between
+// an implementation and a generically-compatible, but different, signature.
+// Bridges have actual bytecode implementation in classfiles.
+// An "overpass", on the other hand, performs the same function as a bridge
+// but does not occur in a classfile; the VM creates overpass itself,
+// when it needs a path to get from a call site to an default method, and
+// a bridge doesn't exist.
+static void create_overpasses(
+ GrowableArray<EmptyVtableSlot*>* slots,
+ InstanceKlass* klass, TRAPS) {
+
+ GrowableArray<Method*> overpasses;
+ BytecodeConstantPool bpool(klass->constants());
+
+ for (int i = 0; i < slots->length(); ++i) {
+ EmptyVtableSlot* slot = slots->at(i);
+
+ if (slot->is_bound()) {
+ MethodFamily* method = slot->get_binding();
+ int max_stack = 0;
+ BytecodeBuffer buffer;
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print("for slot: ");
+ slot->print_on(tty);
+ tty->print_cr("");
+ if (method->has_target()) {
+ method->print_selected(tty, 1);
+ } else {
+ method->print_exception(tty, 1);
+ }
+ }
+#endif // ndef PRODUCT
+ if (method->has_target()) {
+ Method* selected = method->get_selected_target();
+ max_stack = assemble_redirect(
+ &bpool, &buffer, slot->signature(), selected, CHECK);
+ } else if (method->throws_exception()) {
+ max_stack = assemble_abstract_method_error(
+ &bpool, &buffer, method->get_exception_message(), CHECK);
+ }
+ AccessFlags flags = accessFlags_from(
+ JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
+ Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
+ flags, max_stack, slot->size_of_parameters(),
+ ConstMethod::OVERPASS, CHECK);
+ if (m != NULL) {
+ overpasses.push(m);
+ }
+ }
+ }
+
+#ifndef PRODUCT
+ if (TraceDefaultMethods) {
+ tty->print_cr("Created %d overpass methods", overpasses.length());
+ }
+#endif // ndef PRODUCT
+
+ switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
+ merge_in_new_methods(klass, &overpasses, CHECK);
+}
+
+static void sort_methods(GrowableArray<Method*>* methods) {
+ // Note that this must sort using the same key as is used for sorting
+ // methods in InstanceKlass.
+ bool sorted = true;
+ for (int i = methods->length() - 1; i > 0; --i) {
+ for (int j = 0; j < i; ++j) {
+ Method* m1 = methods->at(j);
+ Method* m2 = methods->at(j + 1);
+ if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
+ methods->at_put(j, m2);
+ methods->at_put(j + 1, m1);
+ sorted = false;
+ }
+ }
+ if (sorted) break;
+ sorted = true;
+ }
+#ifdef ASSERT
+ uintptr_t prev = 0;
+ for (int i = 0; i < methods->length(); ++i) {
+ Method* mh = methods->at(i);
+ uintptr_t nv = (uintptr_t)mh->name();
+ assert(nv >= prev, "Incorrect overpass method ordering");
+ prev = nv;
+ }
+#endif
+}
+
+static void merge_in_new_methods(InstanceKlass* klass,
+ GrowableArray<Method*>* new_methods, TRAPS) {
+
+ enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
+
+ Array<AnnotationArray*>* original_annots[NUM_ARRAYS];
+
+ Array<Method*>* original_methods = klass->methods();
+ Annotations* annots = klass->annotations();
+ original_annots[ANNOTATIONS] = annots->methods_annotations();
+ original_annots[PARAMETERS] = annots->methods_parameter_annotations();
+ original_annots[DEFAULTS] = annots->methods_default_annotations();
+
+ Array<int>* original_ordering = klass->method_ordering();
+ Array<int>* merged_ordering = Universe::the_empty_int_array();
+
+ int new_size = klass->methods()->length() + new_methods->length();
+
+ Array<AnnotationArray*>* merged_annots[NUM_ARRAYS];
+
+ Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
+ klass->class_loader_data(), new_size, NULL, CHECK);
+ for (int i = 0; i < NUM_ARRAYS; ++i) {
+ if (original_annots[i] != NULL) {
+ merged_annots[i] = MetadataFactory::new_array<AnnotationArray*>(
+ klass->class_loader_data(), new_size, CHECK);
+ } else {
+ merged_annots[i] = NULL;
+ }
+ }
+ if (original_ordering != NULL && original_ordering->length() > 0) {
+ merged_ordering = MetadataFactory::new_array<int>(
+ klass->class_loader_data(), new_size, CHECK);
+ }
+ int method_order_index = klass->methods()->length();
+
+ sort_methods(new_methods);
+
+ // Perform grand merge of existing methods and new methods
+ int orig_idx = 0;
+ int new_idx = 0;
+
+ for (int i = 0; i < new_size; ++i) {
+ Method* orig_method = NULL;
+ Method* new_method = NULL;
+ if (orig_idx < original_methods->length()) {
+ orig_method = original_methods->at(orig_idx);
+ }
+ if (new_idx < new_methods->length()) {
+ new_method = new_methods->at(new_idx);
+ }
+
+ if (orig_method != NULL &&
+ (new_method == NULL || orig_method->name() < new_method->name())) {
+ merged_methods->at_put(i, orig_method);
+ original_methods->at_put(orig_idx, NULL);
+ for (int j = 0; j < NUM_ARRAYS; ++j) {
+ if (merged_annots[j] != NULL) {
+ merged_annots[j]->at_put(i, original_annots[j]->at(orig_idx));
+ original_annots[j]->at_put(orig_idx, NULL);
+ }
+ }
+ if (merged_ordering->length() > 0) {
+ merged_ordering->at_put(i, original_ordering->at(orig_idx));
+ }
+ ++orig_idx;
+ } else {
+ merged_methods->at_put(i, new_method);
+ if (merged_ordering->length() > 0) {
+ merged_ordering->at_put(i, method_order_index++);
+ }
+ ++new_idx;
+ }
+ // update idnum for new location
+ merged_methods->at(i)->set_method_idnum(i);
+ }
+
+ // Verify correct order
+#ifdef ASSERT
+ uintptr_t prev = 0;
+ for (int i = 0; i < merged_methods->length(); ++i) {
+ Method* mo = merged_methods->at(i);
+ uintptr_t nv = (uintptr_t)mo->name();
+ assert(nv >= prev, "Incorrect method ordering");
+ prev = nv;
+ }
+#endif
+
+ // Replace klass methods with new merged lists
+ klass->set_methods(merged_methods);
+ annots->set_methods_annotations(merged_annots[ANNOTATIONS]);
+ annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]);
+ annots->set_methods_default_annotations(merged_annots[DEFAULTS]);
+
+ ClassLoaderData* cld = klass->class_loader_data();
+ MetadataFactory::free_array(cld, original_methods);
+ for (int i = 0; i < NUM_ARRAYS; ++i) {
+ MetadataFactory::free_array(cld, original_annots[i]);
+ }
+ if (original_ordering->length() > 0) {
+ klass->set_method_ordering(merged_ordering);
+ MetadataFactory::free_array(cld, original_ordering);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/defaultMethods.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
+#define SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
+
+#include "runtime/handles.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/exceptions.hpp"
+
+class InstanceKlass;
+class Symbol;
+class Method;
+
+class DefaultMethods : AllStatic {
+ public:
+
+ // Analyzes class and determines which default methods are inherited
+ // from interfaces (and has no other implementation). For each method
+ // (and each different signature the method could have), create an
+ // "overpass" method that is an instance method that redirects to the
+ // default method. Overpass methods are added to the methods lists for
+ // the class.
+ static void generate_default_methods(
+ InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS);
+
+
+ // Called during linking when an invokespecial to an direct interface
+ // method is found. Selects and returns a method if there is a unique
+ // default method in the 'super_iface' part of the hierarchy which is
+ // also a candidate default for 'this_klass'. Otherwise throws an AME.
+ static Method* find_super_default(
+ Klass* this_klass, Klass* super_iface,
+ Symbol* method_name, Symbol* method_sig, TRAPS);
+};
+
+#endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/genericSignatures.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,1272 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "classfile/genericSignatures.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "memory/resourceArea.hpp"
+
+namespace generic {
+
+// Helper class for parsing the generic signature Symbol in klass and methods
+class DescriptorStream : public ResourceObj {
+ private:
+ Symbol* _symbol;
+ int _offset;
+ int _mark;
+ const char* _parse_error;
+
+ void set_parse_error(const char* error) {
+ assert(error != NULL, "Can't set NULL error string");
+ _parse_error = error;
+ }
+
+ public:
+ DescriptorStream(Symbol* sym)
+ : _symbol(sym), _offset(0), _mark(-1), _parse_error(NULL) {}
+
+ const char* parse_error() const {
+ return _parse_error;
+ }
+
+ bool at_end() { return _offset >= _symbol->utf8_length(); }
+
+ char peek() {
+ if (at_end()) {
+ set_parse_error("Peeking past end of signature");
+ return '\0';
+ } else {
+ return _symbol->byte_at(_offset);
+ }
+ }
+
+ char read() {
+ if (at_end()) {
+ set_parse_error("Reading past end of signature");
+ return '\0';
+ } else {
+ return _symbol->byte_at(_offset++);
+ }
+ }
+
+ void read(char expected) {
+ char c = read();
+ assert_char(c, expected, 0);
+ }
+
+ void assert_char(char c, char expected, int pos = -1) {
+ if (c != expected) {
+ const char* fmt = "Parse error at %d: expected %c but got %c";
+ size_t len = strlen(fmt) + 5;
+ char* buffer = NEW_RESOURCE_ARRAY(char, len);
+ jio_snprintf(buffer, len, fmt, _offset + pos, expected, c);
+ set_parse_error(buffer);
+ }
+ }
+
+ void push(char c) {
+ assert(c == _symbol->byte_at(_offset - 1), "Pushing back wrong value");
+ --_offset;
+ }
+
+ void expect_end() {
+ if (!at_end()) {
+ set_parse_error("Unexpected data trailing signature");
+ }
+ }
+
+ bool has_mark() { return _mark != -1; }
+
+ void set_mark() {
+ _mark = _offset;
+ }
+
+ Identifier* identifier_from_mark() {
+ assert(has_mark(), "Mark should be set");
+ if (!has_mark()) {
+ set_parse_error("Expected mark to be set");
+ return NULL;
+ } else {
+ Identifier* id = new Identifier(_symbol, _mark, _offset - 1);
+ _mark = -1;
+ return id;
+ }
+ }
+};
+
+
+#define CHECK_FOR_PARSE_ERROR() \
+ if (STREAM->parse_error() != NULL) { \
+ if (VerifyGenericSignatures) { \
+ fatal(STREAM->parse_error()); \
+ } \
+ return NULL; \
+ } 0
+
+#define READ() STREAM->read(); CHECK_FOR_PARSE_ERROR()
+#define PEEK() STREAM->peek(); CHECK_FOR_PARSE_ERROR()
+#define PUSH(c) STREAM->push(c)
+#define EXPECT(c) STREAM->read(c); CHECK_FOR_PARSE_ERROR()
+#define EXPECTED(c, ch) STREAM->assert_char(c, ch); CHECK_FOR_PARSE_ERROR()
+#define EXPECT_END() STREAM->expect_end(); CHECK_FOR_PARSE_ERROR()
+
+#define CHECK_STREAM STREAM); CHECK_FOR_PARSE_ERROR(); (0
+
+#ifndef PRODUCT
+void Identifier::print_on(outputStream* str) const {
+ for (int i = _begin; i < _end; ++i) {
+ str->print("%c", (char)_sym->byte_at(i));
+ }
+}
+#endif // ndef PRODUCT
+
+bool Identifier::equals(Identifier* other) {
+ if (_sym == other->_sym && _begin == other->_begin && _end == other->_end) {
+ return true;
+ } else if (_end - _begin != other->_end - other->_begin) {
+ return false;
+ } else {
+ size_t len = _end - _begin;
+ char* addr = ((char*)_sym->bytes()) + _begin;
+ char* oaddr = ((char*)other->_sym->bytes()) + other->_begin;
+ return strncmp(addr, oaddr, len) == 0;
+ }
+}
+
+bool Identifier::equals(Symbol* sym) {
+ Identifier id(sym, 0, sym->utf8_length());
+ return equals(&id);
+}
+
+/**
+ * A formal type parameter may be found in the the enclosing class, but it could
+ * also come from an enclosing method or outer class, in the case of inner-outer
+ * classes or anonymous classes. For example:
+ *
+ * class Outer<T,V> {
+ * class Inner<W> {
+ * void m(T t, V v, W w);
+ * }
+ * }
+ *
+ * In this case, the type variables in m()'s signature are not all found in the
+ * immediate enclosing class (Inner). class Inner has only type parameter W,
+ * but it's outer_class field will reference Outer's descriptor which contains
+ * T & V (no outer_method in this case).
+ *
+ * If you have an anonymous class, it has both an enclosing method *and* an
+ * enclosing class where type parameters can be declared:
+ *
+ * class MOuter<T> {
+ * <V> void bar(V v) {
+ * Runnable r = new Runnable() {
+ * public void run() {}
+ * public void foo(T t, V v) { ... }
+ * };
+ * }
+ * }
+ *
+ * In this case, foo will be a member of some class, Runnable$1, which has no
+ * formal parameters itself, but has an outer_method (bar()) which provides
+ * type parameter V, and an outer class MOuter with type parameter T.
+ *
+ * It is also possible that the outer class is itself an inner class to some
+ * other class (or an anonymous class with an enclosing method), so we need to
+ * follow the outer_class/outer_method chain to it's end when looking for a
+ * type parameter.
+ */
+TypeParameter* Descriptor::find_type_parameter(Identifier* id, int* depth) {
+
+ int current_depth = 0;
+
+ MethodDescriptor* outer_method = as_method_signature();
+ ClassDescriptor* outer_class = as_class_signature();
+
+ if (outer_class == NULL) { // 'this' is a method signature; use the holder
+ outer_class = outer_method->outer_class();
+ }
+
+ while (outer_method != NULL || outer_class != NULL) {
+ if (outer_method != NULL) {
+ for (int i = 0; i < outer_method->type_parameters().length(); ++i) {
+ TypeParameter* p = outer_method->type_parameters().at(i);
+ if (p->identifier()->equals(id)) {
+ *depth = -1; // indicates this this is a method parameter
+ return p;
+ }
+ }
+ }
+ if (outer_class != NULL) {
+ for (int i = 0; i < outer_class->type_parameters().length(); ++i) {
+ TypeParameter* p = outer_class->type_parameters().at(i);
+ if (p->identifier()->equals(id)) {
+ *depth = current_depth;
+ return p;
+ }
+ }
+ outer_method = outer_class->outer_method();
+ outer_class = outer_class->outer_class();
+ ++current_depth;
+ }
+ }
+
+ if (VerifyGenericSignatures) {
+ fatal("Could not resolve identifier");
+ }
+
+ return NULL;
+}
+
+ClassDescriptor* ClassDescriptor::parse_generic_signature(Klass* klass, TRAPS) {
+ return parse_generic_signature(klass, NULL, CHECK_NULL);
+}
+
+ClassDescriptor* ClassDescriptor::parse_generic_signature(
+ Klass* klass, Symbol* original_name, TRAPS) {
+
+ InstanceKlass* ik = InstanceKlass::cast(klass);
+ Symbol* sym = ik->generic_signature();
+
+ ClassDescriptor* spec;
+
+ if (sym == NULL || (spec = ClassDescriptor::parse_generic_signature(sym)) == NULL) {
+ spec = ClassDescriptor::placeholder(ik);
+ }
+
+ u2 outer_index = get_outer_class_index(ik, CHECK_NULL);
+ if (outer_index != 0) {
+ if (original_name == NULL) {
+ original_name = ik->name();
+ }
+ Handle class_loader = Handle(THREAD, ik->class_loader());
+ Handle protection_domain = Handle(THREAD, ik->protection_domain());
+
+ Symbol* outer_name = ik->constants()->klass_name_at(outer_index);
+ Klass* outer = SystemDictionary::find(
+ outer_name, class_loader, protection_domain, CHECK_NULL);
+ if (outer == NULL && !THREAD->is_Compiler_thread()) {
+ outer = SystemDictionary::resolve_super_or_fail(original_name,
+ outer_name, class_loader, protection_domain, false, CHECK_NULL);
+ }
+
+ InstanceKlass* outer_ik;
+ ClassDescriptor* outer_spec = NULL;
+ if (outer == NULL) {
+ outer_spec = ClassDescriptor::placeholder(ik);
+ assert(false, "Outer class not loaded and not loadable from here");
+ } else {
+ outer_ik = InstanceKlass::cast(outer);
+ outer_spec = parse_generic_signature(outer, original_name, CHECK_NULL);
+ }
+ spec->set_outer_class(outer_spec);
+
+ u2 encl_method_idx = ik->enclosing_method_method_index();
+ if (encl_method_idx != 0 && outer_ik != NULL) {
+ ConstantPool* cp = ik->constants();
+ u2 name_index = cp->name_ref_index_at(encl_method_idx);
+ u2 sig_index = cp->signature_ref_index_at(encl_method_idx);
+ Symbol* name = cp->symbol_at(name_index);
+ Symbol* sig = cp->symbol_at(sig_index);
+ Method* m = outer_ik->find_method(name, sig);
+ if (m != NULL) {
+ Symbol* gsig = m->generic_signature();
+ if (gsig != NULL) {
+ MethodDescriptor* gms = MethodDescriptor::parse_generic_signature(gsig, outer_spec);
+ spec->set_outer_method(gms);
+ }
+ } else if (VerifyGenericSignatures) {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("Could not find method %s %s in class %s",
+ name->as_C_string(), sig->as_C_string(), outer_name->as_C_string());
+ fatal(ss.as_string());
+ }
+ }
+ }
+
+ spec->bind_variables_to_parameters();
+ return spec;
+}
+
+ClassDescriptor* ClassDescriptor::placeholder(InstanceKlass* klass) {
+ GrowableArray<TypeParameter*> formals;
+ GrowableArray<ClassType*> interfaces;
+ ClassType* super_type = NULL;
+
+ Klass* super_klass = klass->super();
+ if (super_klass != NULL) {
+ InstanceKlass* super = InstanceKlass::cast(super_klass);
+ super_type = ClassType::from_symbol(super->name());
+ }
+
+ for (int i = 0; i < klass->local_interfaces()->length(); ++i) {
+ InstanceKlass* iface = InstanceKlass::cast(klass->local_interfaces()->at(i));
+ interfaces.append(ClassType::from_symbol(iface->name()));
+ }
+ return new ClassDescriptor(formals, super_type, interfaces);
+}
+
+ClassDescriptor* ClassDescriptor::parse_generic_signature(Symbol* sym) {
+
+ DescriptorStream ds(sym);
+ DescriptorStream* STREAM = &ds;
+
+ GrowableArray<TypeParameter*> parameters(8);
+ char c = READ();
+ if (c == '<') {
+ c = READ();
+ while (c != '>') {
+ PUSH(c);
+ TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM);
+ parameters.append(ftp);
+ c = READ();
+ }
+ } else {
+ PUSH(c);
+ }
+
+ EXPECT('L');
+ ClassType* super = ClassType::parse_generic_signature(CHECK_STREAM);
+
+ GrowableArray<ClassType*> signatures(2);
+ while (!STREAM->at_end()) {
+ EXPECT('L');
+ ClassType* iface = ClassType::parse_generic_signature(CHECK_STREAM);
+ signatures.append(iface);
+ }
+
+ EXPECT_END();
+
+ return new ClassDescriptor(parameters, super, signatures);
+}
+
+#ifndef PRODUCT
+void ClassDescriptor::print_on(outputStream* str) const {
+ str->indent().print_cr("ClassDescriptor {");
+ {
+ streamIndentor si(str);
+ if (_type_parameters.length() > 0) {
+ str->indent().print_cr("Formals {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ _type_parameters.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ if (_super != NULL) {
+ str->indent().print_cr("Superclass: ");
+ {
+ streamIndentor si(str);
+ _super->print_on(str);
+ }
+ }
+ if (_interfaces.length() > 0) {
+ str->indent().print_cr("SuperInterfaces: {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _interfaces.length(); ++i) {
+ _interfaces.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ if (_outer_method != NULL) {
+ str->indent().print_cr("Outer Method: {");
+ {
+ streamIndentor si(str);
+ _outer_method->print_on(str);
+ }
+ str->indent().print_cr("}");
+ }
+ if (_outer_class != NULL) {
+ str->indent().print_cr("Outer Class: {");
+ {
+ streamIndentor si(str);
+ _outer_class->print_on(str);
+ }
+ str->indent().print_cr("}");
+ }
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+ClassType* ClassDescriptor::interface_desc(Symbol* sym) {
+ for (int i = 0; i < _interfaces.length(); ++i) {
+ if (_interfaces.at(i)->identifier()->equals(sym)) {
+ return _interfaces.at(i);
+ }
+ }
+ if (VerifyGenericSignatures) {
+ fatal("Did not find expected interface");
+ }
+ return NULL;
+}
+
+void ClassDescriptor::bind_variables_to_parameters() {
+ if (_outer_class != NULL) {
+ _outer_class->bind_variables_to_parameters();
+ }
+ if (_outer_method != NULL) {
+ _outer_method->bind_variables_to_parameters();
+ }
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ _type_parameters.at(i)->bind_variables_to_parameters(this, i);
+ }
+ if (_super != NULL) {
+ _super->bind_variables_to_parameters(this);
+ }
+ for (int i = 0; i < _interfaces.length(); ++i) {
+ _interfaces.at(i)->bind_variables_to_parameters(this);
+ }
+}
+
+ClassDescriptor* ClassDescriptor::canonicalize(Context* ctx) {
+
+ GrowableArray<TypeParameter*> type_params(_type_parameters.length());
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0));
+ }
+
+ ClassDescriptor* outer = _outer_class == NULL ? NULL :
+ _outer_class->canonicalize(ctx);
+
+ ClassType* super = _super == NULL ? NULL : _super->canonicalize(ctx, 0);
+
+ GrowableArray<ClassType*> interfaces(_interfaces.length());
+ for (int i = 0; i < _interfaces.length(); ++i) {
+ interfaces.append(_interfaces.at(i)->canonicalize(ctx, 0));
+ }
+
+ MethodDescriptor* md = _outer_method == NULL ? NULL :
+ _outer_method->canonicalize(ctx);
+
+ return new ClassDescriptor(type_params, super, interfaces, outer, md);
+}
+
+u2 ClassDescriptor::get_outer_class_index(InstanceKlass* klass, TRAPS) {
+ int inner_index = InstanceKlass::inner_class_inner_class_info_offset;
+ int outer_index = InstanceKlass::inner_class_outer_class_info_offset;
+ int name_offset = InstanceKlass::inner_class_inner_name_offset;
+ int next_offset = InstanceKlass::inner_class_next_offset;
+
+ if (klass->inner_classes() == NULL || klass->inner_classes()->length() == 0) {
+ // No inner class info => no declaring class
+ return 0;
+ }
+
+ Array<u2>* i_icls = klass->inner_classes();
+ ConstantPool* i_cp = klass->constants();
+ int i_length = i_icls->length();
+
+ // Find inner_klass attribute
+ for (int i = 0; i + next_offset < i_length; i += next_offset) {
+ u2 ioff = i_icls->at(i + inner_index);
+ u2 ooff = i_icls->at(i + outer_index);
+ u2 noff = i_icls->at(i + name_offset);
+ if (ioff != 0) {
+ // Check to see if the name matches the class we're looking for
+ // before attempting to find the class.
+ if (i_cp->klass_name_at_matches(klass, ioff) && ooff != 0) {
+ return ooff;
+ }
+ }
+ }
+
+ // It may be anonymous; try for that.
+ u2 encl_method_class_idx = klass->enclosing_method_class_index();
+ if (encl_method_class_idx != 0) {
+ return encl_method_class_idx;
+ }
+
+ return 0;
+}
+
+MethodDescriptor* MethodDescriptor::parse_generic_signature(Method* m, ClassDescriptor* outer) {
+ Symbol* generic_sig = m->generic_signature();
+ MethodDescriptor* md = NULL;
+ if (generic_sig == NULL || (md = parse_generic_signature(generic_sig, outer)) == NULL) {
+ md = parse_generic_signature(m->signature(), outer);
+ }
+ assert(md != NULL, "Could not parse method signature");
+ md->bind_variables_to_parameters();
+ return md;
+}
+
+MethodDescriptor* MethodDescriptor::parse_generic_signature(Symbol* sym, ClassDescriptor* outer) {
+
+ DescriptorStream ds(sym);
+ DescriptorStream* STREAM = &ds;
+
+ GrowableArray<TypeParameter*> params(8);
+ char c = READ();
+ if (c == '<') {
+ c = READ();
+ while (c != '>') {
+ PUSH(c);
+ TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM);
+ params.append(ftp);
+ c = READ();
+ }
+ } else {
+ PUSH(c);
+ }
+
+ EXPECT('(');
+
+ GrowableArray<Type*> parameters(8);
+ c = READ();
+ while (c != ')') {
+ PUSH(c);
+ Type* arg = Type::parse_generic_signature(CHECK_STREAM);
+ parameters.append(arg);
+ c = READ();
+ }
+
+ Type* rt = Type::parse_generic_signature(CHECK_STREAM);
+
+ GrowableArray<Type*> throws;
+ while (!STREAM->at_end()) {
+ EXPECT('^');
+ Type* spec = Type::parse_generic_signature(CHECK_STREAM);
+ throws.append(spec);
+ }
+
+ return new MethodDescriptor(params, outer, parameters, rt, throws);
+}
+
+void MethodDescriptor::bind_variables_to_parameters() {
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ _type_parameters.at(i)->bind_variables_to_parameters(this, i);
+ }
+ for (int i = 0; i < _parameters.length(); ++i) {
+ _parameters.at(i)->bind_variables_to_parameters(this);
+ }
+ _return_type->bind_variables_to_parameters(this);
+ for (int i = 0; i < _throws.length(); ++i) {
+ _throws.at(i)->bind_variables_to_parameters(this);
+ }
+}
+
+bool MethodDescriptor::covariant_match(MethodDescriptor* other, Context* ctx) {
+
+ if (_parameters.length() == other->_parameters.length()) {
+ for (int i = 0; i < _parameters.length(); ++i) {
+ if (!_parameters.at(i)->covariant_match(other->_parameters.at(i), ctx)) {
+ return false;
+ }
+ }
+
+ if (_return_type->as_primitive() != NULL) {
+ return _return_type->covariant_match(other->_return_type, ctx);
+ } else {
+ // return type is a reference
+ return other->_return_type->as_class() != NULL ||
+ other->_return_type->as_variable() != NULL ||
+ other->_return_type->as_array() != NULL;
+ }
+ } else {
+ return false;
+ }
+}
+
+MethodDescriptor* MethodDescriptor::canonicalize(Context* ctx) {
+
+ GrowableArray<TypeParameter*> type_params(_type_parameters.length());
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0));
+ }
+
+ ClassDescriptor* outer = _outer_class == NULL ? NULL :
+ _outer_class->canonicalize(ctx);
+
+ GrowableArray<Type*> params(_parameters.length());
+ for (int i = 0; i < _parameters.length(); ++i) {
+ params.append(_parameters.at(i)->canonicalize(ctx, 0));
+ }
+
+ Type* rt = _return_type->canonicalize(ctx, 0);
+
+ GrowableArray<Type*> throws(_throws.length());
+ for (int i = 0; i < _throws.length(); ++i) {
+ throws.append(_throws.at(i)->canonicalize(ctx, 0));
+ }
+
+ return new MethodDescriptor(type_params, outer, params, rt, throws);
+}
+
+#ifndef PRODUCT
+TempNewSymbol MethodDescriptor::reify_signature(Context* ctx, TRAPS) {
+ stringStream ss(256);
+
+ ss.print("(");
+ for (int i = 0; i < _parameters.length(); ++i) {
+ _parameters.at(i)->reify_signature(&ss, ctx);
+ }
+ ss.print(")");
+ _return_type->reify_signature(&ss, ctx);
+ return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD);
+}
+
+void MethodDescriptor::print_on(outputStream* str) const {
+ str->indent().print_cr("MethodDescriptor {");
+ {
+ streamIndentor si(str);
+ if (_type_parameters.length() > 0) {
+ str->indent().print_cr("Formals: {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _type_parameters.length(); ++i) {
+ _type_parameters.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ str->indent().print_cr("Parameters: {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _parameters.length(); ++i) {
+ _parameters.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ str->indent().print_cr("Return Type: ");
+ {
+ streamIndentor si(str);
+ _return_type->print_on(str);
+ }
+
+ if (_throws.length() > 0) {
+ str->indent().print_cr("Throws: {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _throws.length(); ++i) {
+ _throws.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+TypeParameter* TypeParameter::parse_generic_signature(DescriptorStream* STREAM) {
+ STREAM->set_mark();
+ char c = READ();
+ while (c != ':') {
+ c = READ();
+ }
+
+ Identifier* id = STREAM->identifier_from_mark();
+
+ ClassType* class_bound = NULL;
+ GrowableArray<ClassType*> interface_bounds(8);
+
+ c = READ();
+ if (c != '>') {
+ if (c != ':') {
+ EXPECTED(c, 'L');
+ class_bound = ClassType::parse_generic_signature(CHECK_STREAM);
+ c = READ();
+ }
+
+ while (c == ':') {
+ EXPECT('L');
+ ClassType* fts = ClassType::parse_generic_signature(CHECK_STREAM);
+ interface_bounds.append(fts);
+ c = READ();
+ }
+ }
+ PUSH(c);
+
+ return new TypeParameter(id, class_bound, interface_bounds);
+}
+
+void TypeParameter::bind_variables_to_parameters(Descriptor* sig, int position) {
+ if (_class_bound != NULL) {
+ _class_bound->bind_variables_to_parameters(sig);
+ }
+ for (int i = 0; i < _interface_bounds.length(); ++i) {
+ _interface_bounds.at(i)->bind_variables_to_parameters(sig);
+ }
+ _position = position;
+}
+
+Type* TypeParameter::resolve(
+ Context* ctx, int inner_depth, int ctx_depth) {
+
+ if (inner_depth == -1) {
+ // This indicates that the parameter is a method type parameter, which
+ // isn't resolveable using the class hierarchy context
+ return bound();
+ }
+
+ ClassType* provider = ctx->at_depth(ctx_depth);
+ if (provider != NULL) {
+ for (int i = 0; i < inner_depth && provider != NULL; ++i) {
+ provider = provider->outer_class();
+ }
+ if (provider != NULL) {
+ TypeArgument* arg = provider->type_argument_at(_position);
+ if (arg != NULL) {
+ Type* value = arg->lower_bound();
+ return value->canonicalize(ctx, ctx_depth + 1);
+ }
+ }
+ }
+
+ return bound();
+}
+
+TypeParameter* TypeParameter::canonicalize(Context* ctx, int ctx_depth) {
+ ClassType* bound = _class_bound == NULL ? NULL :
+ _class_bound->canonicalize(ctx, ctx_depth);
+
+ GrowableArray<ClassType*> ifaces(_interface_bounds.length());
+ for (int i = 0; i < _interface_bounds.length(); ++i) {
+ ifaces.append(_interface_bounds.at(i)->canonicalize(ctx, ctx_depth));
+ }
+
+ TypeParameter* ret = new TypeParameter(_identifier, bound, ifaces);
+ ret->_position = _position;
+ return ret;
+}
+
+ClassType* TypeParameter::bound() {
+ if (_class_bound != NULL) {
+ return _class_bound;
+ }
+
+ if (_interface_bounds.length() == 1) {
+ return _interface_bounds.at(0);
+ }
+
+ return ClassType::java_lang_Object(); // TODO: investigate this case
+}
+
+#ifndef PRODUCT
+void TypeParameter::print_on(outputStream* str) const {
+ str->indent().print_cr("Formal: {");
+ {
+ streamIndentor si(str);
+
+ str->indent().print("Identifier: ");
+ _identifier->print_on(str);
+ str->print_cr("");
+ if (_class_bound != NULL) {
+ str->indent().print_cr("Class Bound: ");
+ streamIndentor si(str);
+ _class_bound->print_on(str);
+ }
+ if (_interface_bounds.length() > 0) {
+ str->indent().print_cr("Interface Bounds: {");
+ {
+ streamIndentor si(str);
+ for (int i = 0; i < _interface_bounds.length(); ++i) {
+ _interface_bounds.at(i)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ str->indent().print_cr("Ordinal Position: %d", _position);
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+Type* Type::parse_generic_signature(DescriptorStream* STREAM) {
+ char c = READ();
+ switch (c) {
+ case 'L':
+ return ClassType::parse_generic_signature(CHECK_STREAM);
+ case 'T':
+ return TypeVariable::parse_generic_signature(CHECK_STREAM);
+ case '[':
+ return ArrayType::parse_generic_signature(CHECK_STREAM);
+ default:
+ return new PrimitiveType(c);
+ }
+}
+
+Identifier* ClassType::parse_generic_signature_simple(GrowableArray<TypeArgument*>* args,
+ bool* has_inner, DescriptorStream* STREAM) {
+ STREAM->set_mark();
+
+ char c = READ();
+ while (c != ';' && c != '.' && c != '<') { c = READ(); }
+ Identifier* id = STREAM->identifier_from_mark();
+
+ if (c == '<') {
+ c = READ();
+ while (c != '>') {
+ PUSH(c);
+ TypeArgument* arg = TypeArgument::parse_generic_signature(CHECK_STREAM);
+ args->append(arg);
+ c = READ();
+ }
+ c = READ();
+ }
+
+ *has_inner = (c == '.');
+ if (!(*has_inner)) {
+ EXPECTED(c, ';');
+ }
+
+ return id;
+}
+
+ClassType* ClassType::parse_generic_signature(DescriptorStream* STREAM) {
+ return parse_generic_signature(NULL, CHECK_STREAM);
+}
+
+ClassType* ClassType::parse_generic_signature(ClassType* outer, DescriptorStream* STREAM) {
+ GrowableArray<TypeArgument*> args;
+ ClassType* gct = NULL;
+ bool has_inner = false;
+
+ Identifier* id = parse_generic_signature_simple(&args, &has_inner, STREAM);
+ if (id != NULL) {
+ gct = new ClassType(id, args, outer);
+
+ if (has_inner) {
+ gct = parse_generic_signature(gct, CHECK_STREAM);
+ }
+ }
+ return gct;
+}
+
+ClassType* ClassType::from_symbol(Symbol* sym) {
+ assert(sym != NULL, "Must not be null");
+ GrowableArray<TypeArgument*> args;
+ Identifier* id = new Identifier(sym, 0, sym->utf8_length());
+ return new ClassType(id, args, NULL);
+}
+
+ClassType* ClassType::java_lang_Object() {
+ return from_symbol(vmSymbols::java_lang_Object());
+}
+
+void ClassType::bind_variables_to_parameters(Descriptor* sig) {
+ for (int i = 0; i < _type_arguments.length(); ++i) {
+ _type_arguments.at(i)->bind_variables_to_parameters(sig);
+ }
+ if (_outer_class != NULL) {
+ _outer_class->bind_variables_to_parameters(sig);
+ }
+}
+
+TypeArgument* ClassType::type_argument_at(int i) {
+ if (i >= 0 && i < _type_arguments.length()) {
+ return _type_arguments.at(i);
+ } else {
+ return NULL;
+ }
+}
+
+#ifndef PRODUCT
+void ClassType::reify_signature(stringStream* ss, Context* ctx) {
+ ss->print("L");
+ _identifier->print_on(ss);
+ ss->print(";");
+}
+
+void ClassType::print_on(outputStream* str) const {
+ str->indent().print_cr("Class {");
+ {
+ streamIndentor si(str);
+ str->indent().print("Name: ");
+ _identifier->print_on(str);
+ str->print_cr("");
+ if (_type_arguments.length() != 0) {
+ str->indent().print_cr("Type Arguments: {");
+ {
+ streamIndentor si(str);
+ for (int j = 0; j < _type_arguments.length(); ++j) {
+ _type_arguments.at(j)->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+ }
+ if (_outer_class != NULL) {
+ str->indent().print_cr("Outer Class: ");
+ streamIndentor sir(str);
+ _outer_class->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+bool ClassType::covariant_match(Type* other, Context* ctx) {
+
+ if (other == this) {
+ return true;
+ }
+
+ TypeVariable* variable = other->as_variable();
+ if (variable != NULL) {
+ other = variable->resolve(ctx, 0);
+ }
+
+ ClassType* outer = outer_class();
+ ClassType* other_class = other->as_class();
+
+ if (other_class == NULL ||
+ (outer == NULL) != (other_class->outer_class() == NULL)) {
+ return false;
+ }
+
+ if (!_identifier->equals(other_class->_identifier)) {
+ return false;
+ }
+
+ if (outer != NULL && !outer->covariant_match(other_class->outer_class(), ctx)) {
+ return false;
+ }
+
+ return true;
+}
+
+ClassType* ClassType::canonicalize(Context* ctx, int ctx_depth) {
+
+ GrowableArray<TypeArgument*> args(_type_arguments.length());
+ for (int i = 0; i < _type_arguments.length(); ++i) {
+ args.append(_type_arguments.at(i)->canonicalize(ctx, ctx_depth));
+ }
+
+ ClassType* outer = _outer_class == NULL ? NULL :
+ _outer_class->canonicalize(ctx, ctx_depth);
+
+ return new ClassType(_identifier, args, outer);
+}
+
+TypeVariable* TypeVariable::parse_generic_signature(DescriptorStream* STREAM) {
+ STREAM->set_mark();
+ char c = READ();
+ while (c != ';') {
+ c = READ();
+ }
+ Identifier* id = STREAM->identifier_from_mark();
+
+ return new TypeVariable(id);
+}
+
+void TypeVariable::bind_variables_to_parameters(Descriptor* sig) {
+ _parameter = sig->find_type_parameter(_id, &_inner_depth);
+ if (VerifyGenericSignatures && _parameter == NULL) {
+ fatal("Could not find formal parameter");
+ }
+}
+
+Type* TypeVariable::resolve(Context* ctx, int ctx_depth) {
+ if (parameter() != NULL) {
+ return parameter()->resolve(ctx, inner_depth(), ctx_depth);
+ } else {
+ if (VerifyGenericSignatures) {
+ fatal("Type variable matches no parameter");
+ }
+ return NULL;
+ }
+}
+
+bool TypeVariable::covariant_match(Type* other, Context* ctx) {
+
+ if (other == this) {
+ return true;
+ }
+
+ Context my_context(NULL); // empty, results in erasure
+ Type* my_type = resolve(&my_context, 0);
+ if (my_type == NULL) {
+ return false;
+ }
+
+ return my_type->covariant_match(other, ctx);
+}
+
+Type* TypeVariable::canonicalize(Context* ctx, int ctx_depth) {
+ return resolve(ctx, ctx_depth);
+}
+
+#ifndef PRODUCT
+void TypeVariable::reify_signature(stringStream* ss, Context* ctx) {
+ Type* type = resolve(ctx, 0);
+ if (type != NULL) {
+ type->reify_signature(ss, ctx);
+ }
+}
+
+void TypeVariable::print_on(outputStream* str) const {
+ str->indent().print_cr("Type Variable {");
+ {
+ streamIndentor si(str);
+ str->indent().print("Name: ");
+ _id->print_on(str);
+ str->print_cr("");
+ str->indent().print_cr("Inner depth: %d", _inner_depth);
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+ArrayType* ArrayType::parse_generic_signature(DescriptorStream* STREAM) {
+ Type* base = Type::parse_generic_signature(CHECK_STREAM);
+ return new ArrayType(base);
+}
+
+void ArrayType::bind_variables_to_parameters(Descriptor* sig) {
+ assert(_base != NULL, "Invalid base");
+ _base->bind_variables_to_parameters(sig);
+}
+
+bool ArrayType::covariant_match(Type* other, Context* ctx) {
+ assert(_base != NULL, "Invalid base");
+
+ if (other == this) {
+ return true;
+ }
+
+ ArrayType* other_array = other->as_array();
+ return (other_array != NULL && _base->covariant_match(other_array->_base, ctx));
+}
+
+ArrayType* ArrayType::canonicalize(Context* ctx, int ctx_depth) {
+ assert(_base != NULL, "Invalid base");
+ return new ArrayType(_base->canonicalize(ctx, ctx_depth));
+}
+
+#ifndef PRODUCT
+void ArrayType::reify_signature(stringStream* ss, Context* ctx) {
+ assert(_base != NULL, "Invalid base");
+ ss->print("[");
+ _base->reify_signature(ss, ctx);
+}
+
+void ArrayType::print_on(outputStream* str) const {
+ str->indent().print_cr("Array {");
+ {
+ streamIndentor si(str);
+ _base->print_on(str);
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+bool PrimitiveType::covariant_match(Type* other, Context* ctx) {
+
+ PrimitiveType* other_prim = other->as_primitive();
+ return (other_prim != NULL && _type == other_prim->_type);
+}
+
+PrimitiveType* PrimitiveType::canonicalize(Context* ctx, int ctxd) {
+ return this;
+}
+
+#ifndef PRODUCT
+void PrimitiveType::reify_signature(stringStream* ss, Context* ctx) {
+ ss->print("%c", _type);
+}
+
+void PrimitiveType::print_on(outputStream* str) const {
+ str->indent().print_cr("Primitive: '%c'", _type);
+}
+#endif // ndef PRODUCT
+
+void PrimitiveType::bind_variables_to_parameters(Descriptor* sig) {
+}
+
+TypeArgument* TypeArgument::parse_generic_signature(DescriptorStream* STREAM) {
+ char c = READ();
+ Type* type = NULL;
+
+ switch (c) {
+ case '*':
+ return new TypeArgument(ClassType::java_lang_Object(), NULL);
+ break;
+ default:
+ PUSH(c);
+ // fall-through
+ case '+':
+ case '-':
+ type = Type::parse_generic_signature(CHECK_STREAM);
+ if (c == '+') {
+ return new TypeArgument(type, NULL);
+ } else if (c == '-') {
+ return new TypeArgument(ClassType::java_lang_Object(), type);
+ } else {
+ return new TypeArgument(type, type);
+ }
+ }
+}
+
+void TypeArgument::bind_variables_to_parameters(Descriptor* sig) {
+ assert(_lower_bound != NULL, "Invalid lower bound");
+ _lower_bound->bind_variables_to_parameters(sig);
+ if (_upper_bound != NULL && _upper_bound != _lower_bound) {
+ _upper_bound->bind_variables_to_parameters(sig);
+ }
+}
+
+bool TypeArgument::covariant_match(TypeArgument* other, Context* ctx) {
+ assert(_lower_bound != NULL, "Invalid lower bound");
+
+ if (other == this) {
+ return true;
+ }
+
+ if (!_lower_bound->covariant_match(other->lower_bound(), ctx)) {
+ return false;
+ }
+ return true;
+}
+
+TypeArgument* TypeArgument::canonicalize(Context* ctx, int ctx_depth) {
+ assert(_lower_bound != NULL, "Invalid lower bound");
+ Type* lower = _lower_bound->canonicalize(ctx, ctx_depth);
+ Type* upper = NULL;
+
+ if (_upper_bound == _lower_bound) {
+ upper = lower;
+ } else if (_upper_bound != NULL) {
+ upper = _upper_bound->canonicalize(ctx, ctx_depth);
+ }
+
+ return new TypeArgument(lower, upper);
+}
+
+#ifndef PRODUCT
+void TypeArgument::print_on(outputStream* str) const {
+ str->indent().print_cr("TypeArgument {");
+ {
+ streamIndentor si(str);
+ if (_lower_bound != NULL) {
+ str->indent().print("Lower bound: ");
+ _lower_bound->print_on(str);
+ }
+ if (_upper_bound != NULL) {
+ str->indent().print("Upper bound: ");
+ _upper_bound->print_on(str);
+ }
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+void Context::Mark::destroy() {
+ if (is_active()) {
+ _context->reset_to_mark(_marked_size);
+ }
+ deactivate();
+}
+
+void Context::apply_type_arguments(
+ InstanceKlass* current, InstanceKlass* super, TRAPS) {
+ assert(_cache != NULL, "Cannot use an empty context");
+ ClassType* spec = NULL;
+ if (current != NULL) {
+ ClassDescriptor* descriptor = _cache->descriptor_for(current, CHECK);
+ if (super == current->super()) {
+ spec = descriptor->super();
+ } else {
+ spec = descriptor->interface_desc(super->name());
+ }
+ if (spec != NULL) {
+ _type_arguments.push(spec);
+ }
+ }
+}
+
+void Context::reset_to_mark(int size) {
+ _type_arguments.trunc_to(size);
+}
+
+ClassType* Context::at_depth(int i) const {
+ if (i < _type_arguments.length()) {
+ return _type_arguments.at(_type_arguments.length() - 1 - i);
+ }
+ return NULL;
+}
+
+#ifndef PRODUCT
+void Context::print_on(outputStream* str) const {
+ str->indent().print_cr("Context {");
+ for (int i = 0; i < _type_arguments.length(); ++i) {
+ streamIndentor si(str);
+ str->indent().print("leval %d: ", i);
+ ClassType* ct = at_depth(i);
+ if (ct == NULL) {
+ str->print_cr("<empty>");
+ continue;
+ } else {
+ str->print_cr("{");
+ }
+
+ for (int j = 0; j < ct->type_arguments_length(); ++j) {
+ streamIndentor si(str);
+ TypeArgument* ta = ct->type_argument_at(j);
+ Type* bound = ta->lower_bound();
+ bound->print_on(str);
+ }
+ str->indent().print_cr("}");
+ }
+ str->indent().print_cr("}");
+}
+#endif // ndef PRODUCT
+
+ClassDescriptor* DescriptorCache::descriptor_for(InstanceKlass* ik, TRAPS) {
+
+ ClassDescriptor** existing = _class_descriptors.get(ik);
+ if (existing == NULL) {
+ ClassDescriptor* cd = ClassDescriptor::parse_generic_signature(ik, CHECK_NULL);
+ _class_descriptors.put(ik, cd);
+ return cd;
+ } else {
+ return *existing;
+ }
+}
+
+MethodDescriptor* DescriptorCache::descriptor_for(
+ Method* mh, ClassDescriptor* cd, TRAPS) {
+ assert(mh != NULL && cd != NULL, "Should not be NULL");
+ MethodDescriptor** existing = _method_descriptors.get(mh);
+ if (existing == NULL) {
+ MethodDescriptor* md = MethodDescriptor::parse_generic_signature(mh, cd);
+ _method_descriptors.put(mh, md);
+ return md;
+ } else {
+ return *existing;
+ }
+}
+MethodDescriptor* DescriptorCache::descriptor_for(Method* mh, TRAPS) {
+ ClassDescriptor* cd = descriptor_for(
+ InstanceKlass::cast(mh->method_holder()), CHECK_NULL);
+ return descriptor_for(mh, cd, THREAD);
+}
+
+} // namespace generic
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/genericSignatures.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
+#define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
+
+#include "classfile/symbolTable.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/signature.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/resourceHash.hpp"
+
+class stringStream;
+
+namespace generic {
+
+class Identifier;
+class ClassDescriptor;
+class MethodDescriptor;
+
+class TypeParameter; // a formal type parameter declared in generic signatures
+class TypeArgument; // The "type value" passed to fill parameters in supertypes
+class TypeVariable; // A usage of a type parameter as a value
+/**
+ * Example:
+ *
+ * <T, V> class Foo extends Bar<String> { int m(V v) {} }
+ * ^^^^^^ ^^^^^^ ^^
+ * type parameters type argument type variable
+ *
+ * Note that a type variable could be passed as an argument too:
+ * <T, V> class Foo extends Bar<T> { int m(V v) {} }
+ * ^^^
+ * type argument's value is a type variable
+ */
+
+
+class Type;
+class ClassType;
+class ArrayType;
+class PrimitiveType;
+class Context;
+class DescriptorCache;
+
+class DescriptorStream;
+
+class Identifier : public ResourceObj {
+ private:
+ Symbol* _sym;
+ int _begin;
+ int _end;
+
+ public:
+ Identifier(Symbol* sym, int begin, int end) :
+ _sym(sym), _begin(begin), _end(end) {}
+
+ bool equals(Identifier* other);
+ bool equals(Symbol* sym);
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const;
+#endif // ndef PRODUCT
+};
+
+class Descriptor : public ResourceObj {
+ protected:
+ GrowableArray<TypeParameter*> _type_parameters;
+ ClassDescriptor* _outer_class;
+
+ Descriptor(GrowableArray<TypeParameter*>& params,
+ ClassDescriptor* outer)
+ : _type_parameters(params), _outer_class(outer) {}
+
+ public:
+
+ ClassDescriptor* outer_class() { return _outer_class; }
+ void set_outer_class(ClassDescriptor* sig) { _outer_class = sig; }
+
+ virtual ClassDescriptor* as_class_signature() { return NULL; }
+ virtual MethodDescriptor* as_method_signature() { return NULL; }
+
+ bool is_class_signature() { return as_class_signature() != NULL; }
+ bool is_method_signature() { return as_method_signature() != NULL; }
+
+ GrowableArray<TypeParameter*>& type_parameters() {
+ return _type_parameters;
+ }
+
+ TypeParameter* find_type_parameter(Identifier* id, int* param_depth);
+
+ virtual void bind_variables_to_parameters() = 0;
+
+#ifndef PRODUCT
+ virtual void print_on(outputStream* str) const = 0;
+#endif
+};
+
+class ClassDescriptor : public Descriptor {
+ private:
+ ClassType* _super;
+ GrowableArray<ClassType*> _interfaces;
+ MethodDescriptor* _outer_method;
+
+ ClassDescriptor(GrowableArray<TypeParameter*>& ftp, ClassType* scs,
+ GrowableArray<ClassType*>& sis, ClassDescriptor* outer_class = NULL,
+ MethodDescriptor* outer_method = NULL)
+ : Descriptor(ftp, outer_class), _super(scs), _interfaces(sis),
+ _outer_method(outer_method) {}
+
+ static u2 get_outer_class_index(InstanceKlass* k, TRAPS);
+ static ClassDescriptor* parse_generic_signature(Klass* k, Symbol* original_name, TRAPS);
+
+ public:
+
+ virtual ClassDescriptor* as_class_signature() { return this; }
+
+ MethodDescriptor* outer_method() { return _outer_method; }
+ void set_outer_method(MethodDescriptor* m) { _outer_method = m; }
+
+ ClassType* super() { return _super; }
+ ClassType* interface_desc(Symbol* sym);
+
+ static ClassDescriptor* parse_generic_signature(Klass* k, TRAPS);
+ static ClassDescriptor* parse_generic_signature(Symbol* sym);
+
+ // For use in superclass chains in positions where this is no generic info
+ static ClassDescriptor* placeholder(InstanceKlass* klass);
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const;
+#endif
+
+ ClassDescriptor* canonicalize(Context* ctx);
+
+ // Linking sets the position index in any contained TypeVariable type
+ // to correspond to the location of that identifier in the formal type
+ // parameters.
+ void bind_variables_to_parameters();
+};
+
+class MethodDescriptor : public Descriptor {
+ private:
+ GrowableArray<Type*> _parameters;
+ Type* _return_type;
+ GrowableArray<Type*> _throws;
+
+ MethodDescriptor(GrowableArray<TypeParameter*>& ftp, ClassDescriptor* outer,
+ GrowableArray<Type*>& sigs, Type* rt, GrowableArray<Type*>& throws)
+ : Descriptor(ftp, outer), _parameters(sigs), _return_type(rt),
+ _throws(throws) {}
+
+ public:
+
+ static MethodDescriptor* parse_generic_signature(Method* m, ClassDescriptor* outer);
+ static MethodDescriptor* parse_generic_signature(Symbol* sym, ClassDescriptor* outer);
+
+ MethodDescriptor* as_method_signature() { return this; }
+
+ // Performs generic analysis on the method parameters to determine
+ // if both methods refer to the same argument types.
+ bool covariant_match(MethodDescriptor* other, Context* ctx);
+
+ // Returns a new method descriptor with all generic variables
+ // removed and replaced with whatever is indicated using the Context.
+ MethodDescriptor* canonicalize(Context* ctx);
+
+ void bind_variables_to_parameters();
+
+#ifndef PRODUCT
+ TempNewSymbol reify_signature(Context* ctx, TRAPS);
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class TypeParameter : public ResourceObj {
+ private:
+ Identifier* _identifier;
+ ClassType* _class_bound;
+ GrowableArray<ClassType*> _interface_bounds;
+
+ // The position is the ordinal location of the parameter within the
+ // formal parameter list (excluding outer classes). It is only set for
+ // formal type parameters that are associated with a class -- method
+ // type parameters are left as -1. When resolving a generic variable to
+ // find the actual type, this index is used to access the generic type
+ // argument in the provided context object.
+ int _position; // Assigned during variable linking
+
+ TypeParameter(Identifier* id, ClassType* class_bound,
+ GrowableArray<ClassType*>& interface_bounds) :
+ _identifier(id), _class_bound(class_bound),
+ _interface_bounds(interface_bounds), _position(-1) {}
+
+ public:
+ static TypeParameter* parse_generic_signature(DescriptorStream* str);
+
+ ClassType* bound();
+ int position() { return _position; }
+
+ void bind_variables_to_parameters(Descriptor* sig, int position);
+ Identifier* identifier() { return _identifier; }
+
+ Type* resolve(Context* ctx, int inner_depth, int ctx_depth);
+ TypeParameter* canonicalize(Context* ctx, int ctx_depth);
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class Type : public ResourceObj {
+ public:
+ static Type* parse_generic_signature(DescriptorStream* str);
+
+ virtual ClassType* as_class() { return NULL; }
+ virtual TypeVariable* as_variable() { return NULL; }
+ virtual ArrayType* as_array() { return NULL; }
+ virtual PrimitiveType* as_primitive() { return NULL; }
+
+ virtual bool covariant_match(Type* gt, Context* ctx) = 0;
+ virtual Type* canonicalize(Context* ctx, int ctx_depth) = 0;
+
+ virtual void bind_variables_to_parameters(Descriptor* sig) = 0;
+
+#ifndef PRODUCT
+ virtual void reify_signature(stringStream* ss, Context* ctx) = 0;
+ virtual void print_on(outputStream* str) const = 0;
+#endif
+};
+
+class ClassType : public Type {
+ friend class ClassDescriptor;
+ protected:
+ Identifier* _identifier;
+ GrowableArray<TypeArgument*> _type_arguments;
+ ClassType* _outer_class;
+
+ ClassType(Identifier* identifier,
+ GrowableArray<TypeArgument*>& args,
+ ClassType* outer)
+ : _identifier(identifier), _type_arguments(args), _outer_class(outer) {}
+
+ // Returns true if there are inner classes to read
+ static Identifier* parse_generic_signature_simple(
+ GrowableArray<TypeArgument*>* args,
+ bool* has_inner, DescriptorStream* str);
+
+ static ClassType* parse_generic_signature(ClassType* outer,
+ DescriptorStream* str);
+ static ClassType* from_symbol(Symbol* sym);
+
+ public:
+ ClassType* as_class() { return this; }
+
+ static ClassType* parse_generic_signature(DescriptorStream* str);
+ static ClassType* java_lang_Object();
+
+ Identifier* identifier() { return _identifier; }
+ int type_arguments_length() { return _type_arguments.length(); }
+ TypeArgument* type_argument_at(int i);
+
+ virtual ClassType* outer_class() { return _outer_class; }
+
+ bool covariant_match(Type* gt, Context* ctx);
+ ClassType* canonicalize(Context* ctx, int context_depth);
+
+ void bind_variables_to_parameters(Descriptor* sig);
+
+#ifndef PRODUCT
+ void reify_signature(stringStream* ss, Context* ctx);
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class TypeVariable : public Type {
+ private:
+ Identifier* _id;
+ TypeParameter* _parameter; // assigned during linking
+
+ // how many steps "out" from inner classes, -1 if method
+ int _inner_depth;
+
+ TypeVariable(Identifier* id)
+ : _id(id), _parameter(NULL), _inner_depth(0) {}
+
+ public:
+ TypeVariable* as_variable() { return this; }
+
+ static TypeVariable* parse_generic_signature(DescriptorStream* str);
+
+ Identifier* identifier() { return _id; }
+ TypeParameter* parameter() { return _parameter; }
+ int inner_depth() { return _inner_depth; }
+
+ void bind_variables_to_parameters(Descriptor* sig);
+
+ Type* resolve(Context* ctx, int ctx_depth);
+ bool covariant_match(Type* gt, Context* ctx);
+ Type* canonicalize(Context* ctx, int ctx_depth);
+
+#ifndef PRODUCT
+ void reify_signature(stringStream* ss, Context* ctx);
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class ArrayType : public Type {
+ private:
+ Type* _base;
+
+ ArrayType(Type* base) : _base(base) {}
+
+ public:
+ ArrayType* as_array() { return this; }
+
+ static ArrayType* parse_generic_signature(DescriptorStream* str);
+
+ bool covariant_match(Type* gt, Context* ctx);
+ ArrayType* canonicalize(Context* ctx, int ctx_depth);
+
+ void bind_variables_to_parameters(Descriptor* sig);
+
+#ifndef PRODUCT
+ void reify_signature(stringStream* ss, Context* ctx);
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class PrimitiveType : public Type {
+ friend class Type;
+ private:
+ char _type; // includes V for void
+
+ PrimitiveType(char& type) : _type(type) {}
+
+ public:
+ PrimitiveType* as_primitive() { return this; }
+
+ bool covariant_match(Type* gt, Context* ctx);
+ PrimitiveType* canonicalize(Context* ctx, int ctx_depth);
+
+ void bind_variables_to_parameters(Descriptor* sig);
+
+#ifndef PRODUCT
+ void reify_signature(stringStream* ss, Context* ctx);
+ void print_on(outputStream* str) const;
+#endif
+};
+
+class TypeArgument : public ResourceObj {
+ private:
+ Type* _lower_bound;
+ Type* _upper_bound; // may be null or == _lower_bound
+
+ TypeArgument(Type* lower_bound, Type* upper_bound)
+ : _lower_bound(lower_bound), _upper_bound(upper_bound) {}
+
+ public:
+
+ static TypeArgument* parse_generic_signature(DescriptorStream* str);
+
+ Type* lower_bound() { return _lower_bound; }
+ Type* upper_bound() { return _upper_bound; }
+
+ void bind_variables_to_parameters(Descriptor* sig);
+ TypeArgument* canonicalize(Context* ctx, int ctx_depth);
+
+ bool covariant_match(TypeArgument* a, Context* ctx);
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const;
+#endif
+};
+
+
+class Context : public ResourceObj {
+ private:
+ DescriptorCache* _cache;
+ GrowableArray<ClassType*> _type_arguments;
+
+ void reset_to_mark(int size);
+
+ public:
+ // When this object goes out of scope or 'destroy' is
+ // called, then the application of the type to the
+ // context is wound-back (unless it's been deactivated).
+ class Mark : public StackObj {
+ private:
+ mutable Context* _context;
+ int _marked_size;
+
+ bool is_active() const { return _context != NULL; }
+ void deactivate() const { _context = NULL; }
+
+ public:
+ Mark() : _context(NULL), _marked_size(0) {}
+ Mark(Context* ctx, int sz) : _context(ctx), _marked_size(sz) {}
+ Mark(const Mark& m) : _context(m._context), _marked_size(m._marked_size) {
+ m.deactivate(); // Ownership is transferred
+ }
+
+ Mark& operator=(const Mark& cm) {
+ destroy();
+ _context = cm._context;
+ _marked_size = cm._marked_size;
+ cm.deactivate();
+ return *this;
+ }
+
+ void destroy();
+ ~Mark() { destroy(); }
+ };
+
+ Context(DescriptorCache* cache) : _cache(cache) {}
+
+ Mark mark() { return Mark(this, _type_arguments.length()); }
+ void apply_type_arguments(InstanceKlass* current, InstanceKlass* super,TRAPS);
+
+ ClassType* at_depth(int i) const;
+
+#ifndef PRODUCT
+ void print_on(outputStream* str) const;
+#endif
+};
+
+/**
+ * Contains a cache of descriptors for classes and methods so they can be
+ * looked-up instead of reparsing each time they are needed.
+ */
+class DescriptorCache : public ResourceObj {
+ private:
+ ResourceHashtable<InstanceKlass*, ClassDescriptor*> _class_descriptors;
+ ResourceHashtable<Method*, MethodDescriptor*> _method_descriptors;
+
+ public:
+ ClassDescriptor* descriptor_for(InstanceKlass* ikh, TRAPS);
+
+ MethodDescriptor* descriptor_for(Method* mh, ClassDescriptor* cd, TRAPS);
+ // Class descriptor derived from method holder
+ MethodDescriptor* descriptor_for(Method* mh, TRAPS);
+};
+
+} // namespace generic
+
+#endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
+
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1156,7 +1156,7 @@
// Print stack trace element to resource allocated buffer
char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) {
// Get strings and string lengths
- InstanceKlass* klass = InstanceKlass::cast(method->method_holder());
+ InstanceKlass* klass = method->method_holder();
const char* klass_name = klass->external_name();
int buf_len = (int)strlen(klass_name);
char* source_file_name;
@@ -1747,14 +1747,14 @@
Handle element = ik->allocate_instance_handle(CHECK_0);
// Fill in class name
ResourceMark rm(THREAD);
- const char* str = InstanceKlass::cast(method->method_holder())->external_name();
+ const char* str = method->method_holder()->external_name();
oop classname = StringTable::intern((char*) str, CHECK_0);
java_lang_StackTraceElement::set_declaringClass(element(), classname);
// Fill in method name
oop methodname = StringTable::intern(method->name(), CHECK_0);
java_lang_StackTraceElement::set_methodName(element(), methodname);
// Fill in source file name
- Symbol* source = InstanceKlass::cast(method->method_holder())->source_file_name();
+ Symbol* source = method->method_holder()->source_file_name();
if (ShowHiddenFrames && source == NULL)
source = vmSymbols::unknown_class_name();
oop filename = StringTable::intern(source, CHECK_0);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -137,6 +137,7 @@
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
+ do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \
do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
--- a/hotspot/src/share/vm/classfile/verifier.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -446,7 +446,7 @@
bytecode_name = "<illegal>";
}
}
- InstanceKlass* ik = InstanceKlass::cast(method->method_holder());
+ InstanceKlass* ik = method->method_holder();
ss->indent().print_cr("Location:");
streamIndentor si2(ss);
ss->indent().print_cr("%s.%s%s @%d: %s",
@@ -555,9 +555,10 @@
if (was_recursively_verified()) return;
Method* m = methods->at(index);
- if (m->is_native() || m->is_abstract()) {
+ if (m->is_native() || m->is_abstract() || m->is_overpass()) {
// If m is native or abstract, skip it. It is checked in class file
- // parser that methods do not override a final method.
+ // parser that methods do not override a final method. Overpass methods
+ // are trusted since the VM generates them.
continue;
}
verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
@@ -1849,7 +1850,7 @@
if ((index <= 0) || (index >= nconstants)) {
verify_error(ErrorContext::bad_cp_index(bci, index),
"Illegal constant pool index %d in class %s",
- index, InstanceKlass::cast(cp->pool_holder())->external_name());
+ index, cp->pool_holder()->external_name());
return;
}
}
@@ -1868,7 +1869,7 @@
if ((types & (1 << tag)) == 0) {
verify_error(ErrorContext::bad_cp_index(bci, index),
"Illegal type at constant pool entry %d in class %s",
- index, InstanceKlass::cast(cp->pool_holder())->external_name());
+ index, cp->pool_holder()->external_name());
return;
}
}
@@ -1880,7 +1881,7 @@
if (!tag.is_klass() && !tag.is_unresolved_klass()) {
verify_error(ErrorContext::bad_cp_index(bci, index),
"Illegal type at constant pool entry %d in class %s",
- index, InstanceKlass::cast(cp->pool_holder())->external_name());
+ index, cp->pool_holder()->external_name());
return;
}
}
@@ -2304,11 +2305,21 @@
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
- unsigned int types = (opcode == Bytecodes::_invokeinterface
- ? 1 << JVM_CONSTANT_InterfaceMethodref
- : opcode == Bytecodes::_invokedynamic
- ? 1 << JVM_CONSTANT_InvokeDynamic
- : 1 << JVM_CONSTANT_Methodref);
+ unsigned int types;
+ switch (opcode) {
+ case Bytecodes::_invokeinterface:
+ types = 1 << JVM_CONSTANT_InterfaceMethodref;
+ break;
+ case Bytecodes::_invokedynamic:
+ types = 1 << JVM_CONSTANT_InvokeDynamic;
+ break;
+ case Bytecodes::_invokespecial:
+ types = (1 << JVM_CONSTANT_InterfaceMethodref) |
+ (1 << JVM_CONSTANT_Methodref);
+ break;
+ default:
+ types = 1 << JVM_CONSTANT_Methodref;
+ }
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
// Get method name and signature
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -507,7 +507,7 @@
}
void vmIntrinsics::verify_method(ID actual_id, Method* m) {
- Symbol* mk = Klass::cast(m->method_holder())->name();
+ Symbol* mk = m->method_holder()->name();
ID declared_id = match_method_with_klass(m, mk);
if (declared_id == actual_id) return; // success
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -259,6 +259,7 @@
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
+ template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
--- a/hotspot/src/share/vm/code/compiledIC.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/code/compiledIC.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -191,8 +191,8 @@
int index = klassItable::compute_itable_index(call_info->resolved_method()());
entry = VtableStubs::create_stub(false, index, method());
assert(entry != NULL, "entry not computed");
- Klass* k = call_info->resolved_method()->method_holder();
- assert(Klass::cast(k)->is_interface(), "sanity check");
+ InstanceKlass* k = call_info->resolved_method()->method_holder();
+ assert(k->is_interface(), "sanity check");
InlineCacheBuffer::create_transition_stub(this, k, entry);
} else {
// Can be different than method->vtable_index(), due to package-private etc.
--- a/hotspot/src/share/vm/code/dependencies.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -829,7 +829,7 @@
}
if ( !Dependencies::is_concrete_method(lm)
&& !Dependencies::is_concrete_method(m)
- && Klass::cast(lm->method_holder())->is_subtype_of(m->method_holder()))
+ && lm->method_holder()->is_subtype_of(m->method_holder()))
// Method m is overridden by lm, but both are non-concrete.
return true;
}
@@ -1160,7 +1160,11 @@
// We could also return false if m does not yet appear to be
// executed, if the VM version supports this distinction also.
- return !m->is_abstract();
+ return !m->is_abstract() &&
+ !InstanceKlass::cast(m->method_holder())->is_interface();
+ // TODO: investigate whether default methods should be
+ // considered as "concrete" in this situation. For now they
+ // are not.
}
--- a/hotspot/src/share/vm/code/nmethod.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1263,7 +1263,7 @@
assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
// Remove from list of active nmethods
if (method() != NULL)
- InstanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
+ method()->method_holder()->remove_osr_nmethod(this);
// Set entry as invalid
_entry_bci = InvalidOSREntryBci;
}
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1051,7 +1051,7 @@
guarantee(!method->is_abstract(), "cannot compile abstract methods");
assert(method->method_holder()->oop_is_instance(),
"sanity check");
- assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(),
+ assert(!method->method_holder()->is_not_initialized(),
"method holder must be initialized");
assert(!method->is_method_handle_intrinsic(), "do not enqueue these guys");
@@ -1206,7 +1206,7 @@
assert(method->method_holder()->oop_is_instance(), "not an instance method");
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
- assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(), "method holder must be initialized");
+ assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
if (!TieredCompilation) {
comp_level = CompLevel_highest_tier;
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -67,7 +67,7 @@
// utility method
MethodMatcher* find(methodHandle method) {
- Symbol* class_name = Klass::cast(method->method_holder())->name();
+ Symbol* class_name = method->method_holder()->name();
Symbol* method_name = method->name();
for (MethodMatcher* current = this; current != NULL; current = current->_next) {
if (match(class_name, current->class_name(), current->_class_mode) &&
@@ -624,7 +624,7 @@
assert(has_command_file(), "command file must be specified");
fileStream stream(fopen(cc_file(), "at"));
stream.print("exclude ");
- Klass::cast(method->method_holder())->name()->print_symbol_on(&stream);
+ method->method_holder()->name()->print_symbol_on(&stream);
stream.print(".");
method->name()->print_symbol_on(&stream);
method->signature()->print_symbol_on(&stream);
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -55,16 +55,18 @@
bool Disassembler::_tried_to_load_library = false;
// This routine is in the shared library:
+Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL;
Disassembler::decode_func Disassembler::_decode_instructions = NULL;
static const char hsdis_library_name[] = "hsdis-"HOTSPOT_LIB_ARCH;
-static const char decode_instructions_name[] = "decode_instructions_virtual";
-
+static const char decode_instructions_virtual_name[] = "decode_instructions_virtual";
+static const char decode_instructions_name[] = "decode_instructions";
+static bool use_new_version = true;
#define COMMENT_COLUMN 40 LP64_ONLY(+8) /*could be an option*/
#define BYTES_COMMENT ";..." /* funky byte display comment */
bool Disassembler::load_library() {
- if (_decode_instructions != NULL) {
+ if (_decode_instructions_virtual != NULL || _decode_instructions != NULL) {
// Already succeeded.
return true;
}
@@ -123,11 +125,19 @@
_library = os::dll_load(buf, ebuf, sizeof ebuf);
}
if (_library != NULL) {
+ _decode_instructions_virtual = CAST_TO_FN_PTR(Disassembler::decode_func_virtual,
+ os::dll_lookup(_library, decode_instructions_virtual_name));
+ }
+ if (_decode_instructions_virtual == NULL) {
+ // could not spot in new version, try old version
_decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func,
os::dll_lookup(_library, decode_instructions_name));
+ use_new_version = false;
+ } else {
+ use_new_version = true;
}
_tried_to_load_library = true;
- if (_decode_instructions == NULL) {
+ if (_decode_instructions_virtual == NULL && _decode_instructions == NULL) {
tty->print_cr("Could not load %s; %s; %s", buf,
((_library != NULL)
? "entry point is missing"
@@ -450,17 +460,31 @@
// This is mainly for debugging the library itself.
FILE* out = stdout;
FILE* xmlout = (_print_raw > 1 ? out : NULL);
- return (address)
- (*Disassembler::_decode_instructions)((uintptr_t)start, (uintptr_t)end,
- start, end - start,
+ return use_new_version ?
+ (address)
+ (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
+ start, end - start,
+ NULL, (void*) xmlout,
+ NULL, (void*) out,
+ options(), 0/*nice new line*/)
+ :
+ (address)
+ (*Disassembler::_decode_instructions)(start, end,
NULL, (void*) xmlout,
NULL, (void*) out,
options());
}
- return (address)
- (*Disassembler::_decode_instructions)((uintptr_t)start, (uintptr_t)end,
- start, end - start,
+ return use_new_version ?
+ (address)
+ (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
+ start, end - start,
+ &event_to_env, (void*) this,
+ &printf_to_env, (void*) this,
+ options(), 0/*nice new line*/)
+ :
+ (address)
+ (*Disassembler::_decode_instructions)(start, end,
&event_to_env, (void*) this,
&printf_to_env, (void*) this,
options());
--- a/hotspot/src/share/vm/compiler/disassembler.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/compiler/disassembler.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -49,18 +49,27 @@
friend class decode_env;
private:
// this is the type of the dll entry point:
- typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
+ typedef void* (*decode_func_virtual)(uintptr_t start_va, uintptr_t end_va,
unsigned char* buffer, uintptr_t length,
void* (*event_callback)(void*, const char*, void*),
void* event_stream,
int (*printf_callback)(void*, const char*, ...),
void* printf_stream,
+ const char* options,
+ int newline);
+ // this is the type of the dll entry point for old version:
+ typedef void* (*decode_func)(void* start_va, void* end_va,
+ void* (*event_callback)(void*, const char*, void*),
+ void* event_stream,
+ int (*printf_callback)(void*, const char*, ...),
+ void* printf_stream,
const char* options);
// points to the library.
static void* _library;
// bailout
static bool _tried_to_load_library;
// points to the decode function.
+ static decode_func_virtual _decode_instructions_virtual;
static decode_func _decode_instructions;
// tries to load library and return whether it succedded.
static bool load_library();
@@ -85,7 +94,9 @@
public:
static bool can_decode() {
- return (_decode_instructions != NULL) || load_library();
+ return (_decode_instructions_virtual != NULL) ||
+ (_decode_instructions != NULL) ||
+ load_library();
}
static void decode(CodeBlob *cb, outputStream* st = NULL);
static void decode(nmethod* nm, outputStream* st = NULL);
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -733,12 +733,7 @@
get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
} // end JvmtiHideSingleStepping
- cache_entry(thread)->set_method_handle(
- pool,
- info.resolved_method(),
- info.resolved_appendix(),
- info.resolved_method_type(),
- pool->resolved_references());
+ cache_entry(thread)->set_method_handle(pool, info);
}
IRT_END
@@ -762,12 +757,7 @@
} // end JvmtiHideSingleStepping
ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index);
- cp_cache_entry->set_dynamic_call(
- pool,
- info.resolved_method(),
- info.resolved_appendix(),
- info.resolved_method_type(),
- pool->resolved_references());
+ cp_cache_entry->set_dynamic_call(pool, info);
}
IRT_END
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/defaultMethods.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
@@ -132,7 +133,7 @@
// don't force compilation, resolve was on behalf of compiler
return;
}
- if (InstanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
+ if (selected_method->method_holder()->is_not_initialized()) {
// 'is_not_initialized' means not only '!is_initialized', but also that
// initialization has not been started yet ('!being_initialized')
// Do not force compilation of methods in uninitialized classes.
@@ -404,21 +405,13 @@
Symbol* method_name, Symbol* method_signature,
KlassHandle current_klass, bool check_access, TRAPS) {
- // 1. check if klass is not interface
- if (resolved_klass->is_interface()) {
- ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
- }
-
Handle nested_exception;
- // 2. lookup method in resolved klass and its super klasses
+ // 1. lookup method in resolved klass and its super klasses
lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
if (resolved_method.is_null()) { // not found in the class hierarchy
- // 3. lookup method in all the interfaces implemented by the resolved klass
+ // 2. lookup method in all the interfaces implemented by the resolved klass
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
if (resolved_method.is_null()) {
@@ -432,7 +425,7 @@
}
if (resolved_method.is_null()) {
- // 4. method lookup failed
+ // 3. method lookup failed
ResourceMark rm(THREAD);
THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
@@ -442,6 +435,15 @@
}
}
+ // 4. check if klass is not interface
+ if (resolved_klass->is_interface() && resolved_method->is_abstract()) {
+ ResourceMark rm(THREAD);
+ char buf[200];
+ jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
+ resolved_klass()->external_name());
+ THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+
// 5. check if method is concrete
if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
ResourceMark rm(THREAD);
@@ -464,7 +466,7 @@
// check loader constraints
Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
- Handle class_loader (THREAD, InstanceKlass::cast(resolved_method->method_holder())->class_loader());
+ Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
{
ResourceMark rm(THREAD);
char* failed_type_name =
@@ -526,7 +528,7 @@
if (check_access) {
HandleMark hm(THREAD);
Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
- Handle class_loader (THREAD, InstanceKlass::cast(resolved_method->method_holder())->class_loader());
+ Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
{
ResourceMark rm(THREAD);
char* failed_type_name =
@@ -743,6 +745,27 @@
Symbol* method_name, Symbol* method_signature,
KlassHandle current_klass, bool check_access, TRAPS) {
+ if (resolved_klass->is_interface() && current_klass() != NULL) {
+ // If the target class is a direct interface, treat this as a "super"
+ // default call.
+ //
+ // If the current method is an overpass that happens to call a direct
+ // super-interface's method, then we'll end up rerunning the default method
+ // analysis even though we don't need to, but that's ok since it will end
+ // up with the same answer.
+ InstanceKlass* ik = InstanceKlass::cast(current_klass());
+ Array<Klass*>* interfaces = ik->local_interfaces();
+ int num_interfaces = interfaces->length();
+ for (int index = 0; index < num_interfaces; index++) {
+ if (interfaces->at(index) == resolved_klass()) {
+ Method* method = DefaultMethods::find_super_default(current_klass(),
+ resolved_klass(), method_name, method_signature, CHECK);
+ resolved_method = methodHandle(THREAD, method);
+ return;
+ }
+ }
+ }
+
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
// check if method name is <init>, that it is found in same klass as static type
@@ -784,11 +807,17 @@
{ KlassHandle method_klass = KlassHandle(THREAD,
resolved_method->method_holder());
- if (check_access &&
+ const bool direct_calling_default_method =
+ resolved_klass() != NULL && resolved_method() != NULL &&
+ resolved_klass->is_interface() && !resolved_method->is_abstract();
+
+ if (!direct_calling_default_method &&
+ check_access &&
// a) check if ACC_SUPER flag is set for the current class
current_klass->is_super() &&
// b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
- current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() &&
+ current_klass->is_subtype_of(method_klass()) &&
+ current_klass() != method_klass() &&
// c) check if the method is not <init>
resolved_method->name() != vmSymbols::object_initializer_name()) {
// Lookup super method
@@ -881,12 +910,12 @@
// Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
// has not been rewritten, and the vtable initialized.
- assert(InstanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
+ assert(resolved_method->method_holder()->is_linked(), "must be linked");
// Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
// has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
// a missing receiver might result in a bogus lookup.
- assert(InstanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
+ assert(resolved_method->method_holder()->is_linked(), "must be linked");
// do lookup based on receiver klass using the vtable index
if (resolved_method->method_holder()->is_interface()) { // miranda method
--- a/hotspot/src/share/vm/oops/constMethod.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/constMethod.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -34,29 +34,30 @@
const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
- int byte_code_size,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- TRAPS) {
+ int byte_code_size,
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ MethodType method_type,
+ TRAPS) {
int size = ConstMethod::size(byte_code_size,
compressed_line_number_size,
localvariable_table_length,
exception_table_length,
checked_exceptions_length);
return new (loader_data, size, true, THREAD) ConstMethod(
- byte_code_size, compressed_line_number_size,
- localvariable_table_length, exception_table_length,
- checked_exceptions_length, size);
+ byte_code_size, compressed_line_number_size, localvariable_table_length,
+ exception_table_length, checked_exceptions_length, method_type, size);
}
ConstMethod::ConstMethod(int byte_code_size,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- int size) {
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ MethodType method_type,
+ int size) {
No_Safepoint_Verifier no_safepoint;
set_interpreter_kind(Interpreter::invalid);
@@ -69,6 +70,7 @@
compressed_line_number_size,
localvariable_table_length,
exception_table_length);
+ set_method_type(method_type);
assert(this->size() == size, "wrong size for object");
}
@@ -111,8 +113,7 @@
}
Method* ConstMethod::method() const {
- return InstanceKlass::cast(_constants->pool_holder())->method_with_idnum(
- _method_idnum);
+ return _constants->pool_holder()->method_with_idnum(_method_idnum);
}
// linenumber table - note that length is unknown until decompression,
--- a/hotspot/src/share/vm/oops/constMethod.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/constMethod.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -108,12 +108,17 @@
class ConstMethod : public MetaspaceObj {
friend class VMStructs;
+
+public:
+ typedef enum { NORMAL, OVERPASS } MethodType;
+
private:
enum {
_has_linenumber_table = 1,
_has_checked_exceptions = 2,
_has_localvariable_table = 4,
- _has_exception_table = 8
+ _has_exception_table = 8,
+ _is_overpass = 16
};
// Bit vector of signature
@@ -145,19 +150,22 @@
// Constructor
ConstMethod(int byte_code_size,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- int size);
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ MethodType is_overpass,
+ int size);
public:
+
static ConstMethod* allocate(ClassLoaderData* loader_data,
- int byte_code_size,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- TRAPS);
+ int byte_code_size,
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ MethodType mt,
+ TRAPS);
bool is_constMethod() const { return true; }
@@ -179,6 +187,19 @@
bool has_exception_handler() const
{ return (_flags & _has_exception_table) != 0; }
+ MethodType method_type() const {
+ return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
+ }
+
+ void set_method_type(MethodType mt) {
+ if (mt == NORMAL) {
+ _flags &= ~(_is_overpass);
+ } else {
+ _flags |= _is_overpass;
+ }
+ }
+
+
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
int interpreter_kind(void) const { return _interpreter_kind; }
--- a/hotspot/src/share/vm/oops/constantPool.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -228,7 +228,7 @@
} else {
do_resolve = true;
name = this_oop->unresolved_klass_at(which);
- loader = Handle(THREAD, InstanceKlass::cast(this_oop->pool_holder())->class_loader());
+ loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
}
}
} // unlocking constantPool
@@ -247,7 +247,7 @@
if (do_resolve) {
// this_oop must be unlocked during resolve_or_fail
- oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
+ oop protection_domain = this_oop->pool_holder()->protection_domain();
Handle h_prot (THREAD, protection_domain);
Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
KlassHandle k;
@@ -315,7 +315,7 @@
vframeStream vfst(JavaThread::current());
if (!vfst.at_end()) {
line_number = vfst.method()->line_number_from_bci(vfst.bci());
- Symbol* s = InstanceKlass::cast(vfst.method()->method_holder())->source_file_name();
+ Symbol* s = vfst.method()->method_holder()->source_file_name();
if (s != NULL) {
source_file = s->as_C_string();
}
@@ -325,11 +325,11 @@
// only print something if the classes are different
if (source_file != NULL) {
tty->print("RESOLVE %s %s %s:%d\n",
- InstanceKlass::cast(this_oop->pool_holder())->external_name(),
+ this_oop->pool_holder()->external_name(),
InstanceKlass::cast(k())->external_name(), source_file, line_number);
} else {
tty->print("RESOLVE %s %s\n",
- InstanceKlass::cast(this_oop->pool_holder())->external_name(),
+ this_oop->pool_holder()->external_name(),
InstanceKlass::cast(k())->external_name());
}
}
@@ -339,7 +339,7 @@
// Only updated constant pool - if it is resolved.
do_resolve = this_oop->tag_at(which).is_unresolved_klass();
if (do_resolve) {
- ClassLoaderData* this_key = InstanceKlass::cast(this_oop->pool_holder())->class_loader_data();
+ ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
if (!this_key->is_the_null_class_loader_data()) {
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
}
@@ -367,8 +367,8 @@
assert(entry.is_unresolved(), "must be either symbol or klass");
Thread *thread = Thread::current();
Symbol* name = entry.get_symbol();
- oop loader = InstanceKlass::cast(this_oop->pool_holder())->class_loader();
- oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
+ oop loader = this_oop->pool_holder()->class_loader();
+ oop protection_domain = this_oop->pool_holder()->protection_domain();
Handle h_prot (thread, protection_domain);
Handle h_loader (thread, loader);
Klass* k = SystemDictionary::find(name, h_loader, h_prot, thread);
@@ -409,8 +409,8 @@
} else {
assert(entry.is_unresolved(), "must be either symbol or klass");
Symbol* name = entry.get_symbol();
- oop loader = InstanceKlass::cast(this_oop->pool_holder())->class_loader();
- oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
+ oop loader = this_oop->pool_holder()->class_loader();
+ oop protection_domain = this_oop->pool_holder()->protection_domain();
Handle h_loader(THREAD, loader);
Handle h_prot (THREAD, protection_domain);
KlassHandle k(THREAD, SystemDictionary::find(name, h_loader, h_prot, THREAD));
@@ -1143,16 +1143,21 @@
int from_oplen = operand_array_length(from_cp->operands());
int old_oplen = operand_array_length(to_cp->operands());
if (from_oplen != 0) {
+ ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data();
// append my operands to the target's operands array
if (old_oplen == 0) {
- to_cp->set_operands(from_cp->operands()); // reuse; do not merge
+ // Can't just reuse from_cp's operand list because of deallocation issues
+ int len = from_cp->operands()->length();
+ Array<u2>* new_ops = MetadataFactory::new_array<u2>(loader_data, len, CHECK);
+ Copy::conjoint_memory_atomic(
+ from_cp->operands()->adr_at(0), new_ops->adr_at(0), len * sizeof(u2));
+ to_cp->set_operands(new_ops);
} else {
int old_len = to_cp->operands()->length();
int from_len = from_cp->operands()->length();
int old_off = old_oplen * sizeof(u2);
int from_off = from_oplen * sizeof(u2);
// Use the metaspace for the destination constant pool
- ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data();
Array<u2>* new_operands = MetadataFactory::new_array<u2>(loader_data, old_len + from_len, CHECK);
int fillp = 0, len = 0;
// first part of dest
@@ -1785,7 +1790,7 @@
assert(cp_patches->at(index).is_null(),
err_msg("Unused constant pool patch at %d in class file %s",
index,
- InstanceKlass::cast(pool_holder())->external_name()));
+ pool_holder()->external_name()));
}
#endif // ASSERT
}
@@ -1943,7 +1948,7 @@
st->print(" for ");
pool_holder()->print_value_on(st);
if (pool_holder() != NULL) {
- bool extra = (InstanceKlass::cast(pool_holder())->constants() != this);
+ bool extra = (pool_holder()->constants() != this);
if (extra) st->print(" (extra)");
}
if (cache() != NULL) {
--- a/hotspot/src/share/vm/oops/constantPool.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -86,8 +86,8 @@
friend class Universe; // For null constructor
private:
Array<u1>* _tags; // the tag array describing the constant pool's contents
- ConstantPoolCache* _cache; // the cache holding interpreter runtime information
- Klass* _pool_holder; // the corresponding class
+ ConstantPoolCache* _cache; // the cache holding interpreter runtime information
+ InstanceKlass* _pool_holder; // the corresponding class
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
// Array of resolved objects from the constant pool and map from resolved
@@ -193,9 +193,9 @@
void set_on_stack(const bool value);
// Klass holding pool
- Klass* pool_holder() const { return _pool_holder; }
- void set_pool_holder(Klass* k) { _pool_holder = k; }
- Klass** pool_holder_addr() { return &_pool_holder; }
+ InstanceKlass* pool_holder() const { return _pool_holder; }
+ void set_pool_holder(InstanceKlass* k) { _pool_holder = k; }
+ InstanceKlass** pool_holder_addr() { return &_pool_holder; }
// Interpreter runtime support
ConstantPoolCache* cache() const { return _cache; }
--- a/hotspot/src/share/vm/oops/cpCache.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -231,8 +231,8 @@
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) {
- Klass* interf = method->method_holder();
- assert(InstanceKlass::cast(interf)->is_interface(), "must be an interface");
+ InstanceKlass* interf = method->method_holder();
+ assert(interf->is_interface(), "must be an interface");
assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here");
set_f1(interf);
set_f2(index);
@@ -243,25 +243,17 @@
}
-void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool,
- methodHandle adapter,
- Handle appendix, Handle method_type,
- objArrayHandle resolved_references) {
- set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references);
+void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, const CallInfo &call_info) {
+ set_method_handle_common(cpool, Bytecodes::_invokehandle, call_info);
}
-void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool,
- methodHandle adapter,
- Handle appendix, Handle method_type,
- objArrayHandle resolved_references) {
- set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references);
+void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, const CallInfo &call_info) {
+ set_method_handle_common(cpool, Bytecodes::_invokedynamic, call_info);
}
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
Bytecodes::Code invoke_code,
- methodHandle adapter,
- Handle appendix, Handle method_type,
- objArrayHandle resolved_references) {
+ const CallInfo &call_info) {
// NOTE: This CPCE can be the subject of data races.
// There are three words to update: flags, refs[f2], f1 (in that order).
// Writers must store all other values before f1.
@@ -276,6 +268,9 @@
return;
}
+ const methodHandle adapter = call_info.resolved_method();
+ const Handle appendix = call_info.resolved_appendix();
+ const Handle method_type = call_info.resolved_method_type();
const bool has_appendix = appendix.not_null();
const bool has_method_type = method_type.not_null();
@@ -315,6 +310,7 @@
// This allows us to create fewer method oops, while keeping type safety.
//
+ objArrayHandle resolved_references = cpool->resolved_references();
// Store appendix, if any.
if (has_appendix) {
const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
@@ -421,7 +417,7 @@
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
- Klass::cast(old_method->method_holder())->external_name()));
+ old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
@@ -449,7 +445,7 @@
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
- Klass::cast(old_method->method_holder())->external_name()));
+ old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
--- a/hotspot/src/share/vm/oops/cpCache.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -117,6 +117,8 @@
// The fields are volatile so that they are stored in the order written in the
// source code. The _indices field with the bytecode must be written last.
+class CallInfo;
+
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
friend class constantPoolCacheKlass;
@@ -223,18 +225,12 @@
void set_method_handle(
constantPoolHandle cpool, // holding constant pool (required for locking)
- methodHandle method, // adapter for invokeExact, etc.
- Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.MethodType
- Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
- objArrayHandle resolved_references
+ const CallInfo &call_info // Call link information
);
void set_dynamic_call(
constantPoolHandle cpool, // holding constant pool (required for locking)
- methodHandle method, // adapter for this call site
- Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.CallSite
- Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
- objArrayHandle resolved_references
+ const CallInfo &call_info // Call link information
);
// Common code for invokedynamic and MH invocations.
@@ -255,10 +251,7 @@
void set_method_handle_common(
constantPoolHandle cpool, // holding constant pool (required for locking)
Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic
- methodHandle adapter, // invoker method (f1)
- Handle appendix, // appendix such as CallSite, MethodType, etc. (refs[f2+0])
- Handle method_type, // MethodType (refs[f2+1])
- objArrayHandle resolved_references
+ const CallInfo &call_info // Call link information
);
// invokedynamic and invokehandle call sites have two entries in the
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -743,6 +743,35 @@
}
}
+ if (this_oop->has_default_methods()) {
+ // Step 7.5: initialize any interfaces which have default methods
+ for (int i = 0; i < this_oop->local_interfaces()->length(); ++i) {
+ Klass* iface = this_oop->local_interfaces()->at(i);
+ InstanceKlass* ik = InstanceKlass::cast(iface);
+ if (ik->has_default_methods() && ik->should_be_initialized()) {
+ ik->initialize(THREAD);
+
+ if (HAS_PENDING_EXCEPTION) {
+ Handle e(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ {
+ EXCEPTION_MARK;
+ // Locks object, set state, and notify all waiting threads
+ this_oop->set_initialization_state_and_notify(
+ initialization_error, THREAD);
+
+ // ignore any exception thrown, superclass initialization error is
+ // thrown below
+ CLEAR_PENDING_EXCEPTION;
+ }
+ DTRACE_CLASSINIT_PROBE_WAIT(
+ super__failed, InstanceKlass::cast(this_oop()), -1, wait);
+ THROW_OOP(e());
+ }
+ }
+ }
+ }
+
// Step 8
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
@@ -1252,11 +1281,7 @@
}
#endif
-Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
- return InstanceKlass::find_method(methods(), name, signature);
-}
-
-Method* InstanceKlass::find_method(Array<Method*>* methods, Symbol* name, Symbol* signature) {
+static int binary_search(Array<Method*>* methods, Symbol* name) {
int len = methods->length();
// methods are sorted, so do binary search
int l = 0;
@@ -1267,43 +1292,70 @@
assert(m->is_method(), "must be method");
int res = m->name()->fast_compare(name);
if (res == 0) {
- // found matching name; do linear search to find matching signature
- // first, quick check for common case
- if (m->signature() == signature) return m;
- // search downwards through overloaded methods
- int i;
- for (i = mid - 1; i >= l; i--) {
- Method* m = methods->at(i);
- assert(m->is_method(), "must be method");
- if (m->name() != name) break;
- if (m->signature() == signature) return m;
- }
- // search upwards
- for (i = mid + 1; i <= h; i++) {
- Method* m = methods->at(i);
- assert(m->is_method(), "must be method");
- if (m->name() != name) break;
- if (m->signature() == signature) return m;
- }
- // not found
-#ifdef ASSERT
- int index = linear_search(methods, name, signature);
- assert(index == -1, err_msg("binary search should have found entry %d", index));
-#endif
- return NULL;
+ return mid;
} else if (res < 0) {
l = mid + 1;
} else {
h = mid - 1;
}
}
+ return -1;
+}
+
+Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
+ return InstanceKlass::find_method(methods(), name, signature);
+}
+
+Method* InstanceKlass::find_method(
+ Array<Method*>* methods, Symbol* name, Symbol* signature) {
+ int hit = binary_search(methods, name);
+ if (hit != -1) {
+ Method* m = methods->at(hit);
+ // Do linear search to find matching signature. First, quick check
+ // for common case
+ if (m->signature() == signature) return m;
+ // search downwards through overloaded methods
+ int i;
+ for (i = hit - 1; i >= 0; --i) {
+ Method* m = methods->at(i);
+ assert(m->is_method(), "must be method");
+ if (m->name() != name) break;
+ if (m->signature() == signature) return m;
+ }
+ // search upwards
+ for (i = hit + 1; i < methods->length(); ++i) {
+ Method* m = methods->at(i);
+ assert(m->is_method(), "must be method");
+ if (m->name() != name) break;
+ if (m->signature() == signature) return m;
+ }
+ // not found
#ifdef ASSERT
- int index = linear_search(methods, name, signature);
- assert(index == -1, err_msg("binary search should have found entry %d", index));
+ int index = linear_search(methods, name, signature);
+ assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
+ }
return NULL;
}
+int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
+ return find_method_by_name(methods(), name, end);
+}
+
+int InstanceKlass::find_method_by_name(
+ Array<Method*>* methods, Symbol* name, int* end_ptr) {
+ assert(end_ptr != NULL, "just checking");
+ int start = binary_search(methods, name);
+ int end = start + 1;
+ if (start != -1) {
+ while (start - 1 >= 0 && (methods->at(start - 1))->name() == name) --start;
+ while (end < methods->length() && (methods->at(end))->name() == name) ++end;
+ *end_ptr = end;
+ return start;
+ }
+ return -1;
+}
+
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -245,6 +245,10 @@
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
jint _cached_class_file_len; // JVMTI: length of above
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
+
+ // true if class, superclass, or implemented interfaces have default methods
+ bool _has_default_methods;
+
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// Method array.
Array<Method*>* _methods;
@@ -492,6 +496,13 @@
// (returns NULL if not found)
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
+ // Find method indices by name. If a method with the specified name is
+ // found the index to the first method is returned, and 'end' is filled in
+ // with the index of first non-name-matching method. If no method is found
+ // -1 is returned.
+ int find_method_by_name(Symbol* name, int* end);
+ static int find_method_by_name(Array<Method*>* methods, Symbol* name, int* end);
+
// constant pool
ConstantPool* constants() const { return _constants; }
void set_constants(ConstantPool* c) { _constants = c; }
@@ -592,6 +603,9 @@
return _jvmti_cached_class_field_map;
}
+ bool has_default_methods() const { return _has_default_methods; }
+ void set_has_default_methods(bool b) { _has_default_methods = b; }
+
// for adding methods, ConstMethod::UNSET_IDNUM means no more ids available
inline u2 next_method_idnum();
void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; }
@@ -728,7 +742,6 @@
GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
bool compute_is_subtype_of(Klass* k);
bool can_be_primary_super_slow() const;
- Klass* java_super() const { return super(); }
int oop_size(oop obj) const { return size_helper(); }
bool oop_is_instance_slow() const { return true; }
@@ -750,6 +763,10 @@
return (InstanceKlass*) k;
}
+ InstanceKlass* java_super() const {
+ return (super() == NULL) ? NULL : cast(super());
+ }
+
// Sizing (in words)
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
static int size(int vtable_length, int itable_length,
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -54,22 +54,16 @@
// the same name and signature as m), then m is a Miranda method which is
// entered as a public abstract method in C's vtable. From then on it should
// treated as any other public method in C for method over-ride purposes.
-void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length,
- int &num_miranda_methods,
- Klass* super,
- Array<Method*>* methods,
- AccessFlags class_flags,
- Handle classloader,
- Symbol* classname,
- Array<Klass*>* local_interfaces,
- TRAPS
- ) {
-
+void klassVtable::compute_vtable_size_and_num_mirandas(
+ int* vtable_length_ret, int* num_new_mirandas,
+ GrowableArray<Method*>* all_mirandas, Klass* super,
+ Array<Method*>* methods, AccessFlags class_flags,
+ Handle classloader, Symbol* classname, Array<Klass*>* local_interfaces,
+ TRAPS) {
No_Safepoint_Verifier nsv;
// set up default result values
- vtable_length = 0;
- num_miranda_methods = 0;
+ int vtable_length = 0;
// start off with super's vtable length
InstanceKlass* sk = (InstanceKlass*)super;
@@ -86,9 +80,12 @@
}
}
+ GrowableArray<Method*> new_mirandas(20);
// compute the number of mirandas methods that must be added to the end
- num_miranda_methods = get_num_mirandas(super, methods, local_interfaces);
- vtable_length += (num_miranda_methods * vtableEntry::size());
+ get_mirandas(&new_mirandas, all_mirandas, super, methods, local_interfaces);
+ *num_new_mirandas = new_mirandas.length();
+
+ vtable_length += *num_new_mirandas * vtableEntry::size();
if (Universe::is_bootstrapping() && vtable_length == 0) {
// array classes don't have their superclass set correctly during
@@ -109,6 +106,8 @@
"bad vtable size for class Object");
assert(vtable_length % vtableEntry::size() == 0, "bad vtable length");
assert(vtable_length >= Universe::base_vtable_size(), "vtable too small");
+
+ *vtable_length_ret = vtable_length;
}
int klassVtable::index_of(Method* m, int len) const {
@@ -191,7 +190,7 @@
}
// add miranda methods; it will also update the value of initialized
- fill_in_mirandas(initialized);
+ fill_in_mirandas(&initialized);
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
// package_private -> publicprotected), the vtable might actually be smaller than our initial
@@ -249,6 +248,11 @@
return superk;
}
+// Methods that are "effectively" final don't need vtable entries.
+bool method_is_effectively_final(
+ AccessFlags klass_flags, methodHandle target) {
+ return target->is_final() || klass_flags.is_final() && !target->is_overpass();
+}
// Update child's copy of super vtable for overrides
// OR return true if a new vtable entry is required
@@ -269,7 +273,7 @@
return false;
}
- if (klass->is_final() || target_method()->is_final()) {
+ if (method_is_effectively_final(klass->access_flags(), target_method)) {
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
@@ -303,7 +307,7 @@
if (super_method->name() == name && super_method->signature() == signature) {
// get super_klass for method_holder for the found method
- InstanceKlass* super_klass = InstanceKlass::cast(super_method->method_holder());
+ InstanceKlass* super_klass = super_method->method_holder();
if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
@@ -406,7 +410,8 @@
Symbol* classname,
AccessFlags class_flags,
TRAPS) {
- if ((class_flags.is_final() || target_method()->is_final()) ||
+
+ if (method_is_effectively_final(class_flags, target_method) ||
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
@@ -447,7 +452,7 @@
}
// get the class holding the matching method
// make sure you use that class for is_override
- InstanceKlass* superk = InstanceKlass::cast(super_method->method_holder());
+ InstanceKlass* superk = super_method->method_holder();
// we want only instance method matches
// pretend private methods are not in the super vtable
// since we do override around them: e.g. a.m pub/b.m private/c.m pub,
@@ -502,7 +507,7 @@
// miranda methods are interface methods in a class's vtable
if (mhk->is_interface()) {
- assert(m->is_public() && m->is_abstract(), "should be public and abstract");
+ assert(m->is_public(), "should be public");
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method");
return true;
@@ -532,19 +537,19 @@
return false;
}
-void klassVtable::add_new_mirandas_to_list(GrowableArray<Method*>* list_of_current_mirandas,
- Array<Method*>* current_interface_methods,
- Array<Method*>* class_methods,
- Klass* super) {
+void klassVtable::add_new_mirandas_to_lists(
+ GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
+ Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
+ Klass* super) {
// iterate thru the current interface's method to see if it a miranda
int num_methods = current_interface_methods->length();
for (int i = 0; i < num_methods; i++) {
Method* im = current_interface_methods->at(i);
bool is_duplicate = false;
- int num_of_current_mirandas = list_of_current_mirandas->length();
+ int num_of_current_mirandas = new_mirandas->length();
// check for duplicate mirandas in different interfaces we implement
for (int j = 0; j < num_of_current_mirandas; j++) {
- Method* miranda = list_of_current_mirandas->at(j);
+ Method* miranda = new_mirandas->at(j);
if ((im->name() == miranda->name()) &&
(im->signature() == miranda->signature())) {
is_duplicate = true;
@@ -557,51 +562,47 @@
InstanceKlass *sk = InstanceKlass::cast(super);
// check if it is a duplicate of a super's miranda
if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
- list_of_current_mirandas->append(im);
+ new_mirandas->append(im);
+ }
+ if (all_mirandas != NULL) {
+ all_mirandas->append(im);
}
}
}
}
}
-void klassVtable::get_mirandas(GrowableArray<Method*>* mirandas,
+void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
+ GrowableArray<Method*>* all_mirandas,
Klass* super, Array<Method*>* class_methods,
Array<Klass*>* local_interfaces) {
- assert((mirandas->length() == 0) , "current mirandas must be 0");
+ assert((new_mirandas->length() == 0) , "current mirandas must be 0");
// iterate thru the local interfaces looking for a miranda
int num_local_ifs = local_interfaces->length();
for (int i = 0; i < num_local_ifs; i++) {
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
- add_new_mirandas_to_list(mirandas, ik->methods(), class_methods, super);
+ add_new_mirandas_to_lists(new_mirandas, all_mirandas,
+ ik->methods(), class_methods, super);
// iterate thru each local's super interfaces
Array<Klass*>* super_ifs = ik->transitive_interfaces();
int num_super_ifs = super_ifs->length();
for (int j = 0; j < num_super_ifs; j++) {
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
- add_new_mirandas_to_list(mirandas, sik->methods(), class_methods, super);
+ add_new_mirandas_to_lists(new_mirandas, all_mirandas,
+ sik->methods(), class_methods, super);
}
}
}
-// get number of mirandas
-int klassVtable::get_num_mirandas(Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces) {
- ResourceMark rm;
- GrowableArray<Method*>* mirandas = new GrowableArray<Method*>(20);
- get_mirandas(mirandas, super, class_methods, local_interfaces);
- return mirandas->length();
-}
-
// fill in mirandas
-void klassVtable::fill_in_mirandas(int& initialized) {
- ResourceMark rm;
- GrowableArray<Method*>* mirandas = new GrowableArray<Method*>(20);
- InstanceKlass *this_ik = ik();
- get_mirandas(mirandas, this_ik->super(), this_ik->methods(), this_ik->local_interfaces());
- int num_mirandas = mirandas->length();
- for (int i = 0; i < num_mirandas; i++) {
- put_method_at(mirandas->at(i), initialized);
- initialized++;
+void klassVtable::fill_in_mirandas(int* initialized) {
+ GrowableArray<Method*> mirandas(20);
+ get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
+ ik()->local_interfaces());
+ for (int i = 0; i < mirandas.length(); i++) {
+ put_method_at(mirandas.at(i), *initialized);
+ ++(*initialized);
}
}
@@ -629,7 +630,7 @@
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
- Klass::cast(old_method->method_holder())->external_name()));
+ old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
@@ -744,7 +745,7 @@
Method* target = klass->uncached_lookup_method(method_name, method_signature);
while (target != NULL && target->is_static()) {
// continue with recursive lookup through the superclass
- Klass* super = Klass::cast(target->method_holder())->super();
+ Klass* super = target->method_holder()->super();
target = (super == NULL) ? (Method*)NULL : Klass::cast(super)->uncached_lookup_method(method_name, method_signature);
}
if (target == NULL || !target->is_public() || target->is_abstract()) {
@@ -754,7 +755,7 @@
// if checkconstraints requested
methodHandle target_h (THREAD, target); // preserve across gc
if (checkconstraints) {
- Handle method_holder_loader (THREAD, InstanceKlass::cast(target->method_holder())->class_loader());
+ Handle method_holder_loader (THREAD, target->method_holder()->class_loader());
if (method_holder_loader() != interface_loader()) {
ResourceMark rm(THREAD);
char* failed_type_name =
@@ -824,7 +825,7 @@
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
- Klass::cast(old_method->method_holder())->external_name()));
+ old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
@@ -959,9 +960,9 @@
// m must be a method in an interface
int klassItable::compute_itable_index(Method* m) {
- Klass* intf = m->method_holder();
- assert(InstanceKlass::cast(intf)->is_interface(), "sanity check");
- Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
+ InstanceKlass* intf = m->method_holder();
+ assert(intf->is_interface(), "sanity check");
+ Array<Method*>* methods = intf->methods();
int index = 0;
while(methods->at(index) != m) {
index++;
--- a/hotspot/src/share/vm/oops/klassVtable.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -84,11 +84,11 @@
bool is_initialized();
// computes vtable length (in words) and the number of miranda methods
- static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods,
- Klass* super, Array<Method*>* methods,
- AccessFlags class_flags, Handle classloader,
- Symbol* classname, Array<Klass*>* local_interfaces,
- TRAPS);
+ static void compute_vtable_size_and_num_mirandas(
+ int* vtable_length, int* num_new_mirandas,
+ GrowableArray<Method*>* all_mirandas, Klass* super,
+ Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
+ Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
// RedefineClasses() API support:
// If any entry of this vtable points to any of old_methods,
@@ -125,12 +125,17 @@
// support for miranda methods
bool is_miranda_entry_at(int i);
- void fill_in_mirandas(int& initialized);
+ void fill_in_mirandas(int* initialized);
static bool is_miranda(Method* m, Array<Method*>* class_methods, Klass* super);
- static void add_new_mirandas_to_list(GrowableArray<Method*>* list_of_current_mirandas, Array<Method*>* current_interface_methods, Array<Method*>* class_methods, Klass* super);
- static void get_mirandas(GrowableArray<Method*>* mirandas, Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
- static int get_num_mirandas(Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
-
+ static void add_new_mirandas_to_lists(
+ GrowableArray<Method*>* new_mirandas,
+ GrowableArray<Method*>* all_mirandas,
+ Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
+ Klass* super);
+ static void get_mirandas(
+ GrowableArray<Method*>* new_mirandas,
+ GrowableArray<Method*>* all_mirandas, Klass* super,
+ Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
void verify_against(outputStream* st, klassVtable* vt, int index);
inline InstanceKlass* ik() const;
--- a/hotspot/src/share/vm/oops/method.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/method.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -35,6 +35,7 @@
#include "memory/generation.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
+#include "oops/constMethod.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
@@ -57,22 +58,24 @@
// Implementation of Method
Method* Method::allocate(ClassLoaderData* loader_data,
- int byte_code_size,
- AccessFlags access_flags,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- TRAPS) {
+ int byte_code_size,
+ AccessFlags access_flags,
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ ConstMethod::MethodType method_type,
+ TRAPS) {
assert(!access_flags.is_native() || byte_code_size == 0,
"native methods should not contain byte codes");
ConstMethod* cm = ConstMethod::allocate(loader_data,
- byte_code_size,
- compressed_line_number_size,
- localvariable_table_length,
- exception_table_length,
- checked_exceptions_length,
- CHECK_NULL);
+ byte_code_size,
+ compressed_line_number_size,
+ localvariable_table_length,
+ exception_table_length,
+ checked_exceptions_length,
+ method_type,
+ CHECK_NULL);
int size = Method::size(access_flags.is_native());
@@ -240,12 +243,12 @@
warning("oopmap should only be accessed by the "
"VM, GC task or CMS threads (or during debugging)");
InterpreterOopMap local_mask;
- InstanceKlass::cast(method_holder())->mask_for(h_this, bci, &local_mask);
+ method_holder()->mask_for(h_this, bci, &local_mask);
local_mask.print();
}
}
#endif
- InstanceKlass::cast(method_holder())->mask_for(h_this, bci, mask);
+ method_holder()->mask_for(h_this, bci, mask);
return;
}
@@ -520,7 +523,7 @@
bool Method::is_final_method() const {
// %%% Should return true for private methods also,
// since there is no way to override them.
- return is_final() || Klass::cast(method_holder())->is_final();
+ return is_final() || method_holder()->is_final();
}
@@ -552,7 +555,7 @@
bool Method::has_valid_initializer_flags() const {
return (is_static() ||
- InstanceKlass::cast(method_holder())->major_version() < 51);
+ method_holder()->major_version() < 51);
}
bool Method::is_static_initializer() const {
@@ -614,7 +617,7 @@
if( constants()->tag_at(klass_index).is_unresolved_klass() ) {
Thread *thread = Thread::current();
Symbol* klass_name = constants()->klass_name_at(klass_index);
- Handle loader(thread, InstanceKlass::cast(method_holder())->class_loader());
+ Handle loader(thread, method_holder()->class_loader());
Handle prot (thread, Klass::cast(method_holder())->protection_domain());
return SystemDictionary::find(klass_name, loader, prot, thread) != NULL;
} else {
@@ -932,7 +935,7 @@
// If method is an interface, we skip it - except if it
// is a miranda method
- if (InstanceKlass::cast(method_holder())->is_interface()) {
+ if (method_holder()->is_interface()) {
// Check that method is not a miranda method
if (ik->lookup_method(name(), signature()) == NULL) {
// No implementation exist - so miranda method
@@ -1017,7 +1020,7 @@
ConstantPool* cp_oop = ConstantPool::allocate(loader_data, cp_length, CHECK_(empty));
cp = constantPoolHandle(THREAD, cp_oop);
}
- cp->set_pool_holder(holder());
+ cp->set_pool_holder(InstanceKlass::cast(holder()));
cp->symbol_at_put(_imcp_invoke_name, name);
cp->symbol_at_put(_imcp_invoke_signature, signature);
cp->set_preresolution();
@@ -1031,7 +1034,7 @@
methodHandle m;
{
Method* m_oop = Method::allocate(loader_data, 0, accessFlags_from(flags_bits),
- 0, 0, 0, 0, CHECK_(empty));
+ 0, 0, 0, 0, ConstMethod::NORMAL, CHECK_(empty));
m = methodHandle(THREAD, m_oop);
}
m->set_constants(cp());
@@ -1083,15 +1086,16 @@
int localvariable_len = m->localvariable_table_length();
int exception_table_len = m->exception_table_length();
- ClassLoaderData* loader_data = m()->method_holder()->class_loader_data();
+ ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
Method* newm_oop = Method::allocate(loader_data,
- new_code_length,
- flags,
- new_compressed_linenumber_size,
- localvariable_len,
- exception_table_len,
- checked_exceptions_len,
- CHECK_(methodHandle()));
+ new_code_length,
+ flags,
+ new_compressed_linenumber_size,
+ localvariable_len,
+ exception_table_len,
+ checked_exceptions_len,
+ m->method_type(),
+ CHECK_(methodHandle()));
methodHandle newm (THREAD, newm_oop);
int new_method_size = newm->method_size();
@@ -1233,8 +1237,8 @@
return false;
}
bool sig_is_loaded = true;
- Handle class_loader(THREAD, InstanceKlass::cast(m->method_holder())->class_loader());
- Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain());
+ Handle class_loader(THREAD, m->method_holder()->class_loader());
+ Handle protection_domain(THREAD, m->method_holder()->protection_domain());
ResourceMark rm(THREAD);
Symbol* signature = m->signature();
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
@@ -1260,8 +1264,8 @@
}
bool Method::has_unloaded_classes_in_signature(methodHandle m, TRAPS) {
- Handle class_loader(THREAD, InstanceKlass::cast(m->method_holder())->class_loader());
- Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain());
+ Handle class_loader(THREAD, m->method_holder()->class_loader());
+ Handle protection_domain(THREAD, m->method_holder()->protection_domain());
ResourceMark rm(THREAD);
Symbol* signature = m->signature();
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
@@ -1468,7 +1472,7 @@
Bytecodes::Code Method::orig_bytecode_at(int bci) const {
- BreakpointInfo* bp = InstanceKlass::cast(method_holder())->breakpoints();
+ BreakpointInfo* bp = method_holder()->breakpoints();
for (; bp != NULL; bp = bp->next()) {
if (bp->match(this, bci)) {
return bp->orig_bytecode();
@@ -1480,7 +1484,7 @@
void Method::set_orig_bytecode_at(int bci, Bytecodes::Code code) {
assert(code != Bytecodes::_breakpoint, "cannot patch breakpoints this way");
- BreakpointInfo* bp = InstanceKlass::cast(method_holder())->breakpoints();
+ BreakpointInfo* bp = method_holder()->breakpoints();
for (; bp != NULL; bp = bp->next()) {
if (bp->match(this, bci)) {
bp->set_orig_bytecode(code);
@@ -1490,7 +1494,7 @@
}
void Method::set_breakpoint(int bci) {
- InstanceKlass* ik = InstanceKlass::cast(method_holder());
+ InstanceKlass* ik = method_holder();
BreakpointInfo *bp = new BreakpointInfo(this, bci);
bp->set_next(ik->breakpoints());
ik->set_breakpoints(bp);
@@ -1499,7 +1503,7 @@
}
static void clear_matches(Method* m, int bci) {
- InstanceKlass* ik = InstanceKlass::cast(m->method_holder());
+ InstanceKlass* ik = m->method_holder();
BreakpointInfo* prev_bp = NULL;
BreakpointInfo* next_bp;
for (BreakpointInfo* bp = ik->breakpoints(); bp != NULL; bp = next_bp) {
@@ -1782,7 +1786,7 @@
bool Method::is_method_id(jmethodID mid) {
Method* m = resolve_jmethod_id(mid);
assert(m != NULL, "should be called with non-null method");
- InstanceKlass* ik = InstanceKlass::cast(m->method_holder());
+ InstanceKlass* ik = m->method_holder();
ClassLoaderData* cld = ik->class_loader_data();
if (cld->jmethod_ids() == NULL) return false;
return (cld->jmethod_ids()->contains((Method**)mid));
--- a/hotspot/src/share/vm/oops/method.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/oops/method.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -30,7 +30,6 @@
#include "compiler/oopMap.hpp"
#include "interpreter/invocationCounter.hpp"
#include "oops/annotations.hpp"
-#include "oops/constMethod.hpp"
#include "oops/constantPool.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
@@ -104,6 +103,7 @@
class LocalVariableTableElement;
class AdapterHandlerEntry;
class MethodData;
+class ConstMethod;
class Method : public Metadata {
friend class VMStructs;
@@ -158,14 +158,16 @@
// Constructor
Method(ConstMethod* xconst, AccessFlags access_flags, int size);
public:
+
static Method* allocate(ClassLoaderData* loader_data,
- int byte_code_size,
- AccessFlags access_flags,
- int compressed_line_number_size,
- int localvariable_table_length,
- int exception_table_length,
- int checked_exceptions_length,
- TRAPS);
+ int byte_code_size,
+ AccessFlags access_flags,
+ int compressed_line_number_size,
+ int localvariable_table_length,
+ int exception_table_length,
+ int checked_exceptions_length,
+ ConstMethod::MethodType method_type,
+ TRAPS);
Method() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -207,21 +209,21 @@
// annotations support
AnnotationArray* annotations() const {
- InstanceKlass* ik = InstanceKlass::cast(method_holder());
+ InstanceKlass* ik = method_holder();
if (ik->annotations() == NULL) {
return NULL;
}
return ik->annotations()->get_method_annotations_of(method_idnum());
}
AnnotationArray* parameter_annotations() const {
- InstanceKlass* ik = InstanceKlass::cast(method_holder());
+ InstanceKlass* ik = method_holder();
if (ik->annotations() == NULL) {
return NULL;
}
return ik->annotations()->get_method_parameter_annotations_of(method_idnum());
}
AnnotationArray* annotation_default() const {
- InstanceKlass* ik = InstanceKlass::cast(method_holder());
+ InstanceKlass* ik = method_holder();
if (ik->annotations() == NULL) {
return NULL;
}
@@ -494,7 +496,7 @@
{ return constMethod()->compressed_linenumber_table(); }
// method holder (the Klass* holding this method)
- Klass* method_holder() const { return constants()->pool_holder(); }
+ InstanceKlass* method_holder() const { return constants()->pool_holder(); }
void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments)
Symbol* klass_name() const; // returns the name of the method holder
@@ -695,18 +697,18 @@
// Get this method's jmethodID -- allocate if it doesn't exist
jmethodID jmethod_id() { methodHandle this_h(this);
- return InstanceKlass::get_jmethod_id(InstanceKlass::cast(method_holder()), this_h); }
+ return InstanceKlass::get_jmethod_id(method_holder(), this_h); }
// Lookup the jmethodID for this method. Return NULL if not found.
// NOTE that this function can be called from a signal handler
// (see AsyncGetCallTrace support for Forte Analyzer) and this
// needs to be async-safe. No allocation should be done and
// so handles are not used to avoid deadlock.
- jmethodID find_jmethod_id_or_null() { return InstanceKlass::cast(method_holder())->jmethod_id_or_null(this); }
+ jmethodID find_jmethod_id_or_null() { return method_holder()->jmethod_id_or_null(this); }
// JNI static invoke cached itable index accessors
- int cached_itable_index() { return InstanceKlass::cast(method_holder())->cached_itable_index(method_idnum()); }
- void set_cached_itable_index(int index) { InstanceKlass::cast(method_holder())->set_cached_itable_index(method_idnum(), index); }
+ int cached_itable_index() { return method_holder()->cached_itable_index(method_idnum()); }
+ void set_cached_itable_index(int index) { method_holder()->set_cached_itable_index(method_idnum(), index); }
// Support for inlining of intrinsic methods
vmIntrinsics::ID intrinsic_id() const { return (vmIntrinsics::ID) _intrinsic_id; }
@@ -725,14 +727,18 @@
void set_dont_inline(bool x) { _dont_inline = x; }
bool is_hidden() { return _hidden; }
void set_hidden(bool x) { _hidden = x; }
+ ConstMethod::MethodType method_type() const {
+ return _constMethod->method_type();
+ }
+ bool is_overpass() const { return method_type() == ConstMethod::OVERPASS; }
// On-stack replacement support
bool has_osr_nmethod(int level, bool match_level) {
- return InstanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
+ return method_holder()->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
}
nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level) {
- return InstanceKlass::cast(method_holder())->lookup_osr_nmethod(this, bci, level, match_level);
+ return method_holder()->lookup_osr_nmethod(this, bci, level, match_level);
}
// Inline cache support
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/opto/escape.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1386,12 +1386,12 @@
// Non-escaped allocation returned from Java or runtime call have
// unknown values in fields.
for (EdgeIterator i(pta); i.has_next(); i.next()) {
- PointsToNode* ptn = i.get();
- if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
- if (add_edge(ptn, phantom_obj)) {
+ PointsToNode* field = i.get();
+ if (field->is_Field() && field->as_Field()->is_oop()) {
+ if (add_edge(field, phantom_obj)) {
// New edge was added
new_edges++;
- add_field_uses_to_worklist(ptn->as_Field());
+ add_field_uses_to_worklist(field->as_Field());
}
}
}
@@ -1413,30 +1413,30 @@
// captured by Initialize node.
//
for (EdgeIterator i(pta); i.has_next(); i.next()) {
- PointsToNode* ptn = i.get(); // Field (AddP)
- if (!ptn->is_Field() || !ptn->as_Field()->is_oop())
+ PointsToNode* field = i.get(); // Field (AddP)
+ if (!field->is_Field() || !field->as_Field()->is_oop())
continue; // Not oop field
- int offset = ptn->as_Field()->offset();
+ int offset = field->as_Field()->offset();
if (offset == Type::OffsetBot) {
if (!visited_bottom_offset) {
// OffsetBot is used to reference array's element,
// always add reference to NULL to all Field nodes since we don't
// known which element is referenced.
- if (add_edge(ptn, null_obj)) {
+ if (add_edge(field, null_obj)) {
// New edge was added
new_edges++;
- add_field_uses_to_worklist(ptn->as_Field());
+ add_field_uses_to_worklist(field->as_Field());
visited_bottom_offset = true;
}
}
} else {
// Check only oop fields.
- const Type* adr_type = ptn->ideal_node()->as_AddP()->bottom_type();
+ const Type* adr_type = field->ideal_node()->as_AddP()->bottom_type();
if (adr_type->isa_rawptr()) {
#ifdef ASSERT
// Raw pointers are used for initializing stores so skip it
// since it should be recorded already
- Node* base = get_addp_base(ptn->ideal_node());
+ Node* base = get_addp_base(field->ideal_node());
assert(adr_type->isa_rawptr() && base->is_Proj() &&
(base->in(0) == alloc),"unexpected pointer type");
#endif
@@ -1446,10 +1446,54 @@
offsets_worklist.append(offset);
Node* value = NULL;
if (ini != NULL) {
- BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
- Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
- if (store != NULL && store->is_Store()) {
+ // StoreP::memory_type() == T_ADDRESS
+ BasicType ft = UseCompressedOops ? T_NARROWOOP : T_ADDRESS;
+ Node* store = ini->find_captured_store(offset, type2aelembytes(ft, true), phase);
+ // Make sure initializing store has the same type as this AddP.
+ // This AddP may reference non existing field because it is on a
+ // dead branch of bimorphic call which is not eliminated yet.
+ if (store != NULL && store->is_Store() &&
+ store->as_Store()->memory_type() == ft) {
value = store->in(MemNode::ValueIn);
+#ifdef ASSERT
+ if (VerifyConnectionGraph) {
+ // Verify that AddP already points to all objects the value points to.
+ PointsToNode* val = ptnode_adr(value->_idx);
+ assert((val != NULL), "should be processed already");
+ PointsToNode* missed_obj = NULL;
+ if (val->is_JavaObject()) {
+ if (!field->points_to(val->as_JavaObject())) {
+ missed_obj = val;
+ }
+ } else {
+ if (!val->is_LocalVar() || (val->edge_count() == 0)) {
+ tty->print_cr("----------init store has invalid value -----");
+ store->dump();
+ val->dump();
+ assert(val->is_LocalVar() && (val->edge_count() > 0), "should be processed already");
+ }
+ for (EdgeIterator j(val); j.has_next(); j.next()) {
+ PointsToNode* obj = j.get();
+ if (obj->is_JavaObject()) {
+ if (!field->points_to(obj->as_JavaObject())) {
+ missed_obj = obj;
+ break;
+ }
+ }
+ }
+ }
+ if (missed_obj != NULL) {
+ tty->print_cr("----------field---------------------------------");
+ field->dump();
+ tty->print_cr("----------missed referernce to object-----------");
+ missed_obj->dump();
+ tty->print_cr("----------object referernced by init store -----");
+ store->dump();
+ val->dump();
+ assert(!field->points_to(missed_obj->as_JavaObject()), "missed JavaObject reference");
+ }
+ }
+#endif
} else {
// There could be initializing stores which follow allocation.
// For example, a volatile field store is not collected
@@ -1462,10 +1506,10 @@
}
if (value == NULL) {
// A field's initializing value was not recorded. Add NULL.
- if (add_edge(ptn, null_obj)) {
+ if (add_edge(field, null_obj)) {
// New edge was added
new_edges++;
- add_field_uses_to_worklist(ptn->as_Field());
+ add_field_uses_to_worklist(field->as_Field());
}
}
}
@@ -1607,7 +1651,26 @@
}
// Verify that all fields have initializing values.
if (field->edge_count() == 0) {
+ tty->print_cr("----------field does not have references----------");
field->dump();
+ for (BaseIterator i(field); i.has_next(); i.next()) {
+ PointsToNode* base = i.get();
+ tty->print_cr("----------field has next base---------------------");
+ base->dump();
+ if (base->is_JavaObject() && (base != phantom_obj) && (base != null_obj)) {
+ tty->print_cr("----------base has fields-------------------------");
+ for (EdgeIterator j(base); j.has_next(); j.next()) {
+ j.get()->dump();
+ }
+ tty->print_cr("----------base has references---------------------");
+ for (UseIterator j(base); j.has_next(); j.next()) {
+ j.get()->dump();
+ }
+ }
+ }
+ for (UseIterator i(field); i.has_next(); i.next()) {
+ i.get()->dump();
+ }
assert(field->edge_count() > 0, "sanity");
}
}
@@ -1967,7 +2030,7 @@
if (is_JavaObject()) {
return (this == ptn);
}
- assert(is_LocalVar(), "sanity");
+ assert(is_LocalVar() || is_Field(), "sanity");
for (EdgeIterator i(this); i.has_next(); i.next()) {
if (i.get() == ptn)
return true;
@@ -3127,10 +3190,14 @@
EscapeState fields_es = fields_escape_state();
tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]);
if (nt == PointsToNode::JavaObject && !this->scalar_replaceable())
- tty->print("NSR");
+ tty->print("NSR ");
}
if (is_Field()) {
FieldNode* f = (FieldNode*)this;
+ if (f->is_oop())
+ tty->print("oop ");
+ if (f->offset() > 0)
+ tty->print("+%d ", f->offset());
tty->print("(");
for (BaseIterator i(f); i.has_next(); i.next()) {
PointsToNode* b = i.get();
--- a/hotspot/src/share/vm/prims/jni.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -2985,7 +2985,7 @@
}
// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
- JNIid* id = InstanceKlass::cast(fd.field_holder())->jni_id_for(fd.offset());
+ JNIid* id = fd.field_holder()->jni_id_for(fd.offset());
debug_only(id->set_is_static_field_id();)
debug_only(id->verify(fd.field_holder()));
@@ -4016,7 +4016,7 @@
if (PrintJNIResolving) {
ResourceMark rm(THREAD);
tty->print_cr("[Registering JNI native method %s.%s]",
- Klass::cast(method->method_holder())->external_name(),
+ method->method_holder()->external_name(),
method->name()->as_C_string());
}
return true;
--- a/hotspot/src/share/vm/prims/jvm.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -125,7 +125,7 @@
int line_number = -1;
const char * source_file = NULL;
const char * trace = "explicit";
- Klass* caller = NULL;
+ InstanceKlass* caller = NULL;
JavaThread* jthread = JavaThread::current();
if (jthread->has_last_Java_frame()) {
vframeStream vfst(jthread);
@@ -153,17 +153,17 @@
// that caller, otherwise keep quiet since this should be picked up elsewhere.
bool found_it = false;
if (!vfst.at_end() &&
- InstanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() &&
+ vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class() &&
vfst.method()->name() == vmSymbols::forName0_name()) {
vfst.next();
if (!vfst.at_end() &&
- InstanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class() &&
+ vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class() &&
vfst.method()->name() == vmSymbols::forName_name()) {
vfst.next();
found_it = true;
}
} else if (last_caller != NULL &&
- InstanceKlass::cast(last_caller->method_holder())->name() ==
+ last_caller->method_holder()->name() ==
vmSymbols::java_lang_ClassLoader() &&
(last_caller->name() == vmSymbols::loadClassInternal_name() ||
last_caller->name() == vmSymbols::loadClass_name())) {
@@ -182,7 +182,7 @@
// show method name if it's a native method
trace = vfst.method()->name_and_sig_as_C_string();
}
- Symbol* s = InstanceKlass::cast(caller)->source_file_name();
+ Symbol* s = caller->source_file_name();
if (s != NULL) {
source_file = s->as_C_string();
}
@@ -190,8 +190,8 @@
}
if (caller != NULL) {
if (to_class != caller) {
- const char * from = Klass::cast(caller)->external_name();
- const char * to = Klass::cast(to_class)->external_name();
+ const char * from = caller->external_name();
+ const char * to = to_class->external_name();
// print in a single call to reduce interleaving between threads
if (source_file != NULL) {
tty->print("RESOLVE %s %s %s:%d (%s)\n", from, to, source_file, line_number, trace);
@@ -1228,7 +1228,7 @@
privileged_context = Handle(thread, thread->privileged_stack_top()->privileged_context());
protection_domain = thread->privileged_stack_top()->protection_domain();
} else {
- protection_domain = InstanceKlass::cast(method->method_holder())->protection_domain();
+ protection_domain = method->method_holder()->protection_domain();
}
if ((previous_protection_domain != protection_domain) && (protection_domain != NULL)) {
@@ -3048,10 +3048,10 @@
Method* m = vfst.method();
if (!m->is_native()) {
- Klass* holder = m->method_holder();
- oop loader = InstanceKlass::cast(holder)->class_loader();
+ InstanceKlass* holder = m->method_holder();
+ oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
- return (jclass) JNIHandles::make_local(env, Klass::cast(holder)->java_mirror());
+ return (jclass) JNIHandles::make_local(env, holder->java_mirror());
}
}
}
@@ -3071,9 +3071,9 @@
Method* m = vfst.method();
if (!m->is_native()) {
- Klass* holder = m->method_holder();
+ InstanceKlass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
- oop loader = InstanceKlass::cast(holder)->class_loader();
+ oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
return JNIHandles::make_local(env, loader);
}
@@ -3148,9 +3148,9 @@
for(vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
if (!vfst.method()->is_native()) {
- Klass* holder = vfst.method()->method_holder();
+ InstanceKlass* holder = vfst.method()->method_holder();
assert(holder->is_klass(), "just checking");
- if (InstanceKlass::cast(holder)->name() == class_name_sym) {
+ if (holder->name() == class_name_sym) {
return depth;
}
depth++;
@@ -3171,9 +3171,9 @@
Method* m = vfst.method();
if (!m->is_native()) {
- Klass* holder = m->method_holder();
+ InstanceKlass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
- oop loader = InstanceKlass::cast(holder)->class_loader();
+ oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
return depth;
}
@@ -3322,8 +3322,7 @@
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
// UseNewReflection
vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
- Klass* holder = vfst.method()->method_holder();
- oop loader = InstanceKlass::cast(holder)->class_loader();
+ oop loader = vfst.method()->method_holder()->class_loader();
if (loader != NULL) {
return JNIHandles::make_local(env, loader);
}
@@ -3365,9 +3364,9 @@
!vfst.at_end() && loader == NULL;
vfst.next()) {
if (!vfst.method()->is_native()) {
- Klass* holder = vfst.method()->method_holder();
- loader = InstanceKlass::cast(holder)->class_loader();
- protection_domain = InstanceKlass::cast(holder)->protection_domain();
+ InstanceKlass* holder = vfst.method()->method_holder();
+ loader = holder->class_loader();
+ protection_domain = holder->protection_domain();
}
}
} else {
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -753,7 +753,7 @@
unsigned char* p = bytecodes;
Bytecodes::Code code;
- bool is_rewritten = InstanceKlass::cast(mh->method_holder())->is_rewritten();
+ bool is_rewritten = mh->method_holder()->is_rewritten();
while ((code = bs.next()) >= 0) {
assert(Bytecodes::is_java_code(code), "sanity check");
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -2822,7 +2822,7 @@
JavaThread* current_thread = JavaThread::current();
// does the klass have any local variable information?
- InstanceKlass* ik = InstanceKlass::cast(method_oop->method_holder());
+ InstanceKlass* ik = method_oop->method_holder();
if (!ik->access_flags().has_localvariable_table()) {
return (JVMTI_ERROR_ABSENT_INFORMATION);
}
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -233,7 +233,7 @@
methodHandle m = info.resolved_method();
KlassHandle defc = info.resolved_klass();
int vmindex = -1;
- if (defc->is_interface() && Klass::cast(m->method_holder())->is_interface()) {
+ if (defc->is_interface() && m->method_holder()->is_interface()) {
// LinkResolver does not report itable indexes! (fix this?)
vmindex = klassItable::compute_itable_index(m());
} else if (m->can_be_statically_bound()) {
@@ -749,8 +749,8 @@
DEBUG_ONLY(vmtarget = NULL); // safety
if (m.is_null()) break;
if (!have_defc) {
- Klass* defc = m->method_holder();
- java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
+ InstanceKlass* defc = m->method_holder();
+ java_lang_invoke_MemberName::set_clazz(mname(), defc->java_mirror());
}
if (!have_name) {
//not java_lang_String::create_from_symbol; let's intern member names
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -165,8 +165,7 @@
// Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_00024NativeLibrary_find
// gets found the first time around - otherwise an infinite loop can occure. This is
// another VM/library dependency
- Handle loader(THREAD,
- InstanceKlass::cast(method->method_holder())->class_loader());
+ Handle loader(THREAD, method->method_holder()->class_loader());
if (loader.is_null()) {
entry = lookup_special_native(jni_name);
if (entry == NULL) {
@@ -393,7 +392,7 @@
if (PrintJNIResolving) {
ResourceMark rm(THREAD);
tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]",
- Klass::cast(method->method_holder())->external_name(),
+ method->method_holder()->external_name(),
method->name()->as_C_string());
}
}
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -627,7 +627,7 @@
// negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg
if (m->is_abstract()) return (_msg = "abstract method");
// note: we allow ik->is_abstract()
- if (!InstanceKlass::cast(m->method_holder())->is_initialized()) return (_msg = "method holder not initialized");
+ if (!m->method_holder()->is_initialized()) return (_msg = "method holder not initialized");
if (m->is_native()) return (_msg = "native method");
nmethod* m_code = m->code();
if (m_code != NULL && m_code->code_size() > InlineSmallCode)
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1191,12 +1191,12 @@
if (!constant_pool->tag_at(index).is_symbol()) return;
- Handle class_loader (THREAD, InstanceKlass::cast(constant_pool->pool_holder())->class_loader());
+ Handle class_loader (THREAD, constant_pool->pool_holder()->class_loader());
Symbol* symbol = constant_pool->symbol_at(index);
// class name?
if (symbol->byte_at(0) != '(') {
- Handle protection_domain (THREAD, Klass::cast(constant_pool->pool_holder())->protection_domain());
+ Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain());
SystemDictionary::resolve_or_null(symbol, class_loader, protection_domain, CHECK);
return;
}
@@ -1206,7 +1206,7 @@
for (SignatureStream ss(symbol); !ss.is_done(); ss.next()) {
if (ss.is_object()) {
Symbol* class_name = ss.as_symbol(CHECK);
- Handle protection_domain (THREAD, Klass::cast(constant_pool->pool_holder())->protection_domain());
+ Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain());
SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK);
}
}
--- a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -36,7 +36,7 @@
oop fieldDescriptor::loader() const {
- return InstanceKlass::cast(_cp->pool_holder())->class_loader();
+ return _cp->pool_holder()->class_loader();
}
Symbol* fieldDescriptor::generic_signature() const {
@@ -45,7 +45,7 @@
}
int idx = 0;
- InstanceKlass* ik = InstanceKlass::cast(field_holder());
+ InstanceKlass* ik = field_holder();
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
if (idx == _index) {
return fs.generic_signature();
@@ -58,7 +58,7 @@
}
AnnotationArray* fieldDescriptor::annotations() const {
- InstanceKlass* ik = InstanceKlass::cast(field_holder());
+ InstanceKlass* ik = field_holder();
Array<AnnotationArray*>* md = ik->fields_annotations();
if (md == NULL)
return NULL;
--- a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -43,12 +43,12 @@
// update the access_flags for the field in the klass
void update_klass_field_access_flag() {
- InstanceKlass* ik = InstanceKlass::cast(field_holder());
+ InstanceKlass* ik = field_holder();
ik->field(index())->set_access_flags(_access_flags.as_short());
}
FieldInfo* field() const {
- InstanceKlass* ik = InstanceKlass::cast(field_holder());
+ InstanceKlass* ik = field_holder();
return ik->field(_index);
}
@@ -59,46 +59,46 @@
Symbol* signature() const {
return field()->signature(_cp);
}
- Klass* field_holder() const { return _cp->pool_holder(); }
- ConstantPool* constants() const { return _cp(); }
- AccessFlags access_flags() const { return _access_flags; }
- oop loader() const;
+ InstanceKlass* field_holder() const { return _cp->pool_holder(); }
+ ConstantPool* constants() const { return _cp(); }
+ AccessFlags access_flags() const { return _access_flags; }
+ oop loader() const;
// Offset (in words) of field from start of instanceOop / Klass*
- int offset() const { return field()->offset(); }
- Symbol* generic_signature() const;
- int index() const { return _index; }
- AnnotationArray* annotations() const;
+ int offset() const { return field()->offset(); }
+ Symbol* generic_signature() const;
+ int index() const { return _index; }
+ AnnotationArray* annotations() const;
// Initial field value
- bool has_initial_value() const { return field()->initval_index() != 0; }
- int initial_value_index() const { return field()->initval_index(); }
+ bool has_initial_value() const { return field()->initval_index() != 0; }
+ int initial_value_index() const { return field()->initval_index(); }
constantTag initial_value_tag() const; // The tag will return true on one of is_int(), is_long(), is_single(), is_double()
- jint int_initial_value() const;
- jlong long_initial_value() const;
- jfloat float_initial_value() const;
- jdouble double_initial_value() const;
- oop string_initial_value(TRAPS) const;
+ jint int_initial_value() const;
+ jlong long_initial_value() const;
+ jfloat float_initial_value() const;
+ jdouble double_initial_value() const;
+ oop string_initial_value(TRAPS) const;
// Field signature type
- BasicType field_type() const { return FieldType::basic_type(signature()); }
+ BasicType field_type() const { return FieldType::basic_type(signature()); }
// Access flags
- bool is_public() const { return access_flags().is_public(); }
- bool is_private() const { return access_flags().is_private(); }
- bool is_protected() const { return access_flags().is_protected(); }
- bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); }
+ bool is_public() const { return access_flags().is_public(); }
+ bool is_private() const { return access_flags().is_private(); }
+ bool is_protected() const { return access_flags().is_protected(); }
+ bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); }
- bool is_static() const { return access_flags().is_static(); }
- bool is_final() const { return access_flags().is_final(); }
- bool is_volatile() const { return access_flags().is_volatile(); }
- bool is_transient() const { return access_flags().is_transient(); }
+ bool is_static() const { return access_flags().is_static(); }
+ bool is_final() const { return access_flags().is_final(); }
+ bool is_volatile() const { return access_flags().is_volatile(); }
+ bool is_transient() const { return access_flags().is_transient(); }
- bool is_synthetic() const { return access_flags().is_synthetic(); }
+ bool is_synthetic() const { return access_flags().is_synthetic(); }
- bool is_field_access_watched() const { return access_flags().is_field_access_watched(); }
+ bool is_field_access_watched() const { return access_flags().is_field_access_watched(); }
bool is_field_modification_watched() const
- { return access_flags().is_field_modification_watched(); }
- bool has_generic_signature() const { return access_flags().field_has_generic_signature(); }
+ { return access_flags().is_field_modification_watched(); }
+ bool has_generic_signature() const { return access_flags().field_has_generic_signature(); }
void set_is_field_access_watched(const bool value) {
_access_flags.set_is_field_access_watched(value);
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -3596,6 +3596,15 @@
product(uintx, StringTableSize, 1009, \
"Number of buckets in the interned String table") \
\
+ develop(bool, TraceDefaultMethods, false, \
+ "Trace the default method processing steps") \
+ \
+ develop(bool, ParseAllGenericSignatures, false, \
+ "Parse all generic signatures while classloading") \
+ \
+ develop(bool, VerifyGenericSignatures, false, \
+ "Abort VM on erroneous or inconsistent generic signatures") \
+ \
product(bool, UseVMInterruptibleIO, false, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"EINTR for I/O operations results in OS_INTRPT. The default value"\
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -189,7 +189,7 @@
assert(method->name() == vmSymbols::object_initializer_name(), "Should only be called for default constructor");
assert(method->signature() == vmSymbols::void_method_signature(), "Should only be called for default constructor");
- InstanceKlass* ik = InstanceKlass::cast(method->method_holder());
+ InstanceKlass* ik = method->method_holder();
if (ik->is_initialized() && ik->has_vanilla_constructor()) {
// safe to skip constructor call
} else {
@@ -344,11 +344,11 @@
#ifdef ASSERT
- { Klass* holder = method->method_holder();
+ { InstanceKlass* holder = method->method_holder();
// A klass might not be initialized since JavaCall's might be used during the executing of
// the <clinit>. For example, a Thread.start might start executing on an object that is
// not fully initialized! (bad Java programming style)
- assert(InstanceKlass::cast(holder)->is_linked(), "rewritting must have taken place");
+ assert(holder->is_linked(), "rewritting must have taken place");
}
#endif
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -140,6 +140,7 @@
Monitor* JfrMsg_lock = NULL;
Mutex* JfrBuffer_lock = NULL;
Mutex* JfrStream_lock = NULL;
+Monitor* PeriodicTask_lock = NULL;
#define MAX_NUM_MUTEX 128
static Monitor * _mutex_array[MAX_NUM_MUTEX];
@@ -285,6 +286,7 @@
def(JfrMsg_lock , Monitor, nonleaf+2, true);
def(JfrBuffer_lock , Mutex, nonleaf+3, true);
def(JfrStream_lock , Mutex, nonleaf+4, true);
+ def(PeriodicTask_lock , Monitor, nonleaf+5, true);
}
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -142,6 +142,7 @@
extern Monitor* JfrMsg_lock; // protects JFR messaging
extern Mutex* JfrBuffer_lock; // protects JFR buffer operations
extern Mutex* JfrStream_lock; // protects JFR stream access
+extern Monitor* PeriodicTask_lock; // protects the periodic task structure
// A MutexLocker provides mutual exclusion with respect to a given mutex
// for the scope which contains the locker. The lock is an OS lock, not
--- a/hotspot/src/share/vm/runtime/reflection.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -56,14 +56,14 @@
vframeStream vfst(jthread);
// skip over any frames belonging to java.lang.Class
while (!vfst.at_end() &&
- InstanceKlass::cast(vfst.method()->method_holder())->name() == vmSymbols::java_lang_Class()) {
+ vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class()) {
vfst.next();
}
if (!vfst.at_end()) {
// this frame is a likely suspect
caller = vfst.method()->method_holder();
line_number = vfst.method()->line_number_from_bci(vfst.bci());
- Symbol* s = InstanceKlass::cast(vfst.method()->method_holder())->source_file_name();
+ Symbol* s = vfst.method()->method_holder()->source_file_name();
if (s != NULL) {
source_file = s->as_C_string();
}
@@ -472,6 +472,12 @@
return true;
}
+ // Also allow all accesses from
+ // java/lang/invoke/MagicLambdaImpl subclasses to succeed trivially.
+ if (current_class->is_subclass_of(SystemDictionary::lambda_MagicLambdaImpl_klass())) {
+ return true;
+ }
+
return can_relax_access_check_for(current_class, new_class, classloader_only);
}
@@ -564,6 +570,12 @@
return true;
}
+ // Also allow all accesses from
+ // java/lang/invoke/MagicLambdaImpl subclasses to succeed trivially.
+ if (current_class->is_subclass_of(SystemDictionary::lambda_MagicLambdaImpl_klass())) {
+ return true;
+ }
+
return can_relax_access_check_for(
current_class, field_class, classloader_only);
}
@@ -630,8 +642,8 @@
case T_OBJECT:
case T_ARRAY:
Symbol* name = ss->as_symbol(CHECK_NULL);
- oop loader = InstanceKlass::cast(method->method_holder())->class_loader();
- oop protection_domain = InstanceKlass::cast(method->method_holder())->protection_domain();
+ oop loader = method->method_holder()->class_loader();
+ oop protection_domain = method->method_holder()->protection_domain();
Klass* k = SystemDictionary::resolve_or_fail(
name,
Handle(THREAD, loader),
@@ -702,7 +714,7 @@
assert(!method()->is_initializer() ||
(for_constant_pool_access && method()->is_static()) ||
(method()->name() == vmSymbols::class_initializer_name()
- && Klass::cast(method()->method_holder())->is_interface() && JDK_Version::is_jdk12x_version()), "should call new_constructor instead");
+ && method()->method_holder()->is_interface() && JDK_Version::is_jdk12x_version()), "should call new_constructor instead");
instanceKlassHandle holder (THREAD, method->method_holder());
int slot = method->method_idnum();
@@ -820,7 +832,7 @@
Handle type = new_type(signature, holder, CHECK_NULL);
Handle rh = java_lang_reflect_Field::create(CHECK_NULL);
- java_lang_reflect_Field::set_clazz(rh(), Klass::cast(fd->field_holder())->java_mirror());
+ java_lang_reflect_Field::set_clazz(rh(), fd->field_holder()->java_mirror());
java_lang_reflect_Field::set_slot(rh(), fd->index());
java_lang_reflect_Field::set_name(rh(), name());
java_lang_reflect_Field::set_type(rh(), type());
@@ -888,7 +900,7 @@
method = reflected_method;
} else {
// resolve based on the receiver
- if (InstanceKlass::cast(reflected_method->method_holder())->is_interface()) {
+ if (reflected_method->method_holder()->is_interface()) {
// resolve interface call
if (ReflectionWrapResolutionErrors) {
// new default: 6531596
--- a/hotspot/src/share/vm/runtime/task.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/task.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -61,7 +61,7 @@
}
#endif
-void PeriodicTask::real_time_tick(size_t delay_time) {
+void PeriodicTask::real_time_tick(int delay_time) {
#ifndef PRODUCT
if (ProfilerCheckIntervals) {
_ticks++;
@@ -73,19 +73,39 @@
_intervalHistogram[ms]++;
}
#endif
- int orig_num_tasks = _num_tasks;
- for(int index = 0; index < _num_tasks; index++) {
- _tasks[index]->execute_if_pending(delay_time);
- if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself
- index--; // re-do current slot as it has changed
- orig_num_tasks = _num_tasks;
+
+ {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ int orig_num_tasks = _num_tasks;
+
+ for(int index = 0; index < _num_tasks; index++) {
+ _tasks[index]->execute_if_pending(delay_time);
+ if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself
+ index--; // re-do current slot as it has changed
+ orig_num_tasks = _num_tasks;
+ }
}
}
}
+int PeriodicTask::time_to_wait() {
+ MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
+ NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+
+ if (_num_tasks == 0) {
+ return 0; // sleep until shutdown or a task is enrolled
+ }
+
+ int delay = _tasks[0]->time_to_next_interval();
+ for (int index = 1; index < _num_tasks; index++) {
+ delay = MIN2(delay, _tasks[index]->time_to_next_interval());
+ }
+ return delay;
+}
+
PeriodicTask::PeriodicTask(size_t interval_time) :
- _counter(0), _interval(interval_time) {
+ _counter(0), _interval((int) interval_time) {
// Sanity check the interval time
assert(_interval >= PeriodicTask::min_interval &&
_interval <= PeriodicTask::max_interval &&
@@ -94,33 +114,40 @@
}
PeriodicTask::~PeriodicTask() {
- if (is_enrolled())
- disenroll();
-}
-
-bool PeriodicTask::is_enrolled() const {
- for(int index = 0; index < _num_tasks; index++)
- if (_tasks[index] == this) return true;
- return false;
+ disenroll();
}
void PeriodicTask::enroll() {
- assert(WatcherThread::watcher_thread() == NULL, "dynamic enrollment of tasks not yet supported");
+ MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
+ NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
- if (_num_tasks == PeriodicTask::max_tasks)
+ if (_num_tasks == PeriodicTask::max_tasks) {
fatal("Overflow in PeriodicTask table");
+ }
_tasks[_num_tasks++] = this;
+
+ WatcherThread* thread = WatcherThread::watcher_thread();
+ if (thread) {
+ thread->unpark();
+ } else {
+ WatcherThread::start();
+ }
}
void PeriodicTask::disenroll() {
- assert(WatcherThread::watcher_thread() == NULL ||
- Thread::current() == WatcherThread::watcher_thread(),
- "dynamic disenrollment currently only handled from WatcherThread from within task() method");
+ MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
+ NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
int index;
- for(index = 0; index < _num_tasks && _tasks[index] != this; index++);
- if (index == _num_tasks) return;
+ for(index = 0; index < _num_tasks && _tasks[index] != this; index++)
+ ;
+
+ if (index == _num_tasks) {
+ return;
+ }
+
_num_tasks--;
+
for (; index < _num_tasks; index++) {
_tasks[index] = _tasks[index+1];
}
--- a/hotspot/src/share/vm/runtime/task.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/task.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -49,12 +49,12 @@
static int num_tasks() { return _num_tasks; }
private:
- size_t _counter;
- const size_t _interval;
+ int _counter;
+ const int _interval;
static int _num_tasks;
static PeriodicTask* _tasks[PeriodicTask::max_tasks];
- static void real_time_tick(size_t delay_time);
+ static void real_time_tick(int delay_time);
#ifndef PRODUCT
static elapsedTimer _timer; // measures time between ticks
@@ -69,51 +69,36 @@
PeriodicTask(size_t interval_time); // interval is in milliseconds of elapsed time
~PeriodicTask();
- // Tells whether is enrolled
- bool is_enrolled() const;
-
// Make the task active
- // NOTE: this may only be called before the WatcherThread has been started
+ // For dynamic enrollment at the time T, the task will execute somewhere
+ // between T and T + interval_time.
void enroll();
// Make the task deactive
- // NOTE: this may only be called either while the WatcherThread is
- // inactive or by a task from within its task() method. One-shot or
- // several-shot tasks may be implemented this way.
void disenroll();
- void execute_if_pending(size_t delay_time) {
- _counter += delay_time;
- if (_counter >= _interval) {
+ void execute_if_pending(int delay_time) {
+ // make sure we don't overflow
+ jlong tmp = (jlong) _counter + (jlong) delay_time;
+
+ if (tmp >= (jlong) _interval) {
_counter = 0;
task();
+ } else {
+ _counter += delay_time;
}
}
// Returns how long (time in milliseconds) before the next time we should
// execute this task.
- size_t time_to_next_interval() const {
+ int time_to_next_interval() const {
assert(_interval > _counter, "task counter greater than interval?");
return _interval - _counter;
}
// Calculate when the next periodic task will fire.
// Called by the WatcherThread's run method.
- // This assumes that periodic tasks aren't entering the system
- // dynamically, except for during startup.
- static size_t time_to_wait() {
- if (_num_tasks == 0) {
- // Don't wait any more; shut down the thread since we don't
- // currently support dynamic enrollment.
- return 0;
- }
-
- size_t delay = _tasks[0]->time_to_next_interval();
- for (int index = 1; index < _num_tasks; index++) {
- delay = MIN2(delay, _tasks[index]->time_to_next_interval());
- }
- return delay;
- }
+ static int time_to_wait();
// The task to perform at each period
virtual void task() = 0;
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1217,6 +1217,7 @@
// timer interrupts exists on the platform.
WatcherThread* WatcherThread::_watcher_thread = NULL;
+bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false;
WatcherThread::WatcherThread() : Thread() {
@@ -1237,6 +1238,55 @@
}
}
+int WatcherThread::sleep() const {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+
+ // remaining will be zero if there are no tasks,
+ // causing the WatcherThread to sleep until a task is
+ // enrolled
+ int remaining = PeriodicTask::time_to_wait();
+ int time_slept = 0;
+
+ // we expect this to timeout - we only ever get unparked when
+ // we should terminate or when a new task has been enrolled
+ OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
+
+ jlong time_before_loop = os::javaTimeNanos();
+
+ for (;;) {
+ bool timedout = PeriodicTask_lock->wait(Mutex::_no_safepoint_check_flag, remaining);
+ jlong now = os::javaTimeNanos();
+
+ if (remaining == 0) {
+ // if we didn't have any tasks we could have waited for a long time
+ // consider the time_slept zero and reset time_before_loop
+ time_slept = 0;
+ time_before_loop = now;
+ } else {
+ // need to recalulate since we might have new tasks in _tasks
+ time_slept = (int) ((now - time_before_loop) / 1000000);
+ }
+
+ // Change to task list or spurious wakeup of some kind
+ if (timedout || _should_terminate) {
+ break;
+ }
+
+ remaining = PeriodicTask::time_to_wait();
+ if (remaining == 0) {
+ // Last task was just disenrolled so loop around and wait until
+ // another task gets enrolled
+ continue;
+ }
+
+ remaining -= time_slept;
+ if (remaining <= 0)
+ break;
+ }
+
+ return time_slept;
+}
+
void WatcherThread::run() {
assert(this == watcher_thread(), "just checking");
@@ -1249,26 +1299,7 @@
// Calculate how long it'll be until the next PeriodicTask work
// should be done, and sleep that amount of time.
- size_t time_to_wait = PeriodicTask::time_to_wait();
-
- // we expect this to timeout - we only ever get unparked when
- // we should terminate
- {
- OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
-
- jlong prev_time = os::javaTimeNanos();
- for (;;) {
- int res= _SleepEvent->park(time_to_wait);
- if (res == OS_TIMEOUT || _should_terminate)
- break;
- // spurious wakeup of some kind
- jlong now = os::javaTimeNanos();
- time_to_wait -= (now - prev_time) / 1000000;
- if (time_to_wait <= 0)
- break;
- prev_time = now;
- }
- }
+ int time_waited = sleep();
if (is_error_reported()) {
// A fatal error has happened, the error handler(VMError::report_and_die)
@@ -1298,13 +1329,7 @@
}
}
- PeriodicTask::real_time_tick(time_to_wait);
-
- // If we have no more tasks left due to dynamic disenrollment,
- // shut down the thread since we don't currently support dynamic enrollment
- if (PeriodicTask::num_tasks() == 0) {
- _should_terminate = true;
- }
+ PeriodicTask::real_time_tick(time_waited);
}
// Signal that it is terminated
@@ -1319,22 +1344,33 @@
}
void WatcherThread::start() {
- if (watcher_thread() == NULL) {
+ assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
+
+ if (watcher_thread() == NULL && _startable) {
_should_terminate = false;
// Create the single instance of WatcherThread
new WatcherThread();
}
}
+void WatcherThread::make_startable() {
+ assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
+ _startable = true;
+}
+
void WatcherThread::stop() {
+ {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ _should_terminate = true;
+ OrderAccess::fence(); // ensure WatcherThread sees update in main loop
+
+ WatcherThread* watcher = watcher_thread();
+ if (watcher != NULL)
+ watcher->unpark();
+ }
+
// it is ok to take late safepoints here, if needed
MutexLocker mu(Terminator_lock);
- _should_terminate = true;
- OrderAccess::fence(); // ensure WatcherThread sees update in main loop
-
- Thread* watcher = watcher_thread();
- if (watcher != NULL)
- watcher->_SleepEvent->unpark();
while(watcher_thread() != NULL) {
// This wait should make safepoint checks, wait without a timeout,
@@ -1352,6 +1388,11 @@
}
}
+void WatcherThread::unpark() {
+ MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ PeriodicTask_lock->notify();
+}
+
void WatcherThread::print_on(outputStream* st) const {
st->print("\"%s\" ", name());
Thread::print_on(st);
@@ -3658,12 +3699,18 @@
}
}
- // Start up the WatcherThread if there are any periodic tasks
- // NOTE: All PeriodicTasks should be registered by now. If they
- // aren't, late joiners might appear to start slowly (we might
- // take a while to process their first tick).
- if (PeriodicTask::num_tasks() > 0) {
- WatcherThread::start();
+ {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ // Make sure the watcher thread can be started by WatcherThread::start()
+ // or by dynamic enrollment.
+ WatcherThread::make_startable();
+ // Start up the WatcherThread if there are any periodic tasks
+ // NOTE: All PeriodicTasks should be registered by now. If they
+ // aren't, late joiners might appear to start slowly (we might
+ // take a while to process their first tick).
+ if (PeriodicTask::num_tasks() > 0) {
+ WatcherThread::start();
+ }
}
// Give os specific code one last chance to start
--- a/hotspot/src/share/vm/runtime/thread.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/thread.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -722,6 +722,7 @@
private:
static WatcherThread* _watcher_thread;
+ static bool _startable;
volatile static bool _should_terminate; // updated without holding lock
public:
enum SomeConstants {
@@ -738,6 +739,7 @@
char* name() const { return (char*)"VM Periodic Task Thread"; }
void print_on(outputStream* st) const;
void print() const { print_on(tty); }
+ void unpark();
// Returns the single instance of WatcherThread
static WatcherThread* watcher_thread() { return _watcher_thread; }
@@ -745,6 +747,12 @@
// Create and start the single instance of WatcherThread, or stop it on shutdown
static void start();
static void stop();
+ // Only allow start once the VM is sufficiently initialized
+ // Otherwise the first task to enroll will trigger the start
+ static void make_startable();
+
+ private:
+ int sleep() const;
};
--- a/hotspot/src/share/vm/runtime/vframe.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -161,7 +161,7 @@
// If this is the first frame, and java.lang.Object.wait(...) then print out the receiver.
if (frame_count == 0) {
if (method()->name() == vmSymbols::wait_name() &&
- InstanceKlass::cast(method()->method_holder())->name() == vmSymbols::java_lang_Object()) {
+ method()->method_holder()->name() == vmSymbols::java_lang_Object()) {
StackValueCollection* locs = locals();
if (!locs->is_empty()) {
StackValue* sv = locs->at(0);
@@ -407,7 +407,7 @@
if (Universe::reflect_invoke_cache()->is_same_method(method())) {
// This is Method.invoke() -- skip it
} else if (use_new_reflection &&
- Klass::cast(method()->method_holder())
+ method()->method_holder()
->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
// This is an auxilary frame -- skip it
} else if (method()->is_method_handle_intrinsic() ||
@@ -471,8 +471,8 @@
void vframeStreamCommon::skip_reflection_related_frames() {
while (!at_end() &&
(JDK_Version::is_gte_jdk14x_version() && UseNewReflection &&
- (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) ||
- Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) {
+ (method()->method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) ||
+ method()->method_holder()->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) {
next();
}
}
@@ -547,13 +547,13 @@
void javaVFrame::print_value() const {
Method* m = method();
- Klass* k = m->method_holder();
+ InstanceKlass* k = m->method_holder();
tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")",
_fr.sp(), _fr.unextended_sp(), _fr.fp(), _fr.pc());
tty->print("%s.%s", Klass::cast(k)->internal_name(), m->name()->as_C_string());
if (!m->is_native()) {
- Symbol* source_name = InstanceKlass::cast(k)->source_file_name();
+ Symbol* source_name = k->source_file_name();
int line_number = m->line_number_from_bci(bci());
if (source_name != NULL && (line_number != -1)) {
tty->print("(%s:%d)", source_name->as_C_string(), line_number);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -289,7 +289,7 @@
nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \
nonstatic_field(ConstantPool, _tags, Array<u1>*) \
nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
- nonstatic_field(ConstantPool, _pool_holder, Klass*) \
+ nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPool, _resolved_references, jobject) \
--- a/hotspot/src/share/vm/services/heapDumper.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/services/heapDumper.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -1117,8 +1117,8 @@
writer->write_symbolID(m->name()); // method's name
writer->write_symbolID(m->signature()); // method's signature
- assert(Klass::cast(m->method_holder())->oop_is_instance(), "not InstanceKlass");
- writer->write_symbolID(InstanceKlass::cast(m->method_holder())->source_file_name()); // source file name
+ assert(m->method_holder()->oop_is_instance(), "not InstanceKlass");
+ writer->write_symbolID(m->method_holder()->source_file_name()); // source file name
writer->write_u4(class_serial_num); // class serial number
writer->write_u4((u4) line_number); // line number
}
--- a/hotspot/src/share/vm/services/memPtr.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/services/memPtr.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -311,6 +311,17 @@
inline bool contains_address(address add) const {
return (addr() <= add && addr() + size() > add);
}
+
+ // if this memory region overlaps another region
+ inline bool overlaps_region(const MemPointerRecord* other) const {
+ assert(other != NULL, "Just check");
+ assert(size() > 0 && other->size() > 0, "empty range");
+ return contains_address(other->addr()) ||
+ contains_address(other->addr() + other->size() - 1) || // exclude end address
+ other->contains_address(addr()) ||
+ other->contains_address(addr() + size() - 1); // exclude end address
+ }
+
};
// MemPointerRecordEx also records callsite pc, from where
--- a/hotspot/src/share/vm/services/memSnapshot.cpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/services/memSnapshot.cpp Thu Nov 15 00:54:54 2012 +0000
@@ -31,6 +31,69 @@
#include "services/memSnapshot.hpp"
#include "services/memTracker.hpp"
+#ifdef ASSERT
+
+void decode_pointer_record(MemPointerRecord* rec) {
+ tty->print("Pointer: [" PTR_FORMAT " - " PTR_FORMAT "] size = %d bytes", rec->addr(),
+ rec->addr() + rec->size(), (int)rec->size());
+ tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags())));
+ if (rec->is_vm_pointer()) {
+ if (rec->is_allocation_record()) {
+ tty->print_cr(" (reserve)");
+ } else if (rec->is_commit_record()) {
+ tty->print_cr(" (commit)");
+ } else if (rec->is_uncommit_record()) {
+ tty->print_cr(" (uncommit)");
+ } else if (rec->is_deallocation_record()) {
+ tty->print_cr(" (release)");
+ } else {
+ tty->print_cr(" (tag)");
+ }
+ } else {
+ if (rec->is_arena_size_record()) {
+ tty->print_cr(" (arena size)");
+ } else if (rec->is_allocation_record()) {
+ tty->print_cr(" (malloc)");
+ } else {
+ tty->print_cr(" (free)");
+ }
+ }
+ if (MemTracker::track_callsite()) {
+ char buf[1024];
+ address pc = ((MemPointerRecordEx*)rec)->pc();
+ if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) {
+ tty->print_cr("\tfrom %s", buf);
+ } else {
+ tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc);
+ }
+ }
+}
+
+void decode_vm_region_record(VMMemRegion* rec) {
+ tty->print("VM Region [" PTR_FORMAT " - " PTR_FORMAT "]", rec->addr(),
+ rec->addr() + rec->size());
+ tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags())));
+ if (rec->is_allocation_record()) {
+ tty->print_cr(" (reserved)");
+ } else if (rec->is_commit_record()) {
+ tty->print_cr(" (committed)");
+ } else {
+ ShouldNotReachHere();
+ }
+ if (MemTracker::track_callsite()) {
+ char buf[1024];
+ address pc = ((VMMemRegionEx*)rec)->pc();
+ if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) {
+ tty->print_cr("\tfrom %s", buf);
+ } else {
+ tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc);
+ }
+
+ }
+}
+
+#endif
+
bool VMMemPointerIterator::insert_record(MemPointerRecord* rec) {
VMMemRegionEx new_rec;
@@ -73,52 +136,61 @@
return true;
}
assert(cur->base() > rec->addr(), "Just check: locate()");
- assert(rec->addr() + rec->size() <= cur->base(), "Can not overlap");
+ assert(!cur->overlaps_region(rec), "overlapping reserved regions");
return insert_record(rec);
}
// we do consolidate committed regions
bool VMMemPointerIterator::add_committed_region(MemPointerRecord* rec) {
assert(rec->is_commit_record(), "Sanity check");
- VMMemRegion* cur;
- cur = (VMMemRegion*)current();
- assert(cur->is_reserved_region() && cur->contains_region(rec),
+ VMMemRegion* reserved_rgn = (VMMemRegion*)current();
+ assert(reserved_rgn->is_reserved_region() && reserved_rgn->contains_region(rec),
"Sanity check");
// thread's native stack is always marked as "committed", ignore
// the "commit" operation for creating stack guard pages
- if (FLAGS_TO_MEMORY_TYPE(cur->flags()) == mtThreadStack &&
+ if (FLAGS_TO_MEMORY_TYPE(reserved_rgn->flags()) == mtThreadStack &&
FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) {
return true;
}
- cur = (VMMemRegion*)next();
- while (cur != NULL && cur->is_committed_region()) {
+ // if the reserved region has any committed regions
+ VMMemRegion* committed_rgn = (VMMemRegion*)next();
+ while (committed_rgn != NULL && committed_rgn->is_committed_region()) {
// duplicated commit records
- if(cur->contains_region(rec)) {
+ if(committed_rgn->contains_region(rec)) {
return true;
- }
- if (cur->base() > rec->addr()) {
- // committed regions can not overlap
- assert(rec->addr() + rec->size() <= cur->base(), "Can not overlap");
- if (rec->addr() + rec->size() == cur->base()) {
- cur->expand_region(rec->addr(), rec->size());
- return true;
+ } else if (committed_rgn->overlaps_region(rec)) {
+ // overlaps front part
+ if (rec->addr() < committed_rgn->addr()) {
+ committed_rgn->expand_region(rec->addr(),
+ committed_rgn->addr() - rec->addr());
} else {
- return insert_record(rec);
+ // overlaps tail part
+ address committed_rgn_end = committed_rgn->addr() +
+ committed_rgn->size();
+ assert(committed_rgn_end < rec->addr() + rec->size(),
+ "overlap tail part");
+ committed_rgn->expand_region(committed_rgn_end,
+ (rec->addr() + rec->size()) - committed_rgn_end);
}
- } else if (cur->base() + cur->size() == rec->addr()) {
- cur->expand_region(rec->addr(), rec->size());
+ } else if (committed_rgn->base() + committed_rgn->size() == rec->addr()) {
+ // adjunct each other
+ committed_rgn->expand_region(rec->addr(), rec->size());
VMMemRegion* next_reg = (VMMemRegion*)next();
// see if we can consolidate next committed region
if (next_reg != NULL && next_reg->is_committed_region() &&
- next_reg->base() == cur->base() + cur->size()) {
- cur->expand_region(next_reg->base(), next_reg->size());
+ next_reg->base() == committed_rgn->base() + committed_rgn->size()) {
+ committed_rgn->expand_region(next_reg->base(), next_reg->size());
+ // delete merged region
remove();
}
return true;
+ } else if (committed_rgn->base() > rec->addr()) {
+ // found the location, insert this committed region
+ return insert_record(rec);
}
- cur = (VMMemRegion*)next();
+ committed_rgn = (VMMemRegion*)next();
}
return insert_record(rec);
}
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Wed Nov 14 10:20:25 2012 -0800
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -217,7 +217,12 @@
return missed;
}
- E at(int i) const {
+ E& at(int i) {
+ assert(0 <= i && i < _len, "illegal index");
+ return _data[i];
+ }
+
+ E const& at(int i) const {
assert(0 <= i && i < _len, "illegal index");
return _data[i];
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/pair.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_PAIR_HPP
+#define SHARE_VM_UTILITIES_PAIR_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/top.hpp"
+
+template<typename T, typename V, typename ALLOC_BASE = ResourceObj>
+class Pair : public ALLOC_BASE {
+ public:
+ T first;
+ V second;
+
+ Pair() {}
+ Pair(T t, V v) : first(t), second(v) {}
+};
+
+
+#endif // SHARE_VM_UTILITIES_PAIR_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/resourceHash.hpp Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP
+#define SHARE_VM_UTILITIES_RESOURCEHASH_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/top.hpp"
+
+template<typename K> struct ResourceHashtableFns {
+ typedef unsigned (*hash_fn)(K const&);
+ typedef bool (*equals_fn)(K const&, K const&);
+};
+
+template<typename K> unsigned primitive_hash(const K& k) {
+ unsigned hash = (unsigned)((uintptr_t)k);
+ return hash ^ (hash > 3); // just in case we're dealing with aligned ptrs
+}
+
+template<typename K> bool primitive_equals(const K& k0, const K& k1) {
+ return k0 == k1;
+}
+
+template<
+ typename K, typename V,
+ typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>,
+ typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>,
+ unsigned SIZE = 256
+ >
+class ResourceHashtable : public ResourceObj {
+ private:
+
+ class Node : public ResourceObj {
+ public:
+ unsigned _hash;
+ K _key;
+ V _value;
+ Node* _next;
+
+ Node(unsigned hash, K const& key, V const& value) :
+ _hash(hash), _key(key), _value(value), _next(NULL) {}
+ };
+
+ Node* _table[SIZE];
+
+ // Returns a pointer to where the node where the value would reside if
+ // it's in the table.
+ Node** lookup_node(unsigned hash, K const& key) {
+ unsigned index = hash % SIZE;
+ Node** ptr = &_table[index];
+ while (*ptr != NULL) {
+ Node* node = *ptr;
+ if (node->_hash == hash && EQUALS(key, node->_key)) {
+ break;
+ }
+ ptr = &(node->_next);
+ }
+ return ptr;
+ }
+
+ Node const** lookup_node(unsigned hash, K const& key) const {
+ return const_cast<Node const**>(
+ const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
+ }
+
+ public:
+ ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); }
+
+ bool contains(K const& key) const {
+ return get(key) != NULL;
+ }
+
+ V* get(K const& key) const {
+ unsigned hv = HASH(key);
+ Node const** ptr = lookup_node(hv, key);
+ if (*ptr != NULL) {
+ return const_cast<V*>(&(*ptr)->_value);
+ } else {
+ return NULL;
+ }
+ }
+
+ // Inserts or replaces a value in the table
+ void put(K const& key, V const& value) {
+ unsigned hv = HASH(key);
+ Node** ptr = lookup_node(hv, key);
+ if (*ptr != NULL) {
+ (*ptr)->_value = value;
+ } else {
+ *ptr = new Node(hv, key, value);
+ }
+ }
+
+ // ITER contains bool do_entry(K const&, V const&), which will be
+ // called for each entry in the table. If do_entry() returns false,
+ // the iteration is cancelled.
+ template<class ITER>
+ void iterate(ITER* iter) const {
+ Node* const* bucket = _table;
+ while (bucket < &_table[SIZE]) {
+ Node* node = *bucket;
+ while (node != NULL) {
+ bool cont = iter->do_entry(node->_key, node->_value);
+ if (!cont) { return; }
+ node = node->_next;
+ }
+ ++bucket;
+ }
+ }
+};
+
+
+#endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/8002069/Test8002069.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8002069
+ * @summary Assert failed in C2: assert(field->edge_count() > 0) failed: sanity
+ *
+ * @run main/othervm -Xmx32m -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:CompileCommand=exclude,Test8002069.dummy Test8002069
+ */
+
+abstract class O {
+ int f;
+ public O() { f = 5; }
+ abstract void put(int i);
+ public int foo(int i) {
+ put(i);
+ return i;
+ }
+};
+
+class A extends O {
+ int[] a;
+ public A(int s) {
+ a = new int[s];
+ }
+ public void put(int i) {
+ a[i%a.length] = i;
+ }
+}
+
+class B extends O {
+ int sz;
+ int[] a;
+ public B(int s) {
+ sz = s;
+ a = new int[s];
+ }
+ public void put(int i) {
+ a[i%sz] = i;
+ }
+}
+
+public class Test8002069 {
+ public static void main(String args[]) {
+ int sum = 0;
+ for (int i=0; i<8000; i++) {
+ sum += test1(i);
+ }
+ for (int i=0; i<100000; i++) {
+ sum += test2(i);
+ }
+ System.out.println("PASSED. sum = " + sum);
+ }
+
+ private O o;
+
+ private int foo(int i) {
+ return o.foo(i);
+ }
+ static int test1(int i) {
+ Test8002069 t = new Test8002069();
+ t.o = new A(5);
+ return t.foo(i);
+ }
+ static int test2(int i) {
+ Test8002069 t = new Test8002069();
+ t.o = new B(5);
+ dummy(i);
+ return t.foo(i);
+ }
+
+ static int dummy(int i) {
+ return i*2;
+ }
+}
+
--- a/jaxp/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/jaxp/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
6b1db0b41d2f6e2a7b3bdbc8a8db823b47752906 jdk8-b61
5d0fa0108d028c05753a47bcf2a598357dabf0c0 jdk8-b62
192d8a244bc36427757866e9fb3a08938c0e674c jdk8-b63
+27ab79568c34abf80958d5fa8c04fd1740d243da jdk8-b64
--- a/jaxws/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/jaxws/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
97e5e74e2a341d9142ce28043912a3c255e28e03 jdk8-b61
d265b9b4c0f55c23a1c9fda02a8052fd9df2eec5 jdk8-b62
86989f702267debe16d13720d5ae7ae9839796f4 jdk8-b63
+5ded18a14bcc80b2a253f2b84da0073a0ecac665 jdk8-b64
--- a/jdk/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
61ddb3fd000a09ab05bff1940b0ac211661e94cf jdk8-b61
50b8b17449d200c66bfd68fb4f3a9197432c9e2b jdk8-b62
f117a3e06f78a258074674ad17601f99bcb1ce0d jdk8-b63
+26dbd73fb7662a29b3e47179fdc88a0bfa4e231e jdk8-b64
--- a/jdk/make/common/Defs-linux.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/common/Defs-linux.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -111,21 +111,18 @@
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
- # Default OBJCOPY comes from GNU Binutils on Linux:
- DEF_OBJCOPY=/usr/bin/objcopy
- ifdef CROSS_COMPILE_ARCH
- # don't try to generate .debuginfo files when cross compiling
- _JUNK_ := $(shell \
- echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
- "skipping .debuginfo generation.")
- OBJCOPY=
+ ifndef CROSS_COMPILE_ARCH
+ # Default OBJCOPY comes from GNU Binutils on Linux:
+ DEF_OBJCOPY=/usr/bin/objcopy
else
- OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
- ifneq ($(ALT_OBJCOPY),)
- _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
- # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
- OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
- endif
+ # Assume objcopy is part of the cross-compilation toolkit
+ DEF_OBJCOPY=$(COMPILER_PATH)/objcopy
+ endif
+ OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
+ ifneq ($(ALT_OBJCOPY),)
+ _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
+ # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
+ OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
endif
# Setting ENABLE_FULL_DEBUG_SYMBOLS=1 (and OBJCOPY) above enables the
@@ -137,7 +134,7 @@
ifeq ($(OBJCOPY),)
_JUNK_ := $(shell \
- echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
+ echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files. You may need to set ALT_OBJCOPY.")
ENABLE_FULL_DEBUG_SYMBOLS=0
else
_JUNK_ := $(shell \
--- a/jdk/make/common/shared/Defs-control.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/common/shared/Defs-control.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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
@@ -88,9 +88,9 @@
dummy := $(shell $(MKDIR) -p $(TEMP_DIR))
# The language version we want for this jdk build
-SOURCE_LANGUAGE_VERSION=7
+SOURCE_LANGUAGE_VERSION=8
# The class version we want for this jdk build
-TARGET_CLASS_VERSION=7
+TARGET_CLASS_VERSION=8
# The MESSAGE, WARNING and ERROR files are used to store sanity check and
# source check messages, warnings and errors.
--- a/jdk/make/common/shared/Defs-java.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/common/shared/Defs-java.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -143,12 +143,12 @@
endif
# Add the source level
-SOURCE_LANGUAGE_VERSION = 7
+SOURCE_LANGUAGE_VERSION = 8
LANGUAGE_VERSION = -source $(SOURCE_LANGUAGE_VERSION)
JAVACFLAGS += $(LANGUAGE_VERSION)
# Add the class version we want
-TARGET_CLASS_VERSION = 7
+TARGET_CLASS_VERSION = 8
CLASS_VERSION = -target $(TARGET_CLASS_VERSION)
JAVACFLAGS += $(CLASS_VERSION)
JAVACFLAGS += -encoding ascii
--- a/jdk/make/java/invoke/Makefile Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/java/invoke/Makefile Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. 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
@@ -36,7 +36,7 @@
# The sources built here use new language syntax to generate
# method handle calls. Let's be sure we are using that format.
-LANGUAGE_VERSION = -source 7
-CLASS_VERSION = -target 7
+LANGUAGE_VERSION = -source 8
+CLASS_VERSION = -target 8
include $(BUILDDIR)/common/Classes.gmk
--- a/jdk/make/sun/javazic/tzdata/VERSION Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/VERSION Thu Nov 15 00:54:54 2012 +0000
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2012c
+tzdata2012i
--- a/jdk/make/sun/javazic/tzdata/africa Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/africa Thu Nov 15 00:54:54 2012 +0000
@@ -260,7 +260,7 @@
# I received a mail from an airline which says that the daylight
# saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
-# http://www.nentjes.info/Bill/bill5.htm
+# http://www.nentjes.info/Bill/bill5.htm
# http://www.timeanddate.com/worldclock/city.html?n=53
# From Steffen Thorsen (2007-09-04): The official information...:
# http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
@@ -314,18 +314,18 @@
# in September.
# From Steffen Thorsen (2009-08-11):
-# We have been able to confirm the August change with the Egyptian Cabinet
+# We have been able to confirm the August change with the Egyptian Cabinet
# Information and Decision Support Center:
# <a href="http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html">
# http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
# </a>
-#
+#
# The Middle East News Agency
# <a href="http://www.mena.org.eg/index.aspx">
# http://www.mena.org.eg/index.aspx
# </a>
# also reports "Egypt starts winter time on August 21"
-# today in article numbered "71, 11/08/2009 12:25 GMT."
+# today in article numbered "71, 11/08/2009 12:25 GMT."
# Only the title above is available without a subscription to their service,
# and can be found by searching for "winter" in their search engine
# (at least today).
@@ -504,7 +504,7 @@
# From Steffen Thorsen (2008-06-25):
# Mauritius plans to observe DST from 2008-11-01 to 2009-03-31 on a trial
# basis....
-# It seems that Mauritius observed daylight saving time from 1982-10-10 to
+# It seems that Mauritius observed daylight saving time from 1982-10-10 to
# 1983-03-20 as well, but that was not successful....
# http://www.timeanddate.com/news/time/mauritius-daylight-saving-time.html
@@ -528,12 +528,12 @@
# than previously announced (2008-11-01 to 2009-03-31). The new start
# date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
# given, but it is probably at either 2 or 3 wall clock time).
-#
-# A little strange though, since the article says that they moved the date
-# to align itself with Europe and USA which also change time on that date,
-# but that means they have not paid attention to what happened in
-# USA/Canada last year (DST ends first Sunday in November). I also wonder
-# why that they end on a Friday, instead of aligning with Europe which
+#
+# A little strange though, since the article says that they moved the date
+# to align itself with Europe and USA which also change time on that date,
+# but that means they have not paid attention to what happened in
+# USA/Canada last year (DST ends first Sunday in November). I also wonder
+# why that they end on a Friday, instead of aligning with Europe which
# changes two days later.
# From Alex Krivenyshev (2008-07-11):
@@ -592,7 +592,7 @@
# </a>
# From Arthur David Olson (2009-07-11):
-# The "mauritius-dst-will-not-repeat" wrapup includes this:
+# The "mauritius-dst-will-not-repeat" wrapup includes this:
# "The trial ended on March 29, 2009, when the clocks moved back by one hour
# at 2am (or 02:00) local time..."
@@ -686,8 +686,8 @@
# XXX--guess that it is only Morocco for now; guess only 2008 for now.
# From Steffen Thorsen (2008-08-27):
-# Morocco will change the clocks back on the midnight between August 31
-# and September 1. They originally planned to observe DST to near the end
+# Morocco will change the clocks back on the midnight between August 31
+# and September 1. They originally planned to observe DST to near the end
# of September:
#
# One article about it (in French):
@@ -821,6 +821,23 @@
# "...à partir du dernier dimance d'avril et non fins mars,
# comme annoncé précédemment."
+# From Milamber Space Network (2012-07-17):
+# The official return to GMT is announced by the Moroccan government:
+# <a href="http://www.mmsp.gov.ma/fr/actualites.aspx?id=288">
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
+# </a>
+#
+# Google translation, lightly edited:
+# Back to the standard time of the Kingdom (GMT)
+# Pursuant to Decree No. 2-12-126 issued on 26 Jumada (I) 1433 (April 18,
+# 2012) and in accordance with the order of Mr. President of the
+# Government No. 3-47-12 issued on 24 Sha'ban (11 July 2012), the Ministry
+# of Public Service and Administration Modernization announces the return
+# of the legal time of the Kingdom (GMT) from Friday, July 20, 2012 until
+# Monday, August 20, 2012. So the time will be delayed by 60 minutes from
+# 3:00 am Friday, July 20, 2012 and will again be advanced by 60 minutes
+# August 20, 2012 from 2:00 am.
+
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 S
@@ -848,6 +865,8 @@
Rule Morocco 2011 only - Jul 31 0 0 -
Rule Morocco 2012 max - Apr lastSun 2:00 1:00 S
Rule Morocco 2012 max - Sep lastSun 3:00 0 -
+Rule Morocco 2012 only - Jul 20 3:00 0 -
+Rule Morocco 2012 only - Aug 20 2:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
@@ -876,7 +895,7 @@
# Forecasting Riaan van Zyl explained that the far eastern parts of
# the country are close to 40 minutes earlier in sunrise than the rest
# of the country.
-#
+#
# From Paul Eggert (2007-03-31):
# Apparently the Caprivi Strip informally observes Botswana time, but
# we have no details. In the meantime people there can use Africa/Gaborone.
--- a/jdk/make/sun/javazic/tzdata/asia Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/asia Thu Nov 15 00:54:54 2012 +0000
@@ -124,7 +124,7 @@
# From Alexander Krivenyshev (2012-02-10):
# According to News Armenia, on Feb 9, 2012,
# http://newsarmenia.ru/society/20120209/42609695.html
-#
+#
# The Armenia National Assembly adopted final reading of Amendments to the
# Law "On procedure of calculation time on the territory of the Republic of
# Armenia" according to which Armenia [is] abolishing Daylight Saving Time.
@@ -204,15 +204,15 @@
# </a>
# From A. N. M. Kamrus Saadat (2009-06-15):
-# Finally we've got the official mail regarding DST start time where DST start
-# time is mentioned as Jun 19 2009, 23:00 from BTRC (Bangladesh
-# Telecommunication Regulatory Commission).
+# Finally we've got the official mail regarding DST start time where DST start
+# time is mentioned as Jun 19 2009, 23:00 from BTRC (Bangladesh
+# Telecommunication Regulatory Commission).
#
# No DST end date has been announced yet.
# From Alexander Krivenyshev (2009-09-25):
-# Bangladesh won't go back to Standard Time from October 1, 2009,
-# instead it will continue DST measure till the cabinet makes a fresh decision.
+# Bangladesh won't go back to Standard Time from October 1, 2009,
+# instead it will continue DST measure till the cabinet makes a fresh decision.
#
# Following report by same newspaper-"The Daily Star Friday":
# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
@@ -226,8 +226,8 @@
# From Steffen Thorsen (2009-10-13):
# IANS (Indo-Asian News Service) now reports:
-# Bangladesh has decided that the clock advanced by an hour to make
-# maximum use of daylight hours as an energy saving measure would
+# Bangladesh has decided that the clock advanced by an hour to make
+# maximum use of daylight hours as an energy saving measure would
# "continue for an indefinite period."
#
# One of many places where it is published:
@@ -255,7 +255,7 @@
# From Alexander Krivenyshev (2010-03-22):
# According to Bangladesh newspaper "The Daily Star,"
-# Cabinet cancels Daylight Saving Time
+# Cabinet cancels Daylight Saving Time
# <a href="http://www.thedailystar.net/newDesign/latest_news.php?nid=22817">
# http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
# </a>
@@ -383,11 +383,11 @@
# observing daylight saving time in 1986.
#
# From Thomas S. Mullaney (2008-02-11):
-# I think you're combining two subjects that need to treated
-# separately: daylight savings (which, you're correct, wasn't
-# implemented until the 1980s) and the unified time zone centered near
-# Beijing (which was implemented in 1949). Briefly, there was also a
-# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
+# I think you're combining two subjects that need to treated
+# separately: daylight savings (which, you're correct, wasn't
+# implemented until the 1980s) and the unified time zone centered near
+# Beijing (which was implemented in 1949). Briefly, there was also a
+# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
# ceased, and the second eventually recognized (again, in the 1980s).
#
# From Paul Eggert (2008-06-30):
@@ -524,7 +524,7 @@
# as of 2009-10-28:
# Year Period
# 1941 1 Apr to 30 Sep
-# 1942 Whole year
+# 1942 Whole year
# 1943 Whole year
# 1944 Whole year
# 1945 Whole year
@@ -615,16 +615,16 @@
# From Arthur David Olson (2010-04-07):
# Here's Google's translation of the table at the bottom of the "summert.htm" page:
# Decade Name Start and end date
-# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time May 1 to September 30
-# 41 years of the Republic of China (AD 1952) Daylight Saving Time March 1 to October 31
-# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time April 1 to October 31
-# In the 44 years to 45 years (AD 1955-1956 years) Daylight Saving Time April 1 to September 30
-# Republic of China 46 years to 48 years (AD 1957-1959) Summer Time April 1 to September 30
-# Republic of China 49 years to 50 years (AD 1960-1961) Summer Time June 1 to September 30
-# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
-# Republic of China 63 years to 64 years (1974-1975 AD) Daylight Saving Time April 1 to September 30
-# Republic of China 65 years to 67 years (1976-1978 AD) Stop Daylight Saving Time
-# Republic of China 68 years (AD 1979) Daylight Saving Time July 1 to September 30
+# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time May 1 to September 30
+# 41 years of the Republic of China (AD 1952) Daylight Saving Time March 1 to October 31
+# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time April 1 to October 31
+# In the 44 years to 45 years (AD 1955-1956 years) Daylight Saving Time April 1 to September 30
+# Republic of China 46 years to 48 years (AD 1957-1959) Summer Time April 1 to September 30
+# Republic of China 49 years to 50 years (AD 1960-1961) Summer Time June 1 to September 30
+# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
+# Republic of China 63 years to 64 years (1974-1975 AD) Daylight Saving Time April 1 to September 30
+# Republic of China 65 years to 67 years (1976-1978 AD) Stop Daylight Saving Time
+# Republic of China 68 years (AD 1979) Daylight Saving Time July 1 to September 30
# Republic of China since 69 years (AD 1980) Stop Daylight Saving Time
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1193,15 +1193,15 @@
#
# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+beyond.ps
-# From Paul Eggert (2005-02-22):
+# From Paul Eggert (2012-10-26):
# I used Ephraim Silverberg's dst-israel.el program
# <ftp://ftp.cs.huji.ac.il/pub/tz/software/dst-israel.el> (2005-02-20)
# along with Ed Reingold's cal-hebrew in GNU Emacs 21.4,
-# to generate the transitions in this list.
+# to generate the transitions from 2005 through 2012.
# (I replaced "lastFri" with "Fri>=26" by hand.)
-# The spring transitions below all correspond to the following Rule:
+# The spring transitions all correspond to the following Rule:
#
-# Rule Zion 2005 max - Mar Fri>=26 2:00 1:00 D
+# Rule Zion 2005 2012 - Mar Fri>=26 2:00 1:00 D
#
# but older zic implementations (e.g., Solaris 8) do not support
# "Fri>=26" to mean April 1 in years like 2005, so for now we list the
@@ -1218,39 +1218,36 @@
Rule Zion 2010 only - Sep 12 2:00 0 S
Rule Zion 2011 only - Apr 1 2:00 1:00 D
Rule Zion 2011 only - Oct 2 2:00 0 S
-Rule Zion 2012 2015 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2012 only - Mar Fri>=26 2:00 1:00 D
Rule Zion 2012 only - Sep 23 2:00 0 S
-Rule Zion 2013 only - Sep 8 2:00 0 S
-Rule Zion 2014 only - Sep 28 2:00 0 S
-Rule Zion 2015 only - Sep 20 2:00 0 S
-Rule Zion 2016 only - Apr 1 2:00 1:00 D
-Rule Zion 2016 only - Oct 9 2:00 0 S
-Rule Zion 2017 2021 - Mar Fri>=26 2:00 1:00 D
-Rule Zion 2017 only - Sep 24 2:00 0 S
-Rule Zion 2018 only - Sep 16 2:00 0 S
-Rule Zion 2019 only - Oct 6 2:00 0 S
-Rule Zion 2020 only - Sep 27 2:00 0 S
-Rule Zion 2021 only - Sep 12 2:00 0 S
-Rule Zion 2022 only - Apr 1 2:00 1:00 D
-Rule Zion 2022 only - Oct 2 2:00 0 S
-Rule Zion 2023 2032 - Mar Fri>=26 2:00 1:00 D
-Rule Zion 2023 only - Sep 24 2:00 0 S
-Rule Zion 2024 only - Oct 6 2:00 0 S
-Rule Zion 2025 only - Sep 28 2:00 0 S
-Rule Zion 2026 only - Sep 20 2:00 0 S
-Rule Zion 2027 only - Oct 10 2:00 0 S
-Rule Zion 2028 only - Sep 24 2:00 0 S
-Rule Zion 2029 only - Sep 16 2:00 0 S
-Rule Zion 2030 only - Oct 6 2:00 0 S
-Rule Zion 2031 only - Sep 21 2:00 0 S
-Rule Zion 2032 only - Sep 12 2:00 0 S
-Rule Zion 2033 only - Apr 1 2:00 1:00 D
-Rule Zion 2033 only - Oct 2 2:00 0 S
-Rule Zion 2034 2037 - Mar Fri>=26 2:00 1:00 D
-Rule Zion 2034 only - Sep 17 2:00 0 S
-Rule Zion 2035 only - Oct 7 2:00 0 S
-Rule Zion 2036 only - Sep 28 2:00 0 S
-Rule Zion 2037 only - Sep 13 2:00 0 S
+
+# From Ephraim Silverberg (2012-10-18):
+
+# Yesterday, the Interior Ministry Committee, after more than a year
+# past, approved sending the proposed June 2011 changes to the Time
+# Decree Law back to the Knesset for second and third (final) votes
+# before the upcoming elections on Jan. 22, 2013. Hence, although the
+# changes are not yet law, they are expected to be so before February 2013.
+#
+# As of 2013, DST starts at 02:00 on the Friday before the last Sunday in March.
+# DST ends at 02:00 on the first Sunday after October 1, unless it occurs on the
+# second day of the Jewish Rosh Hashana holiday, in which case DST ends a day
+# later (i.e. at 02:00 the first Monday after October 2).
+# [Rosh Hashana holidays are factored in until 2100.]
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D
+Rule Zion 2013 2026 - Oct Sun>=2 2:00 0 S
+Rule Zion 2027 only - Oct Mon>=3 2:00 0 S
+Rule Zion 2028 max - Oct Sun>=2 2:00 0 S
+# The following rules are commented out for now, as they break older
+# versions of zic that support only signed 32-bit timestamps, i.e.,
+# through 2038-01-19 03:14:07 UTC.
+#Rule Zion 2028 2053 - Oct Sun>=2 2:00 0 S
+#Rule Zion 2054 only - Oct Mon>=3 2:00 0 S
+#Rule Zion 2055 2080 - Oct Sun>=2 2:00 0 S
+#Rule Zion 2081 only - Oct Mon>=3 2:00 0 S
+#Rule Zion 2082 max - Oct Sun>=2 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Jerusalem 2:20:56 - LMT 1880
@@ -1385,6 +1382,16 @@
# From Arthur David Olson (2009-04-06):
# We still have Jordan switching to DST on Thursdays in 2000 and 2001.
+# From Steffen Thorsen (2012-10-25):
+# Yesterday the government in Jordan announced that they will not
+# switch back to standard time this winter, so the will stay on DST
+# until about the same time next year (at least).
+# http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?NewsID=88950
+#
+# From Paul Eggert (2012-10-25):
+# For now, assume this is just a one-year measure. If it becomes
+# permanent, we should move Jordan from EET to AST effective tomorrow.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Jordan 1973 only - Jun 6 0:00 1:00 S
Rule Jordan 1973 1975 - Oct 1 0:00 0 -
@@ -1413,7 +1420,8 @@
Rule Jordan 2003 only - Oct 24 0:00s 0 -
Rule Jordan 2004 only - Oct 15 0:00s 0 -
Rule Jordan 2005 only - Sep lastFri 0:00s 0 -
-Rule Jordan 2006 max - Oct lastFri 0:00s 0 -
+Rule Jordan 2006 2011 - Oct lastFri 0:00s 0 -
+Rule Jordan 2013 max - Oct lastFri 0:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Amman 2:23:44 - LMT 1931
2:00 Jordan EE%sT
@@ -1858,15 +1866,15 @@
# shown 8 per cent higher consumption of electricity.
# From Alex Krivenyshev (2008-05-15):
-#
-# Here is an article that Pakistan plan to introduce Daylight Saving Time
+#
+# Here is an article that Pakistan plan to introduce Daylight Saving Time
# on June 1, 2008 for 3 months.
-#
-# "... The federal cabinet on Wednesday announced a new conservation plan to help
-# reduce load shedding by approving the closure of commercial centres at 9pm and
-# moving clocks forward by one hour for the next three months.
+#
+# "... The federal cabinet on Wednesday announced a new conservation plan to help
+# reduce load shedding by approving the closure of commercial centres at 9pm and
+# moving clocks forward by one hour for the next three months.
# ...."
-#
+#
# <a href="http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html">
# http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
# </a>
@@ -1926,7 +1934,7 @@
# Government has decided to restore the previous time by moving the
# clocks backward by one hour from October 1. A formal announcement to
# this effect will be made after the Prime Minister grants approval in
-# this regard."
+# this regard."
# <a href="http://www.thenews.com.pk/updates.asp?id=87168">
# http://www.thenews.com.pk/updates.asp?id=87168
# </a>
@@ -2222,7 +2230,7 @@
# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=306795">
# http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
# </a>
-# the clocks were set back one hour at 2010-08-11 00:00:00 local time in
+# the clocks were set back one hour at 2010-08-11 00:00:00 local time in
# Gaza and the West Bank.
# Some more background info:
# <a href="http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html">
@@ -2261,7 +2269,7 @@
# The rules for Egypt are stolen from the `africa' file.
# From Steffen Thorsen (2011-09-30):
-# West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
+# West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
# 00:00).
# So West Bank and Gaza now have the same time again.
#
@@ -2316,6 +2324,8 @@
# From Arthur David Olson (2011-09-20):
# 2011 transitions per http://www.timeanddate.com as of 2011-09-20.
+# From Paul Eggert (2012-10-12):
+# 2012 transitions per http://www.timeanddate.com as of 2012-10-12.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2326,7 +2336,7 @@
2:00 Palestine EE%sT 2011 Apr 2 12:01
2:00 1:00 EEST 2011 Aug 1
2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 28
+ 2:00 1:00 EEST 2012 Sep 21 1:00
2:00 - EET
Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
@@ -2341,7 +2351,7 @@
2:00 - EET 2011 Aug 30
2:00 1:00 EEST 2011 Sep 30 3:00
2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 28 3:00
+ 2:00 1:00 EEST 2012 Sep 21 1:00
2:00 - EET
# Paracel Is
@@ -2535,19 +2545,19 @@
# having it between Wednesday and Thursday (two workdays in Syria) since the
# weekend in Syria is not Saturday and Sunday, but Friday and Saturday. So now
# it is implemented at midnight of the last workday before weekend...
-#
+#
# From Steffen Thorsen (2007-10-27):
# Jesper Norgaard Welen wrote:
-#
+#
# > "Winter local time in Syria will be observed at midnight of Thursday 1
# > November 2007, and the clock will be put back 1 hour."
-#
+#
# I found confirmation on this in this gov.sy-article (Arabic):
# http://wehda.alwehda.gov.sy/_print_veiw.asp?FileName=12521710520070926111247
-#
+#
# which using Google's translate tools says:
-# Council of Ministers also approved the commencement of work on
-# identifying the winter time as of Friday, 2/11/2007 where the 60th
+# Council of Ministers also approved the commencement of work on
+# identifying the winter time as of Friday, 2/11/2007 where the 60th
# minute delay at midnight Thursday 1/11/2007.
Rule Syria 2007 only - Nov Fri>=1 0:00 0 -
@@ -2613,8 +2623,8 @@
# </a>
# From Steffen Thorsen (2009-10-27):
-# The Syrian Arab News Network on 2009-09-29 reported that Syria will
-# revert back to winter (standard) time on midnight between Thursday
+# The Syrian Arab News Network on 2009-09-29 reported that Syria will
+# revert back to winter (standard) time on midnight between Thursday
# 2009-10-29 and Friday 2009-10-30:
# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm">
# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
--- a/jdk/make/sun/javazic/tzdata/australasia Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/australasia Thu Nov 15 00:54:54 2012 +0000
@@ -306,9 +306,9 @@
# </a>
# From Alexander Krivenyshev (2010-10-24):
-# According to Radio Fiji and Fiji Times online, Fiji will end DST 3
+# According to Radio Fiji and Fiji Times online, Fiji will end DST 3
# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
-# Here is confirmation from Government of the Republic of the Fiji Islands,
+# Here is confirmation from Government of the Republic of the Fiji Islands,
# Ministry of Information (fiji.gov.fj) web site:
# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
@@ -319,15 +319,15 @@
# </a>
# From Steffen Thorsen (2011-10-03):
-# Now the dates have been confirmed, and at least our start date
+# Now the dates have been confirmed, and at least our start date
# assumption was correct (end date was one week wrong).
#
# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155">
# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
# </a>
# which says
-# Members of the public are reminded to change their time to one hour in
-# advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
+# Members of the public are reminded to change their time to one hour in
+# advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
# 2am on February 26 next year.
# From Ken Rylander (2011-10-24)
@@ -344,15 +344,23 @@
# The commencement of daylight saving will remain unchanged and start
# on the 23rd of October, 2011.
+# From the Fiji Government Online Portal (2012-08-21) via Steffen Thorsen:
+# The Minister for Labour, Industrial Relations and Employment Mr Jone Usamate
+# today confirmed that Fiji will start daylight savings at 2 am on Sunday 21st
+# October 2012 and end at 3 am on Sunday 20th January 2013.
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=6702&catid=71&Itemid=155
+#
+# From Paul Eggert (2012-08-31):
+# For now, guess a pattern of the penultimate Sundays in October and January.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S
Rule Fiji 1999 2000 - Feb lastSun 3:00 0 -
Rule Fiji 2009 only - Nov 29 2:00 1:00 S
Rule Fiji 2010 only - Mar lastSun 3:00 0 -
-Rule Fiji 2010 only - Oct 24 2:00 1:00 S
+Rule Fiji 2010 max - Oct Sun>=18 2:00 1:00 S
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
-Rule Fiji 2011 only - Oct 23 2:00 1:00 S
-Rule Fiji 2012 only - Jan 22 3:00 0 -
+Rule Fiji 2012 max - Jan Sun>=18 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva
12:00 Fiji FJ%sT # Fiji Time
@@ -581,7 +589,7 @@
# From David Zuelke (2011-05-09):
# Subject: Samoa to move timezone from east to west of international date line
-#
+#
# <a href="http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963">
# http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
# </a>
@@ -643,6 +651,23 @@
# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
# seasons, there is not yet any indication that this trend will continue on
# a regular basis. For now, we have explicitly listed the transitions below.
+#
+# From Nicky (2012-09-10):
+# Daylight Saving Time commences on Sunday 30th September 2012 and
+# ends on Sunday 7th of April 2013.
+#
+# Please find link below for more information.
+# http://www.mcil.gov.ws/mcil_publications.html
+#
+# That publication also includes dates for Summer of 2013/4 as well
+# which give the impression of a pattern in selecting dates for the
+# future, so for now, we will guess this will continue.
+
+# Western Samoa
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule WS 2012 max - Sep lastSun 3:00 1 D
+Rule WS 2012 max - Apr Sun>=1 4:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
-11:26:56 - LMT 1911
-11:30 - SAMT 1950 # Samoa Time
@@ -650,8 +675,8 @@
-11:00 1:00 WSDT 2011 Apr 2 4:00
-11:00 - WST 2011 Sep 24 3:00
-11:00 1:00 WSDT 2011 Dec 30
- 13:00 1:00 WSDT 2012 Apr 1 4:00
- 13:00 - WST
+ 13:00 1:00 WSDT 2012 Apr Sun>=1 4:00
+ 13:00 WS WS%sT
# Solomon Is
# excludes Bougainville, for which see Papua New Guinea
@@ -663,25 +688,25 @@
#
# From Gwillim Law (2011-12-29)
# A correspondent informed me that Tokelau, like Samoa, will be skipping
-# December 31 this year, thereby changing its time zone from UTC-10 to
-# UTC+14. When I tried to verify this statement, I found a confirming
-# article in Time magazine online
-# <a href="http://www.time.com/time/world/article/0,8599,2103243,00.html">
-# (http://www.time.com/time/world/article/0,8599,2103243,00.html).
-# </a>
+# December 31 this year ...
#
-# From Jonathan Leffler (2011-12-29)
-# Information from the BBC to the same effect:
-# <a href="http://www.bbc.co.uk/news/world-asia-16351377">
-# http://www.bbc.co.uk/news/world-asia-16351377
-# </a>
+# From Steffen Thorsen (2012-07-25)
+# ... we double checked by calling hotels and offices based in Tokelau asking
+# about the time there, and they all told a time that agrees with UTC+13....
+# Shanks says UTC-10 from 1901 [but] ... there is a good chance the change
+# actually was to UTC-11 back then.
#
-# Patch supplied by Tim Parenti (2011-12-29)
+# From Paul Eggert (2012-07-25)
+# A Google Books snippet of Appendix to the Journals of the House of
+# Representatives of New Zealand, Session 1948,
+# <http://books.google.com/books?id=ZaVCAQAAIAAJ>, page 65, says Tokelau
+# was "11 hours slow on G.M.T." Go with Thorsen and assume Shanks & Pottenger
+# are off by an hour starting in 1901.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Fakaofo -11:24:56 - LMT 1901
- -10:00 - TKT 2011 Dec 30 # Tokelau Time
- 14:00 - TKT
+ -11:00 - TKT 2011 Dec 30 # Tokelau Time
+ 13:00 - TKT
# Tonga
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1362,22 +1387,22 @@
# See "southeast Australia" above for 2008 and later.
# From Steffen Thorsen (2009-04-28):
-# According to the official press release, South Australia's extended daylight
-# saving period will continue with the same rules as used during the 2008-2009
+# According to the official press release, South Australia's extended daylight
+# saving period will continue with the same rules as used during the 2008-2009
# summer (southern hemisphere).
-#
+#
# From
# <a href="http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf">
# http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
# </a>
-# The extended daylight saving period that South Australia has been trialling
+# The extended daylight saving period that South Australia has been trialling
# for over the last year is now set to be ongoing.
-# Daylight saving will continue to start on the first Sunday in October each
+# Daylight saving will continue to start on the first Sunday in October each
# year and finish on the first Sunday in April the following year.
-# Industrial Relations Minister, Paul Caica, says this provides South Australia
-# with a consistent half hour time difference with NSW, Victoria, Tasmania and
+# Industrial Relations Minister, Paul Caica, says this provides South Australia
+# with a consistent half hour time difference with NSW, Victoria, Tasmania and
# the ACT for all 52 weeks of the year...
-#
+#
# We have a wrap-up here:
# <a href="http://www.timeanddate.com/news/time/south-australia-extends-dst.html">
# http://www.timeanddate.com/news/time/south-australia-extends-dst.html
--- a/jdk/make/sun/javazic/tzdata/europe Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/europe Thu Nov 15 00:54:54 2012 +0000
@@ -597,12 +597,12 @@
# According to Kremlin press service, Russian President Dmitry Medvedev
# signed a federal law "On calculation of time" on June 9, 2011.
# According to the law Russia is abolishing daylight saving time.
-#
-# Medvedev signed a law "On the Calculation of Time" (in russian):
+#
+# Medvedev signed a law "On the Calculation of Time" (in russian):
# <a href="http://bmockbe.ru/events/?ID=7583">
# http://bmockbe.ru/events/?ID=7583
# </a>
-#
+#
# Medvedev signed a law on the calculation of the time (in russian):
# <a href="http://www.regnum.ru/news/polit/1413906.html">
# http://www.regnum.ru/news/polit/1413906.html
@@ -1710,7 +1710,7 @@
# From Alexander Krivenyshev (2011-10-26)
# NO need to divide Moldova into two timezones at this point.
# As of today, Transnistria (Pridnestrovie)- Tiraspol reversed its own
-# decision to abolish DST this winter.
+# decision to abolish DST this winter.
# Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
# Tiraspol will go back to winter time on October 30, 2011.
# News from Moldova (in russian):
@@ -2600,11 +2600,11 @@
# http://www.alomaliye.com/bkk_2002_3769.htm
# From Gökdeniz Karadağ (2011-03-10):
-#
+#
# According to the articles linked below, Turkey will change into summer
# time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
# This change is due to a nationwide exam on 27th.
-#
+#
# <a href="http://www.worldbulletin.net/?aType=haber&ArticleID=70872">
# http://www.worldbulletin.net/?aType=haber&ArticleID=70872
# </a>
@@ -2721,7 +2721,7 @@
# time this year after all.
#
# From Udo Schwedt (2011-10-18):
-# As far as I understand, the recent change to the Ukranian time zone
+# As far as I understand, the recent change to the Ukranian time zone
# (Europe/Kiev) to introduce permanent daylight saving time (similar
# to Russia) was reverted today:
#
--- a/jdk/make/sun/javazic/tzdata/leapseconds Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/leapseconds Thu Nov 15 00:54:54 2012 +0000
@@ -100,8 +100,8 @@
#
#
# A positive leap second will be introduced at the end of June 2012.
-# The sequence of dates of the UTC second markers will be:
-#
+# The sequence of dates of the UTC second markers will be:
+#
# 2012 June 30, 23h 59m 59s
# 2012 June 30, 23h 59m 60s
# 2012 July 1, 0h 0m 0s
@@ -118,6 +118,6 @@
#
#
# Daniel GAMBIS
-# Head
+# Head
# Earth Orientation Center of IERS
# Observatoire de Paris, France
--- a/jdk/make/sun/javazic/tzdata/northamerica Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/northamerica Thu Nov 15 00:54:54 2012 +0000
@@ -501,7 +501,7 @@
-8:00 US P%sT 1946
-8:00 - PST 1969
-8:00 US P%sT 1980 Apr 27 2:00
- -9:00 US Y%sT 1980 Oct 26 2:00
+ -9:00 US Y%sT 1980 Oct 26 2:00
-8:00 US P%sT 1983 Oct 30 2:00
-9:00 US Y%sT 1983 Nov 30
-9:00 US AK%sT
@@ -1866,7 +1866,7 @@
# Here is a summary of the three clock change events in Creston's history:
# 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
# Exact date unknown
-# 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
+# 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
# Exact date in October unknown; Sunday October 1 is a reasonable guess.
# 3. June 1918: switch to Pacific Daylight Time (GMT-7)
# Exact date in June unknown; Sunday June 2 is a reasonable guess.
@@ -2696,20 +2696,20 @@
# except that it switches at midnight standard time as usual.
#
# From Steffen Thorsen (2007-10-25):
-# Carlos Alberto Fonseca Arauz informed me that Cuba will end DST one week
+# Carlos Alberto Fonseca Arauz informed me that Cuba will end DST one week
# earlier - on the last Sunday of October, just like in 2006.
-#
+#
# He supplied these references:
-#
+#
# http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
# http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
-#
+#
# From Alex Kryvenishev (2007-10-25):
# Here is also article from Granma (Cuba):
-#
+#
# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
# http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
-#
+#
# http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
# From Arthur David Olson (2008-03-09):
@@ -2793,7 +2793,7 @@
# </a>
#
# From Steffen Thorsen (2011-10-30)
-# Cuba will end DST two weeks later this year. Instead of going back
+# Cuba will end DST two weeks later this year. Instead of going back
# tonight, it has been delayed to 2011-11-13 at 01:00.
#
# One source (Spanish)
@@ -2805,11 +2805,11 @@
# <a href="http://www.timeanddate.com/news/time/cuba-time-changes-2011.html">
# http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
# </a>
-#
+#
# From Steffen Thorsen (2012-03-01)
-# According to Radio Reloj, Cuba will start DST on Midnight between March
+# According to Radio Reloj, Cuba will start DST on Midnight between March
# 31 and April 1.
-#
+#
# Radio Reloj has the following info (Spanish):
# <a href="http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril">
# http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
@@ -2820,6 +2820,13 @@
# http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
# </a>
+# From Steffen Thorsen (2012-11-03):
+# Radio Reloj and many other sources report that Cuba is changing back
+# to standard time on 2012-11-04:
+# http://www.radioreloj.cu/index.php/noticias-radio-reloj/36-nacionales/9961-regira-horario-normal-en-cuba-desde-el-domingo-cuatro-de-noviembre
+# From Paul Eggert (2012-11-03):
+# For now, assume the future rule is first Sunday in November.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cuba 1928 only - Jun 10 0:00 1:00 D
Rule Cuba 1928 only - Oct 10 0:00 0 S
@@ -2857,7 +2864,7 @@
Rule Cuba 2011 only - Mar Sun>=15 0:00s 1:00 D
Rule Cuba 2011 only - Nov 13 0:00s 0 S
Rule Cuba 2012 only - Apr 1 0:00s 1:00 D
-Rule Cuba 2012 max - Oct lastSun 0:00s 0 S
+Rule Cuba 2012 max - Nov Sun>=1 0:00s 0 S
Rule Cuba 2013 max - Mar Sun>=8 0:00s 1:00 D
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
--- a/jdk/make/sun/javazic/tzdata/southamerica Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/sun/javazic/tzdata/southamerica Thu Nov 15 00:54:54 2012 +0000
@@ -254,7 +254,7 @@
Rule Arg 2007 only - Dec 30 0:00 1:00 S
Rule Arg 2008 2009 - Mar Sun>=15 0:00 0 -
Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
-
+
# From Mariano Absatz (2004-05-21):
# Today it was officially published that the Province of Mendoza is changing
# its timezone this winter... starting tomorrow night....
@@ -344,9 +344,9 @@
# confirms what Alex Krivenyshev has earlier sent to the tz
# emailing list about that San Luis plans to return to standard
# time much earlier than the rest of the country. It also
-# confirms that upon request the provinces San Juan and Mendoza
-# refused to follow San Luis in this change.
-#
+# confirms that upon request the provinces San Juan and Mendoza
+# refused to follow San Luis in this change.
+#
# The change is supposed to take place Monday the 21.st at 0:00
# hours. As far as I understand it if this goes ahead, we need
# a new timezone for San Luis (although there are also documented
@@ -408,7 +408,7 @@
# <a href="http://www.lanacion.com.ar/nota.asp?nota_id=1107912">
# http://www.lanacion.com.ar/nota.asp?nota_id=1107912
# </a>
-#
+#
# The press release says:
# (...) anunció que el próximo domingo a las 00:00 los puntanos deberán
# atrasar una hora sus relojes.
@@ -822,8 +822,8 @@
#
# From Alexander Krivenyshev (2011-10-04):
# State Bahia will return to Daylight savings time this year after 8 years off.
-# The announcement was made by Governor Jaques Wagner in an interview to a
-# television station in Salvador.
+# The announcement was made by Governor Jaques Wagner in an interview to a
+# television station in Salvador.
# In Portuguese:
# <a href="http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html">
@@ -852,6 +852,15 @@
# http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
# </a>
+# From Kelley Cook (2012-10-16):
+# The governor of state of Bahia in Brazil announced on Thursday that
+# due to public pressure, he is reversing the DST policy they implemented
+# last year and will not be going to Summer Time on October 21st....
+# http://www.correio24horas.com.br/r/artigo/apos-pressoes-wagner-suspende-horario-de-verao-na-bahia
+
+# From Rodrigo Severo (2012-10-16):
+# Tocantins state will have DST.
+# http://noticias.terra.com.br/brasil/noticias/0,,OI6232536-EI306.html
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
# Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
@@ -1071,7 +1080,8 @@
-3:00 Brazil BR%sT 1990 Sep 17
-3:00 - BRT 1995 Sep 14
-3:00 Brazil BR%sT 2003 Sep 24
- -3:00 - BRT
+ -3:00 - BRT 2012 Oct 21
+ -3:00 Brazil BR%sT
#
# Alagoas (AL), Sergipe (SE)
Zone America/Maceio -2:22:52 - LMT 1914
@@ -1090,7 +1100,8 @@
Zone America/Bahia -2:34:04 - LMT 1914
-3:00 Brazil BR%sT 2003 Sep 24
-3:00 - BRT 2011 Oct 16
- -3:00 Brazil BR%sT
+ -3:00 Brazil BR%sT 2012 Oct 21
+ -3:00 - BRT
#
# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
@@ -1182,7 +1193,7 @@
# Due to drought, Chile extends Daylight Time in three weeks. This
# is one-time change (Saturday 3/29 at 24:00 for America/Santiago
# and Saturday 3/29 at 22:00 for Pacific/Easter)
-# The Supreme Decree is located at
+# The Supreme Decree is located at
# <a href="http://www.shoa.cl/servicios/supremo316.pdf">
# http://www.shoa.cl/servicios/supremo316.pdf
# </a>
@@ -1193,7 +1204,7 @@
# From Jose Miguel Garrido (2008-03-05):
# ...
-# You could see the announces of the change on
+# You could see the announces of the change on
# <a href="http://www.shoa.cl/noticias/2008/04hora/hora.htm">
# http://www.shoa.cl/noticias/2008/04hora/hora.htm
# </a>.
--- a/jdk/make/tools/GenerateCharacter/CharacterData01.java.template Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/GenerateCharacter/CharacterData01.java.template Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -311,6 +311,8 @@
case 0x011063: retval = 90; break; // BRAHMI NUMBER NINETY
case 0x011064: retval = 100; break; // BRAHMI NUMBER ONE HUNDRED
case 0x011065: retval = 1000; break; // BRAHMI NUMBER ONE THOUSAND
+ case 0x012432: retval = 216000; break; // CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH
+ case 0x012433: retval = 432000; break; // CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN
case 0x01D36C: retval = 40; break; // COUNTING ROD TENS DIGIT FOUR
case 0x01D36D: retval = 50; break; // COUNTING ROD TENS DIGIT FIVE
case 0x01D36E: retval = 60; break; // COUNTING ROD TENS DIGIT SIX
--- a/jdk/make/tools/UnicodeData/PropList.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/UnicodeData/PropList.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# PropList-6.1.0.txt
-# Date: 2011-11-30, 01:49:54 GMT [MD]
+# PropList-6.2.0.txt
+# Date: 2012-05-23, 20:34:59 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
--- a/jdk/make/tools/UnicodeData/Scripts.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/UnicodeData/Scripts.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# Scripts-6.1.0.txt
-# Date: 2011-11-27, 05:10:50 GMT [MD]
+# Scripts-6.2.0.txt
+# Date: 2012-06-04, 17:21:29 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
@@ -146,7 +146,7 @@
208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS
208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS
-20A0..20B9 ; Common # Sc [26] EURO-CURRENCY SIGN..INDIAN RUPEE SIGN
+20A0..20BA ; Common # Sc [27] EURO-CURRENCY SIGN..TURKISH LIRA SIGN
2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
2102 ; Common # L& DOUBLE-STRUCK CAPITAL C
2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA
@@ -576,7 +576,7 @@
E0001 ; Common # Cf LANGUAGE TAG
E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
-# Total code points: 6412
+# Total code points: 6413
# ================================================
@@ -760,7 +760,7 @@
061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK
0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
-0656..065E ; Arabic # Mn [9] ARABIC SUBSCRIPT ALEF..ARABIC FATHA WITH TWO DOTS
+0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW
066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
@@ -827,7 +827,7 @@
1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
-# Total code points: 1234
+# Total code points: 1235
# ================================================
@@ -1477,7 +1477,6 @@
0300..036F ; Inherited # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
0485..0486 ; Inherited # Mn [2] COMBINING CYRILLIC DASIA PNEUMATA..COMBINING CYRILLIC PSILI PNEUMATA
064B..0655 ; Inherited # Mn [11] ARABIC FATHATAN..ARABIC HAMZA BELOW
-065F ; Inherited # Mn ARABIC WAVY HAMZA BELOW
0670 ; Inherited # Mn ARABIC LETTER SUPERSCRIPT ALEF
0951..0952 ; Inherited # Mn [2] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI STRESS SIGN ANUDATTA
1CD0..1CD2 ; Inherited # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
@@ -1504,7 +1503,7 @@
1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 524
+# Total code points: 523
# ================================================
--- a/jdk/make/tools/UnicodeData/SpecialCasing.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/UnicodeData/SpecialCasing.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# SpecialCasing-6.1.0.txt
-# Date: 2011-11-27, 05:10:51 GMT [MD]
+# SpecialCasing-6.2.0.txt
+# Date: 2012-05-23, 20:35:15 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
#
--- a/jdk/make/tools/UnicodeData/UnicodeData.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/UnicodeData/UnicodeData.txt Thu Nov 15 00:54:54 2012 +0000
@@ -7190,6 +7190,7 @@
20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;;
20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;;
20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
+20BA;TURKISH LIRA SIGN;Sc;0;ET;;;;;N;;;;;
20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
@@ -18703,8 +18704,8 @@
1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;;
12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;;
12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;;
-12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;;N;;;;;
-12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;;N;;;;;
+12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;216000;N;;;;;
+12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;432000;N;;;;;
12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;;
12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;;
12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;;
@@ -18739,8 +18740,8 @@
12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;;
12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;;
12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;;
-12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;;N;;;;;
-12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;;N;;;;;
+12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;-1;N;;;;;
+12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;-1;N;;;;;
12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;;
12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;;
1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;;
--- a/jdk/make/tools/UnicodeData/VERSION Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/make/tools/UnicodeData/VERSION Thu Nov 15 00:54:54 2012 +0000
@@ -1,1 +1,1 @@
-6.1.0
+6.2.0
--- a/jdk/makefiles/CompileNativeLibraries.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/CompileNativeLibraries.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -300,6 +300,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_SUFFIX:=$(BUILD_LIBMLIB_LDLIBS) \
$(LDFLAGS_JDKLIB_SUFFIX),\
+ LDFLAGS_SUFFIX_solaris:=-lc, \
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=mlib_image.dll" \
@@ -428,6 +429,7 @@
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(BUILD_LIBMLIB_LDLIBS) -ljava -ljvm \
$(call SET_SHARED_LIBRARY_ORIGIN),\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libmlib_image_v))
$(BUILD_LIBMLIB_IMAGE_V): $(BUILD_LIBJAVA)
@@ -710,7 +712,7 @@
LDFLAGS:=$(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_solaris:=-R/usr/dt/lib$(OPENJDK_TARGET_CPU_ISADIR) -R$(OPENWIN_LIB)$(OPENJDK_TARGET_CPU_ISADIR),\
LDFLAGS_SUFFIX_linux:=-ljvm $(LIBM) $(LIBDL) -ljava,\
- LDFLAGS_SUFFIX_solaris:=-ljvm $(LIBM) $(LIBDL) -ljava,\
+ LDFLAGS_SUFFIX_solaris:=-ljvm $(LIBM) $(LIBDL) -ljava -lc,\
LDFLAGS_SUFFIX_macosx:=-lmlib_image -ljvm $(LIBM) \
-framework Cocoa \
-framework OpenGL \
@@ -966,7 +968,7 @@
-export:ZIP_ReadEntry -export:ZIP_GetNextEntry jvm.lib \
$(WIN_JAVA_LIB),\
LDFLAGS_SUFFIX_linux:=-ljvm -ljava $(LIBZ),\
- LDFLAGS_SUFFIX_solaris:=-ljvm -ljava $(LIBZ),\
+ LDFLAGS_SUFFIX_solaris:=-ljvm -ljava $(LIBZ) -lc,\
LDFLAGS_SUFFIX_macosx:=$(LIBZ) -ljava -ljvm,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
@@ -1144,9 +1146,8 @@
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_SUFFIX_linux:=$(LIBDL),\
- LDFLAGS_SUFFIX_solaris:=$(LIBDL),\
+ LDFLAGS_SUFFIX_solaris:=$(LIBDL) -lc,\
LDFLAGS_SUFFIX_windows:=$(LDFLAGS_JDKLIB_SUFFIX),\
- LDFLAGS_SUFFIX:=,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=jdwp.dll" \
@@ -1186,7 +1187,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_windows:=netapi32.lib user32.lib mpr.lib advapi32.lib,\
LDFLAGS_SUFFIX_windows:=$(LDFLAGS_JDKLIB_SUFFIX),\
- LDFLAGS_SUFFIX:=,\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
EXCLUDE_FILES:=$(LIBJAAS_EXCLUDE_FILES),\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS) \
@@ -1217,7 +1218,7 @@
LDFLAGS_SUFFIX_linux:=$(LIBDL),\
LDFLAGS_SUFFIX_windows:=$(LDFLAGS_JDKLIB_SUFFIX) $(LIBDL),\
LDFLAGS_SUFFIX_macosx:= $(LIBDL),\
- LDFLAGS_SUFFIX:=,\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=jsdt.dll" \
@@ -1242,7 +1243,7 @@
INCLUDE_FILES:=cmscam02.c cmscgats.c cmscnvrt.c cmserr.c \
cmsgamma.c cmsgmt.c cmsintrp.c cmsio0.c \
cmsio1.c cmslut.c cmsmd5.c cmsmtrx.c \
- cmsnamed.c cmsopt.c cmspack.c cmspcs.c \
+ cmsnamed.c cmsopt.c cmshalf.c cmspack.c cmspcs.c \
cmsplugin.c cmsps2.c cmssamp.c cmssm.c \
cmstypes.c cmsvirt.c cmswtpnt.c cmsxform.c \
LCMS.c,\
@@ -1259,7 +1260,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_solaris:=/usr/lib$(OPENJDK_TARGET_CPU_ISADIR)/libm.so.2,\
LDFLAGS_windows:=$(WIN_AWT_LIB) $(WIN_JAVA_LIB),\
- LDFLAGS_SUFFIX_solaris:=-lawt -ljava -ljvm,\
+ LDFLAGS_SUFFIX_solaris:=-lawt -ljava -ljvm -lc,\
LDFLAGS_SUFFIX_macosx:=$(LIBM) -lawt -ljava -ljvm,\
LDFLAGS_SUFFIX_linux:=-lm -lawt -ljava -ljvm,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
@@ -1626,7 +1627,7 @@
-framework Cocoa -framework Security -framework ApplicationServices,\
LDFLAGS_SUFFIX:=$(LIBINSTRUMENT_LDFLAGS_SUFFIX),\
LDFLAGS_SUFFIX_macosx:=-liconv $(LIBZ),\
- LDFLAGS_SUFFIX_solaris:=$(LIBZ) -L $(INSTALL_LIBRARIES_HERE)/jli -ljli $(LIBDL),\
+ LDFLAGS_SUFFIX_solaris:=$(LIBZ) -L $(INSTALL_LIBRARIES_HERE)/jli -ljli $(LIBDL) -lc,\
LDFLAGS_SUFFIX_linux:=$(LIBZ) -L $(INSTALL_LIBRARIES_HERE)/jli -ljli $(LIBDL),\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
@@ -1716,10 +1717,6 @@
BUILD_LIBHPROF_LDFLAGS:=
-ifeq ($(OPENJDK_TARGET_OS),solaris)
- BUILD_LIBHPROF_LDFLAGS += -lsocket -lnsl -lc
-endif
-
LIBHPROF_OPTIMIZATION:=HIGHEST
ifneq ($(findstring $(OPENJDK_TARGET_OS),solaris linux),)
ifeq ($(ENABLE_DEBUG_SYMBOLS), yes)
@@ -1727,10 +1724,6 @@
endif
endif
-ifneq ($(OPENJDK_TARGET_OS),windows)
- BUILD_LIBHPROF_LDFLAGS += $(LIBDL)
-endif
-
$(eval $(call SetupNativeCompilation,BUILD_LIBHPROF,\
LIBRARY:=hprof, \
OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\
@@ -1744,7 +1737,9 @@
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_windows:=wsock32.lib winmm.lib advapi32.lib,\
- LDFLAGS_SUFFIX:=$(BUILD_LIBHPROF_LDFLAGS),\
+ LDFLAGS_SUFFIX_linux:=$(LIBDL),\
+ LDFLAGS_SUFFIX_macosx:=$(LIBDL),\
+ LDFLAGS_SUFFIX_solaris:=-lsocket -lnsl $(LIBDL) -lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=hprof.dll" \
@@ -1768,6 +1763,7 @@
MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libjava_crw_demo/mapfile-vers, \
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=java_crw_demo.dll" \
@@ -2392,7 +2388,7 @@
LANG:=C,\
OPTIMIZATION:=LOW, \
CFLAGS:=$(CFLAGS_JDKLIB) $(LIBAWT_HEADLESS_CFLAGS),\
- MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libawt_headless/mapfile-vers, \
+ MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libawt_headless/mapfile-vers,\
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_linux:=$(call SET_SHARED_LIBRARY_ORIGIN,/..),\
@@ -2402,8 +2398,8 @@
LDFLAGS_macosx:=$(call SET_SHARED_LIBRARY_ORIGIN).,\
REORDER:=$(LIBAWT_HEADLESS_REORDER), \
LDFLAGS_SUFFIX_linux:=-ljvm -lawt -lm $(LIBDL) -ljava,\
- LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX), \
- LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava, \
+ LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc,\
+ LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava,\
OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libawt_headless))
$(BUILD_LIBAWT_HEADLESS) : $(BUILD_LIBAWT)
@@ -2572,6 +2568,7 @@
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_SUFFIX:=$(LIBSPLASHSCREEN_LDFLAGS_SUFFIX) $(LIBZ),\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=splashscreen.dll" \
@@ -2647,6 +2644,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN),\
LDFLAGS_SUFFIX_posix:=$(LIBDL), \
LDFLAGS_SUFFIX_windows:=winscard.lib,\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=j2pcsc.dll" \
@@ -2673,7 +2671,8 @@
MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libj2gss/mapfile-vers, \
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
- LDFLAGS_SUFFIX:=$(LIBDL), \
+ LDFLAGS_SUFFIX:=$(LIBDL),\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libj2gss))
BUILD_LIBRARIES += $(BUILD_LIBJ2GSS)
@@ -2767,7 +2766,8 @@
MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libj2pkcs11/mapfile-vers, \
LDFLAGS:=$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN),\
- LDFLAGS_SUFFIX_posix:=$(LIBDL), \
+ LDFLAGS_SUFFIX_posix:=$(LIBDL),\
+ LDFLAGS_SUFFIX_solaris:=-lc,\
VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/windows/resource/version.rc,\
RC_FLAGS:=$(RC_FLAGS)\
-D "JDK_FNAME=j2pkcs11.dll" \
--- a/jdk/makefiles/CreateJars.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/CreateJars.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -271,7 +271,7 @@
ifeq ($(OPENJDK_TARGET_OS), macosx)
RT_JAR_EXCLUDES += com/sun/nio/sctp \
- sun/nio/ch/sctp \
+ sun/nio/ch/sctp
endif
# Find all files in the classes dir to use as dependencies. This could be more fine granular.
--- a/jdk/makefiles/GendataTimeZone.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/GendataTimeZone.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -26,7 +26,7 @@
GENDATA_TIMEZONE :=
# TODO: read from make/sun/javazic/tzdata/VERSION
-GENDATA_TIMEZONE_VERSION := tzdata2012c
+GENDATA_TIMEZONE_VERSION := tzdata2012i
GENDATA_TIMEZONE_DST := $(JDK_OUTPUTDIR)/lib/zi
GENDATA_TIMEZONE_TMP := $(JDK_OUTPUTDIR)/gendata_timezone
--- a/jdk/makefiles/GensrcIcons.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/GensrcIcons.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -109,13 +109,17 @@
ifeq ($(OPENJDK_TARGET_OS),macosx)
- GENSRC_OSX_ICONS = $(GENSRC_OSX_ICONS_DST)/AWTIconData.h
- GENSRC_OSX_ICONS_SRC =
- GENSRC_OSX_ICONS_TMP = $(JDK_OUTPUTDIR)/gensrc
- GENSRC_OSX_ICONS_DST = $(GENSRC_OSX_ICONS_TMP)/sun/osxapp
-
-$(GENSRC_OSX_ICONS_DST)/AWTIconData.h: \
- $(JDK_TOPDIR)/src/macosx/native/sun/osxapp/resource/icons/JavaApp.icns
+ GENSRC_OSX_ICONS_TMP := $(JDK_OUTPUTDIR)/gensrc
+ GENSRC_OSX_ICONS_DST := $(GENSRC_OSX_ICONS_TMP)/sun/osxapp
+ GENSRC_OSX_ICONS := $(GENSRC_OSX_ICONS_DST)/AWTIconData.h
+
+ ifdef OPENJDK
+ GENSRC_OSX_ICONS_SRC := $(JDK_TOPDIR)/src/macosx/native/sun/osxapp/resource/icons/JavaApp.icns
+ else
+ GENSRC_OSX_ICONS_SRC := $(JDK_TOPDIR)/src/closed/macosx/native/sun/osxapp/resource/icons/JavaApp.icns
+ endif
+
+$(GENSRC_OSX_ICONS_DST)/AWTIconData.h: $(GENSRC_OSX_ICONS_SRC)
$(RM) $@ $@.tmp
$(MKDIR) -p $(dir $@)
$(ECHO) "static unsigned char sAWTIconData[] = { " >> $@.tmp
--- a/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -68,8 +68,9 @@
ALL_US_LOCALES += $$($1_US_LOCALES)
ALL_NON_US_LOCALES += $$($1_NON_US_LOCALES)
- SED_ARGS+= -e 's/$$(HASH)$1_USLocales$$(HASH)/ $$($1_US_LOCALES)/g'
- SED_ARGS+= -e 's/$$(HASH)$1_NonUSLocales$$(HASH)/ $$($1_NON_US_LOCALES)/g'
+ # Don't sed in a space if there are no locales.
+ SED_ARGS+= -e 's/$$(HASH)$1_USLocales$$(HASH)/$$(if $$($1_US_LOCALES),$$(SPACE)$$($1_US_LOCALES),)/g'
+ SED_ARGS+= -e 's/$$(HASH)$1_NonUSLocales$$(HASH)/$$(if $$($1_NON_US_LOCALES),$$(SPACE)$$($1_NON_US_LOCALES),)/g'
endef
#sun.text.resources.FormatData
--- a/jdk/makefiles/Import.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/Import.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -121,7 +121,7 @@
endif
define CopyDir
- $1_SRC_FILES := $(shell $(FIND) $2 -type f -a ! -name "wb.jar")
+ $1_SRC_FILES := $(shell $(FIND) $2 -type f -a \( -name DUMMY $(addprefix -o$(SPACE)-name$(SPACE),$4) \))
$1_DST_FILES := $$(patsubst $2/%,$3/%,$$($1_SRC_FILES))
IMPORT_TARGET_FILES += $$($1_DST_FILES)
$3/% : $2/%
@@ -134,9 +134,10 @@
#
# Import hotspot
#
-
-$(eval $(call CopyDir,HOTSPOT0, $(HOTSPOT_LIB_DIR), $(INSTALL_LIBRARIES_HERE)))
-$(eval $(call CopyDir,HOTSPOT1, $(HOTSPOT_DIST)/lib, $(JDK_OUTPUTDIR)/lib))
+HOTSPOT_IMPORT_FILES:=$(addprefix $(LIBRARY_PREFIX), jvm.* saproc.* jsig.* sawindbg.* jvm_db.* jvm_dtrace.*) \
+ Xusage.txt sa-jdi.jar
+$(eval $(call CopyDir,HOTSPOT0, $(HOTSPOT_LIB_DIR), $(INSTALL_LIBRARIES_HERE), $(HOTSPOT_IMPORT_FILES)))
+$(eval $(call CopyDir,HOTSPOT1, $(HOTSPOT_DIST)/lib, $(JDK_OUTPUTDIR)/lib, $(HOTSPOT_IMPORT_FILES)))
JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
$(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
--- a/jdk/makefiles/Setup.gmk Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/makefiles/Setup.gmk Thu Nov 15 00:54:54 2012 +0000
@@ -45,7 +45,7 @@
JVM:=$(JAVA),\
JAVAC:=$(JAVAC_JARS),\
JAVAH:=$(JAVAH_JARS),\
- FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes -source 7 -target 7 -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS),\
+ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes -source 8 -target 8 -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS),\
SERVER_DIR:=$(SJAVAC_SERVER_DIR),\
SERVER_JVM:=$(SJAVAC_SERVER_JAVA)))
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBEKeyFactory.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBEKeyFactory.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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,12 +55,25 @@
}
static {
- validTypes = new HashSet<String>(4);
+ validTypes = new HashSet<String>(17);
validTypes.add("PBEWithMD5AndDES".toUpperCase());
validTypes.add("PBEWithSHA1AndDESede".toUpperCase());
validTypes.add("PBEWithSHA1AndRC2_40".toUpperCase());
+ validTypes.add("PBEWithSHA1AndRC2_128".toUpperCase());
+ validTypes.add("PBEWithSHA1AndRC4_40".toUpperCase());
+ validTypes.add("PBEWithSHA1AndRC4_128".toUpperCase());
// Proprietary algorithm.
validTypes.add("PBEWithMD5AndTripleDES".toUpperCase());
+ validTypes.add("PBEWithHmacSHA1AndAES_128".toUpperCase());
+ validTypes.add("PBEWithHmacSHA224AndAES_128".toUpperCase());
+ validTypes.add("PBEWithHmacSHA256AndAES_128".toUpperCase());
+ validTypes.add("PBEWithHmacSHA384AndAES_128".toUpperCase());
+ validTypes.add("PBEWithHmacSHA512AndAES_128".toUpperCase());
+ validTypes.add("PBEWithHmacSHA1AndAES_256".toUpperCase());
+ validTypes.add("PBEWithHmacSHA224AndAES_256".toUpperCase());
+ validTypes.add("PBEWithHmacSHA256AndAES_256".toUpperCase());
+ validTypes.add("PBEWithHmacSHA384AndAES_256".toUpperCase());
+ validTypes.add("PBEWithHmacSHA512AndAES_256".toUpperCase());
}
public static final class PBEWithMD5AndDES
@@ -84,6 +97,27 @@
}
}
+ public static final class PBEWithSHA1AndRC2_128
+ extends PBEKeyFactory {
+ public PBEWithSHA1AndRC2_128() {
+ super("PBEWithSHA1AndRC2_128");
+ }
+ }
+
+ public static final class PBEWithSHA1AndRC4_40
+ extends PBEKeyFactory {
+ public PBEWithSHA1AndRC4_40() {
+ super("PBEWithSHA1AndRC4_40");
+ }
+ }
+
+ public static final class PBEWithSHA1AndRC4_128
+ extends PBEKeyFactory {
+ public PBEWithSHA1AndRC4_128() {
+ super("PBEWithSHA1AndRC4_128");
+ }
+ }
+
/*
* Private proprietary algorithm for supporting JCEKS.
*/
@@ -94,6 +128,75 @@
}
}
+ public static final class PBEWithHmacSHA1AndAES_128
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA1AndAES_128() {
+ super("PBEWithHmacSHA1AndAES_128");
+ }
+ }
+
+ public static final class PBEWithHmacSHA224AndAES_128
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA224AndAES_128() {
+ super("PBEWithHmacSHA224AndAES_128");
+ }
+ }
+
+ public static final class PBEWithHmacSHA256AndAES_128
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA256AndAES_128() {
+ super("PBEWithHmacSHA256AndAES_128");
+ }
+ }
+
+ public static final class PBEWithHmacSHA384AndAES_128
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA384AndAES_128() {
+ super("PBEWithHmacSHA384AndAES_128");
+ }
+ }
+
+ public static final class PBEWithHmacSHA512AndAES_128
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA512AndAES_128() {
+ super("PBEWithHmacSHA512AndAES_128");
+ }
+ }
+
+ public static final class PBEWithHmacSHA1AndAES_256
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA1AndAES_256() {
+ super("PBEWithHmacSHA1AndAES_256");
+ }
+ }
+
+ public static final class PBEWithHmacSHA224AndAES_256
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA224AndAES_256() {
+ super("PBEWithHmacSHA224AndAES_256");
+ }
+ }
+
+ public static final class PBEWithHmacSHA256AndAES_256
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA256AndAES_256() {
+ super("PBEWithHmacSHA256AndAES_256");
+ }
+ }
+
+ public static final class PBEWithHmacSHA384AndAES_256
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA384AndAES_256() {
+ super("PBEWithHmacSHA384AndAES_256");
+ }
+ }
+
+ public static final class PBEWithHmacSHA512AndAES_256
+ extends PBEKeyFactory {
+ public PBEWithHmacSHA512AndAES_256() {
+ super("PBEWithHmacSHA512AndAES_256");
+ }
+ }
/**
* Generates a <code>SecretKey</code> object from the provided key
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBEParameters.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBEParameters.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. 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
@@ -57,6 +57,9 @@
// the iteration count
private int iCount = 0;
+ // the cipher parameter
+ private AlgorithmParameterSpec cipherParam = null;
+
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException
{
@@ -66,6 +69,7 @@
}
this.salt = ((PBEParameterSpec)paramSpec).getSalt().clone();
this.iCount = ((PBEParameterSpec)paramSpec).getIterationCount();
+ this.cipherParam = ((PBEParameterSpec)paramSpec).getParameterSpec();
}
protected void engineInit(byte[] encoded)
@@ -102,7 +106,8 @@
throws InvalidParameterSpecException
{
if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) {
- return paramSpec.cast(new PBEParameterSpec(this.salt, this.iCount));
+ return paramSpec.cast(
+ new PBEParameterSpec(this.salt, this.iCount, this.cipherParam));
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES1Core.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+/**
+ * This class represents password-based encryption as defined by the PKCS #5
+ * standard.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see javax.crypto.Cipher
+ */
+final class PBES1Core {
+
+ // the encapsulated DES cipher
+ private CipherCore cipher;
+ private MessageDigest md;
+ private int blkSize;
+ private String algo = null;
+ private byte[] salt = null;
+ private int iCount = 10;
+
+ /**
+ * Creates an instance of PBE Cipher using the specified CipherSpi
+ * instance.
+ *
+ */
+ PBES1Core(String cipherAlg) throws NoSuchAlgorithmException,
+ NoSuchPaddingException {
+ algo = cipherAlg;
+ if (algo.equals("DES")) {
+ cipher = new CipherCore(new DESCrypt(),
+ DESConstants.DES_BLOCK_SIZE);
+ } else if (algo.equals("DESede")) {
+
+ cipher = new CipherCore(new DESedeCrypt(),
+ DESConstants.DES_BLOCK_SIZE);
+ } else {
+ throw new NoSuchAlgorithmException("No Cipher implementation " +
+ "for PBEWithMD5And" + algo);
+ }
+ cipher.setMode("CBC");
+ cipher.setPadding("PKCS5Padding");
+ // get instance of MD5
+ md = MessageDigest.getInstance("MD5");
+ }
+
+ /**
+ * Sets the mode of this cipher. This algorithm can only be run in CBC
+ * mode.
+ *
+ * @param mode the cipher mode
+ *
+ * @exception NoSuchAlgorithmException if the requested cipher mode is
+ * invalid
+ */
+ void setMode(String mode) throws NoSuchAlgorithmException {
+ cipher.setMode(mode);
+ }
+
+ /**
+ * Sets the padding mechanism of this cipher. This algorithm only uses
+ * PKCS #5 padding.
+ *
+ * @param padding the padding mechanism
+ *
+ * @exception NoSuchPaddingException if the requested padding mechanism
+ * is invalid
+ */
+ void setPadding(String paddingScheme) throws NoSuchPaddingException {
+ cipher.setPadding(paddingScheme);
+ }
+
+ /**
+ * Returns the block size (in bytes).
+ *
+ * @return the block size (in bytes)
+ */
+ int getBlockSize() {
+ return DESConstants.DES_BLOCK_SIZE;
+ }
+
+ /**
+ * Returns the length in bytes that an output buffer would need to be in
+ * order to hold the result of the next <code>update</code> or
+ * <code>doFinal</code> operation, given the input length
+ * <code>inputLen</code> (in bytes).
+ *
+ * <p>This call takes into account any unprocessed (buffered) data from a
+ * previous <code>update</code> call, and padding.
+ *
+ * <p>The actual output length of the next <code>update</code> or
+ * <code>doFinal</code> call may be smaller than the length returned by
+ * this method.
+ *
+ * @param inputLen the input length (in bytes)
+ *
+ * @return the required output buffer size (in bytes)
+ *
+ */
+ int getOutputSize(int inputLen) {
+ return cipher.getOutputSize(inputLen);
+ }
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ *
+ * <p> This is useful in the case where a random IV has been created
+ * (see <a href = "#init">init</a>),
+ * or in the context of password-based encryption or
+ * decryption, where the IV is derived from a user-supplied password.
+ *
+ * @return the initialization vector in a new buffer, or null if the
+ * underlying algorithm does not use an IV, or if the IV has not yet
+ * been set.
+ */
+ byte[] getIV() {
+ return cipher.getIV();
+ }
+
+ /**
+ * Returns the parameters used with this cipher.
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this cipher, or may contain the default set of parameters or a set of
+ * randomly generated parameters used by the underlying cipher
+ * implementation (provided that the underlying cipher implementation
+ * uses a default set of parameters or creates new parameters if it needs
+ * parameters but was not initialized with any).
+ *
+ * @return the parameters used with this cipher, or null if this cipher
+ * does not use any parameters.
+ */
+ AlgorithmParameters getParameters() {
+ AlgorithmParameters params = null;
+ if (salt == null) {
+ salt = new byte[8];
+ SunJCE.RANDOM.nextBytes(salt);
+ }
+ PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
+ try {
+ params = AlgorithmParameters.getInstance("PBEWithMD5And" +
+ (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), "SunJCE");
+ } catch (NoSuchAlgorithmException nsae) {
+ // should never happen
+ throw new RuntimeException("SunJCE called, but not configured");
+ } catch (NoSuchProviderException nspe) {
+ // should never happen
+ throw new RuntimeException("SunJCE called, but not configured");
+ }
+ try {
+ params.init(pbeSpec);
+ } catch (InvalidParameterSpecException ipse) {
+ // should never happen
+ throw new RuntimeException("PBEParameterSpec not supported");
+ }
+ return params;
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of
+ * algorithm parameters, and a source of randomness.
+ * The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes, it will get them from <code>random</code>.
+ *
+ * @param opmode the operation mode of this cipher (this is one of
+ * the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher
+ */
+ void init(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (((opmode == Cipher.DECRYPT_MODE) ||
+ (opmode == Cipher.UNWRAP_MODE)) && (params == null)) {
+ throw new InvalidAlgorithmParameterException("Parameters "
+ + "missing");
+ }
+ if ((key == null) ||
+ (key.getEncoded() == null) ||
+ !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
+ }
+
+ if (params == null) {
+ // create random salt and use default iteration count
+ salt = new byte[8];
+ random.nextBytes(salt);
+ } else {
+ if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: PBE expected");
+ }
+ salt = ((PBEParameterSpec) params).getSalt();
+ // salt must be 8 bytes long (by definition)
+ if (salt.length != 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be 8 bytes long");
+ }
+ iCount = ((PBEParameterSpec) params).getIterationCount();
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
+ }
+
+ byte[] derivedKey = deriveCipherKey(key);
+ // use all but the last 8 bytes as the key value
+ SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
+ derivedKey.length-8, algo);
+ // use the last 8 bytes as the IV
+ IvParameterSpec ivSpec = new IvParameterSpec(derivedKey,
+ derivedKey.length-8,
+ 8);
+ // initialize the underlying cipher
+ cipher.init(opmode, cipherKey, ivSpec, random);
+ }
+
+ private byte[] deriveCipherKey(Key key) {
+
+ byte[] result = null;
+ byte[] passwdBytes = key.getEncoded();
+
+ if (algo.equals("DES")) {
+ // P || S (password concatenated with salt)
+ byte[] concat = new byte[passwdBytes.length + salt.length];
+ System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
+ java.util.Arrays.fill(passwdBytes, (byte)0x00);
+ System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
+
+ // digest P || S with c iterations
+ byte[] toBeHashed = concat;
+ for (int i = 0; i < iCount; i++) {
+ md.update(toBeHashed);
+ toBeHashed = md.digest(); // this resets the digest
+ }
+ java.util.Arrays.fill(concat, (byte)0x00);
+ result = toBeHashed;
+ } else if (algo.equals("DESede")) {
+ // if the 2 salt halves are the same, invert one of them
+ int i;
+ for (i=0; i<4; i++) {
+ if (salt[i] != salt[i+4])
+ break;
+ }
+ if (i==4) { // same, invert 1st half
+ for (i=0; i<2; i++) {
+ byte tmp = salt[i];
+ salt[i] = salt[3-i];
+ salt[3-1] = tmp;
+ }
+ }
+
+ // Now digest each half (concatenated with password). For each
+ // half, go through the loop as many times as specified by the
+ // iteration count parameter (inner for loop).
+ // Concatenate the output from each digest round with the
+ // password, and use the result as the input to the next digest
+ // operation.
+ byte[] kBytes = null;
+ IvParameterSpec iv = null;
+ byte[] toBeHashed = null;
+ result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
+ DESConstants.DES_BLOCK_SIZE];
+ for (i = 0; i < 2; i++) {
+ toBeHashed = new byte[salt.length/2];
+ System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0,
+ toBeHashed.length);
+ for (int j=0; j < iCount; j++) {
+ md.update(toBeHashed);
+ md.update(passwdBytes);
+ toBeHashed = md.digest(); // this resets the digest
+ }
+ System.arraycopy(toBeHashed, 0, result, i*16,
+ toBeHashed.length);
+ }
+ }
+ return result;
+ }
+
+ void init(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ PBEParameterSpec pbeSpec = null;
+ if (params != null) {
+ try {
+ pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ throw new InvalidAlgorithmParameterException("Wrong parameter "
+ + "type: PBE "
+ + "expected");
+ }
+ }
+ init(opmode, key, pbeSpec, random);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code>, are processed, and the
+ * result is stored in a new buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result
+ *
+ */
+ byte[] update(byte[] input, int inputOffset, int inputLen) {
+ return cipher.update(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code>, are processed, and the
+ * result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code>.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ int update(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException {
+ return cipher.update(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation,
+ * or finishes a multiple-part operation.
+ * The data is encrypted or decrypted, depending on how this cipher was
+ * initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code>, and any input bytes that
+ * may have been buffered during a previous <code>update</code> operation,
+ * are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ *
+ * <p>The cipher is reset to its initial state (uninitialized) after this
+ * call.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception BadPaddingException if decrypting and padding is choosen,
+ * but the last input data does not have proper padding bytes.
+ */
+ byte[] doFinal(byte[] input, int inputOffset, int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return cipher.doFinal(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation,
+ * or finishes a multiple-part operation.
+ * The data is encrypted or decrypted, depending on how this cipher was
+ * initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code>, and any input bytes that
+ * may have been buffered during a previous <code>update</code> operation,
+ * are processed, with padding (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code>.
+ *
+ * <p>The cipher is reset to its initial state (uninitialized) after this
+ * call.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if decrypting and padding is choosen,
+ * but the last input data does not have proper padding bytes.
+ */
+ int doFinal(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return cipher.doFinal(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ /**
+ * Wrap a key.
+ *
+ * @param key the key to be wrapped.
+ *
+ * @return the wrapped key.
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block
+ * cipher, no padding has been requested, and the length of the
+ * encoding of the key to be wrapped is not a
+ * multiple of the block size.
+ *
+ * @exception InvalidKeyException if it is impossible or unsafe to
+ * wrap the key with this cipher (e.g., a hardware protected key is
+ * being passed to a software only cipher).
+ */
+ byte[] wrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ byte[] result = null;
+
+ try {
+ byte[] encodedKey = key.getEncoded();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidKeyException("Cannot get an encoding of " +
+ "the key to be wrapped");
+ }
+
+ result = doFinal(encodedKey, 0, encodedKey.length);
+ } catch (BadPaddingException e) {
+ // Should never happen
+ }
+
+ return result;
+ }
+
+ /**
+ * Unwrap a previously wrapped key.
+ *
+ * @param wrappedKey the key to be unwrapped.
+ *
+ * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
+ *
+ * @param wrappedKeyType the type of the wrapped key.
+ * This is one of <code>Cipher.SECRET_KEY</code>,
+ * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
+ *
+ * @return the unwrapped key.
+ *
+ * @exception NoSuchAlgorithmException if no installed providers
+ * can create keys of type <code>wrappedKeyType</code> for the
+ * <code>wrappedKeyAlgorithm</code>.
+ *
+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
+ * represent a wrapped key of type <code>wrappedKeyType</code> for
+ * the <code>wrappedKeyAlgorithm</code>.
+ */
+ Key unwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ byte[] encodedKey;
+ try {
+ encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
+ } catch (BadPaddingException ePadding) {
+ throw new InvalidKeyException("The wrapped key is not padded " +
+ "correctly");
+ } catch (IllegalBlockSizeException eBlockSize) {
+ throw new InvalidKeyException("The wrapped key does not have " +
+ "the correct length");
+ }
+ return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES2Core.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.io.UnsupportedEncodingException;
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.interfaces.*;
+import javax.crypto.spec.*;
+
+/**
+ * This class represents password-based encryption as defined by the PKCS #5
+ * standard.
+ * These algorithms implement PBE with HmacSHA1/HmacSHA2-family and AES-CBC.
+ * Padding is done as described in PKCS #5.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see javax.crypto.Cipher
+ */
+abstract class PBES2Core extends CipherSpi {
+
+ private static final int DEFAULT_SALT_LENGTH = 20;
+ private static final int DEFAULT_COUNT = 4096;
+
+ // the encapsulated cipher
+ private final CipherCore cipher;
+ private final int keyLength; // in bits
+ private final int blkSize; // in bits
+ private final PBKDF2Core kdf;
+ private final String pbeAlgo;
+ private final String cipherAlgo;
+ private int iCount = DEFAULT_COUNT;
+ private byte[] salt = null;
+ private IvParameterSpec ivSpec = null;
+
+ /**
+ * Creates an instance of PBE Scheme 2 according to the selected
+ * password-based key derivation function and encryption scheme.
+ */
+ PBES2Core(String kdfAlgo, String cipherAlgo, int keySize)
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+
+ this.cipherAlgo = cipherAlgo;
+ keyLength = keySize * 8;
+ pbeAlgo = "PBEWith" + kdfAlgo + "And" + cipherAlgo + "_" + keyLength;
+
+ if (cipherAlgo.equals("AES")) {
+ blkSize = AESConstants.AES_BLOCK_SIZE;
+ cipher = new CipherCore(new AESCrypt(), blkSize);
+
+ switch(kdfAlgo) {
+ case "HmacSHA1":
+ kdf = new PBKDF2Core.HmacSHA1();
+ break;
+ case "HmacSHA224":
+ kdf = new PBKDF2Core.HmacSHA224();
+ break;
+ case "HmacSHA256":
+ kdf = new PBKDF2Core.HmacSHA256();
+ break;
+ case "HmacSHA384":
+ kdf = new PBKDF2Core.HmacSHA384();
+ break;
+ case "HmacSHA512":
+ kdf = new PBKDF2Core.HmacSHA512();
+ break;
+ default:
+ throw new NoSuchAlgorithmException(
+ "No Cipher implementation for " + kdfAlgo);
+ }
+ } else {
+ throw new NoSuchAlgorithmException("No Cipher implementation for " +
+ pbeAlgo);
+ }
+ cipher.setMode("CBC");
+ cipher.setPadding("PKCS5Padding");
+ }
+
+ protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+ if ((mode != null) && (!mode.equalsIgnoreCase("CBC"))) {
+ throw new NoSuchAlgorithmException("Invalid cipher mode: " + mode);
+ }
+ }
+
+ protected void engineSetPadding(String paddingScheme)
+ throws NoSuchPaddingException {
+ if ((paddingScheme != null) &&
+ (!paddingScheme.equalsIgnoreCase("PKCS5Padding"))) {
+ throw new NoSuchPaddingException("Invalid padding scheme: " +
+ paddingScheme);
+ }
+ }
+
+ protected int engineGetBlockSize() {
+ return blkSize;
+ }
+
+ protected int engineGetOutputSize(int inputLen) {
+ return cipher.getOutputSize(inputLen);
+ }
+
+ protected byte[] engineGetIV() {
+ return cipher.getIV();
+ }
+
+ protected AlgorithmParameters engineGetParameters() {
+ AlgorithmParameters params = null;
+ if (salt == null) {
+ // generate random salt and use default iteration count
+ salt = new byte[DEFAULT_SALT_LENGTH];
+ SunJCE.RANDOM.nextBytes(salt);
+ iCount = DEFAULT_COUNT;
+ }
+ if (ivSpec == null) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ SunJCE.RANDOM.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ }
+ PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
+ try {
+ params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE");
+ } catch (NoSuchAlgorithmException nsae) {
+ // should never happen
+ throw new RuntimeException("SunJCE called, but not configured");
+ } catch (NoSuchProviderException nspe) {
+ // should never happen
+ throw new RuntimeException("SunJCE called, but not configured");
+ }
+ try {
+ params.init(pbeSpec);
+ } catch (InvalidParameterSpecException ipse) {
+ // should never happen
+ throw new RuntimeException("PBEParameterSpec not supported");
+ }
+ return params;
+ }
+
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ try {
+ engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
+ } catch (InvalidAlgorithmParameterException ie) {
+ InvalidKeyException ike =
+ new InvalidKeyException("requires PBE parameters");
+ ike.initCause(ie);
+ throw ike;
+ }
+ }
+
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if ((key == null) ||
+ (key.getEncoded() == null) ||
+ !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
+ }
+
+ // TBD: consolidate the salt, ic and IV parameter checks below
+
+ // Extract salt and iteration count from the key, if present
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
+ if (salt != null && salt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
+ if (iCount == 0) {
+ iCount = DEFAULT_COUNT;
+ } else if (iCount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
+ }
+
+ // Extract salt, iteration count and IV from the params, if present
+ if (params == null) {
+ if (salt == null) {
+ // generate random salt and use default iteration count
+ salt = new byte[DEFAULT_SALT_LENGTH];
+ random.nextBytes(salt);
+ iCount = DEFAULT_COUNT;
+ }
+ if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ }
+ } else {
+ if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: PBE expected");
+ }
+ // salt and iteration count from the params take precedence
+ byte[] specSalt = ((PBEParameterSpec) params).getSalt();
+ if (specSalt != null && specSalt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ salt = specSalt;
+ int specICount = ((PBEParameterSpec) params).getIterationCount();
+ if (specICount == 0) {
+ specICount = DEFAULT_COUNT;
+ } else if (specICount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
+ iCount = specICount;
+
+ AlgorithmParameterSpec specParams =
+ ((PBEParameterSpec) params).getParameterSpec();
+ if (specParams != null) {
+ if (specParams instanceof IvParameterSpec) {
+ ivSpec = (IvParameterSpec)specParams;
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "Wrong parameter type: IV expected");
+ }
+ } else if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "Missing parameter type: IV expected");
+ }
+ }
+
+ SecretKeySpec cipherKey = null;
+ byte[] derivedKey = null;
+ byte[] passwdBytes = key.getEncoded();
+ char[] passwdChars = new char[passwdBytes.length];
+
+ for (int i=0; i<passwdChars.length; i++)
+ passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
+
+ PBEKeySpec pbeSpec =
+ new PBEKeySpec(passwdChars, salt, iCount, blkSize * 8);
+ // password char[] was cloned in PBEKeySpec constructor,
+ // so we can zero it out here
+ java.util.Arrays.fill(passwdChars, ' ');
+ java.util.Arrays.fill(passwdBytes, (byte)0x00);
+
+ SecretKey s = null;
+
+ try {
+ s = kdf.engineGenerateSecret(pbeSpec);
+
+ } catch (InvalidKeySpecException ikse) {
+ InvalidKeyException ike =
+ new InvalidKeyException("Cannot construct PBE key");
+ ike.initCause(ikse);
+ throw ike;
+ }
+ derivedKey = s.getEncoded();
+ cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
+
+ // initialize the underlying cipher
+ cipher.init(opmode, cipherKey, ivSpec, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ AlgorithmParameterSpec pbeSpec = null;
+ if (params != null) {
+ try {
+ pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ throw new InvalidAlgorithmParameterException(
+ "Wrong parameter type: PBE expected");
+ }
+ }
+ engineInit(opmode, key, pbeSpec, random);
+ }
+
+ protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+ return cipher.update(input, inputOffset, inputLen);
+ }
+
+ protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException {
+ return cipher.update(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return cipher.doFinal(input, inputOffset, inputLen);
+ }
+
+ protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return cipher.doFinal(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return keyLength;
+ }
+
+ protected byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ return cipher.wrap(key);
+ }
+
+ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ byte[] encodedKey;
+ return cipher.unwrap(wrappedKey, wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+
+ public static final class HmacSHA1AndAES_128 extends PBES2Core {
+ public HmacSHA1AndAES_128()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA1", "AES", 16);
+ }
+ }
+
+ public static final class HmacSHA224AndAES_128 extends PBES2Core {
+ public HmacSHA224AndAES_128()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA224", "AES", 16);
+ }
+ }
+
+ public static final class HmacSHA256AndAES_128 extends PBES2Core {
+ public HmacSHA256AndAES_128()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA256", "AES", 16);
+ }
+ }
+
+ public static final class HmacSHA384AndAES_128 extends PBES2Core {
+ public HmacSHA384AndAES_128()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA384", "AES", 16);
+ }
+ }
+
+ public static final class HmacSHA512AndAES_128 extends PBES2Core {
+ public HmacSHA512AndAES_128()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA512", "AES", 16);
+ }
+ }
+
+ public static final class HmacSHA1AndAES_256 extends PBES2Core {
+ public HmacSHA1AndAES_256()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA1", "AES", 32);
+ }
+ }
+
+ public static final class HmacSHA224AndAES_256 extends PBES2Core {
+ public HmacSHA224AndAES_256()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA224", "AES", 32);
+ }
+ }
+
+ public static final class HmacSHA256AndAES_256 extends PBES2Core {
+ public HmacSHA256AndAES_256()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA256", "AES", 32);
+ }
+ }
+
+ public static final class HmacSHA384AndAES_256 extends PBES2Core {
+ public HmacSHA384AndAES_256()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA384", "AES", 32);
+ }
+ }
+
+ public static final class HmacSHA512AndAES_256 extends PBES2Core {
+ public HmacSHA512AndAES_256()
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super("HmacSHA512", "AES", 32);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBES2Parameters.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.AlgorithmParametersSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEParameterSpec;
+import sun.misc.HexDumpEncoder;
+import sun.security.util.*;
+
+/**
+ * This class implements the parameter set used with password-based
+ * encryption scheme 2 (PBES2), which is defined in PKCS#5 as follows:
+ *
+ * <pre>
+ * -- PBES2
+ *
+ * PBES2Algorithms ALGORITHM-IDENTIFIER ::=
+ * { {PBES2-params IDENTIFIED BY id-PBES2}, ...}
+ *
+ * id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
+ *
+ * PBES2-params ::= SEQUENCE {
+ * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+ *
+ * PBES2-KDFs ALGORITHM-IDENTIFIER ::=
+ * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+ *
+ * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... }
+ *
+ * -- PBKDF2
+ *
+ * PBKDF2Algorithms ALGORITHM-IDENTIFIER ::=
+ * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...}
+ *
+ * id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12}
+ *
+ * PBKDF2-params ::= SEQUENCE {
+ * salt CHOICE {
+ * specified OCTET STRING,
+ * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ * },
+ * iterationCount INTEGER (1..MAX),
+ * keyLength INTEGER (1..MAX) OPTIONAL,
+ * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
+ * }
+ *
+ * PBKDF2-SaltSources ALGORITHM-IDENTIFIER ::= { ... }
+ *
+ * PBKDF2-PRFs ALGORITHM-IDENTIFIER ::= {
+ * {NULL IDENTIFIED BY id-hmacWithSHA1} |
+ * {NULL IDENTIFIED BY id-hmacWithSHA224} |
+ * {NULL IDENTIFIED BY id-hmacWithSHA256} |
+ * {NULL IDENTIFIED BY id-hmacWithSHA384} |
+ * {NULL IDENTIFIED BY id-hmacWithSHA512}, ... }
+ *
+ * algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::=
+ * {algorithm id-hmacWithSHA1, parameters NULL : NULL}
+ *
+ * id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7}
+ *
+ * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... }
+ *
+ * </pre>
+ */
+
+abstract class PBES2Parameters extends AlgorithmParametersSpi {
+
+ private static final int pkcs5PBKDF2[] =
+ {1, 2, 840, 113549, 1, 5, 12};
+ private static final int pkcs5PBES2[] =
+ {1, 2, 840, 113549, 1, 5, 13};
+ private static final int hmacWithSHA1[] =
+ {1, 2, 840, 113549, 2, 7};
+ private static final int hmacWithSHA224[] =
+ {1, 2, 840, 113549, 2, 8};
+ private static final int hmacWithSHA256[] =
+ {1, 2, 840, 113549, 2, 9};
+ private static final int hmacWithSHA384[] =
+ {1, 2, 840, 113549, 2, 10};
+ private static final int hmacWithSHA512[] =
+ {1, 2, 840, 113549, 2, 11};
+ private static final int aes128CBC[] =
+ {2, 16, 840, 1, 101, 3, 4, 1, 2};
+ private static final int aes192CBC[] =
+ {2, 16, 840, 1, 101, 3, 4, 1, 22};
+ private static final int aes256CBC[] =
+ {2, 16, 840, 1, 101, 3, 4, 1, 42};
+
+ private static ObjectIdentifier pkcs5PBKDF2_OID;
+ private static ObjectIdentifier pkcs5PBES2_OID;
+ private static ObjectIdentifier hmacWithSHA1_OID;
+ private static ObjectIdentifier hmacWithSHA224_OID;
+ private static ObjectIdentifier hmacWithSHA256_OID;
+ private static ObjectIdentifier hmacWithSHA384_OID;
+ private static ObjectIdentifier hmacWithSHA512_OID;
+ private static ObjectIdentifier aes128CBC_OID;
+ private static ObjectIdentifier aes192CBC_OID;
+ private static ObjectIdentifier aes256CBC_OID;
+
+ static {
+ try {
+ pkcs5PBKDF2_OID = new ObjectIdentifier(pkcs5PBKDF2);
+ pkcs5PBES2_OID = new ObjectIdentifier(pkcs5PBES2);
+ hmacWithSHA1_OID = new ObjectIdentifier(hmacWithSHA1);
+ hmacWithSHA224_OID = new ObjectIdentifier(hmacWithSHA224);
+ hmacWithSHA256_OID = new ObjectIdentifier(hmacWithSHA256);
+ hmacWithSHA384_OID = new ObjectIdentifier(hmacWithSHA384);
+ hmacWithSHA512_OID = new ObjectIdentifier(hmacWithSHA512);
+ aes128CBC_OID = new ObjectIdentifier(aes128CBC);
+ aes192CBC_OID = new ObjectIdentifier(aes192CBC);
+ aes256CBC_OID = new ObjectIdentifier(aes256CBC);
+ } catch (IOException ioe) {
+ // should not happen
+ }
+ }
+
+ // the PBES2 algorithm name
+ private String pbes2AlgorithmName = null;
+
+ // the salt
+ private byte[] salt = null;
+
+ // the iteration count
+ private int iCount = 0;
+
+ // the cipher parameter
+ private AlgorithmParameterSpec cipherParam = null;
+
+ // the key derivation function (default is HmacSHA1)
+ private ObjectIdentifier kdfAlgo_OID = hmacWithSHA1_OID;
+
+ // the encryption function
+ private ObjectIdentifier cipherAlgo_OID = null;
+
+ // the cipher keysize (in bits)
+ private int keysize = -1;
+
+ PBES2Parameters() {
+ // KDF, encryption & keysize values are set later, in engineInit(byte[])
+ }
+
+ PBES2Parameters(String pbes2AlgorithmName) throws NoSuchAlgorithmException {
+ int and;
+ String kdfAlgo = null;
+ String cipherAlgo = null;
+
+ // Extract the KDF and encryption algorithm names
+ this.pbes2AlgorithmName = pbes2AlgorithmName;
+ if (pbes2AlgorithmName.startsWith("PBEWith") &&
+ (and = pbes2AlgorithmName.indexOf("And", 7 + 1)) > 0) {
+ kdfAlgo = pbes2AlgorithmName.substring(7, and);
+ cipherAlgo = pbes2AlgorithmName.substring(and + 3);
+
+ // Check for keysize
+ int underscore;
+ if ((underscore = cipherAlgo.indexOf('_')) > 0) {
+ int slash;
+ if ((slash = cipherAlgo.indexOf('/', underscore + 1)) > 0) {
+ keysize =
+ Integer.parseInt(cipherAlgo.substring(underscore + 1,
+ slash));
+ } else {
+ keysize =
+ Integer.parseInt(cipherAlgo.substring(underscore + 1));
+ }
+ cipherAlgo = cipherAlgo.substring(0, underscore);
+ }
+ } else {
+ throw new NoSuchAlgorithmException("No crypto implementation for " +
+ pbes2AlgorithmName);
+ }
+
+ switch (kdfAlgo) {
+ case "HmacSHA1":
+ kdfAlgo_OID = hmacWithSHA1_OID;
+ break;
+ case "HmacSHA224":
+ kdfAlgo_OID = hmacWithSHA224_OID;
+ break;
+ case "HmacSHA256":
+ kdfAlgo_OID = hmacWithSHA256_OID;
+ break;
+ case "HmacSHA384":
+ kdfAlgo_OID = hmacWithSHA384_OID;
+ break;
+ case "HmacSHA512":
+ kdfAlgo_OID = hmacWithSHA512_OID;
+ break;
+ default:
+ throw new NoSuchAlgorithmException(
+ "No crypto implementation for " + kdfAlgo);
+ }
+
+ if (cipherAlgo.equals("AES")) {
+ this.keysize = keysize;
+ switch (keysize) {
+ case 128:
+ cipherAlgo_OID = aes128CBC_OID;
+ break;
+ case 256:
+ cipherAlgo_OID = aes256CBC_OID;
+ break;
+ default:
+ throw new NoSuchAlgorithmException(
+ "No Cipher implementation for " + keysize + "-bit " +
+ cipherAlgo);
+ }
+ } else {
+ throw new NoSuchAlgorithmException("No Cipher implementation for " +
+ cipherAlgo);
+ }
+ }
+
+ protected void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (!(paramSpec instanceof PBEParameterSpec)) {
+ throw new InvalidParameterSpecException
+ ("Inappropriate parameter specification");
+ }
+ this.salt = ((PBEParameterSpec)paramSpec).getSalt().clone();
+ this.iCount = ((PBEParameterSpec)paramSpec).getIterationCount();
+ this.cipherParam = ((PBEParameterSpec)paramSpec).getParameterSpec();
+ }
+
+ protected void engineInit(byte[] encoded)
+ throws IOException
+ {
+ String kdfAlgo = null;
+ String cipherAlgo = null;
+
+ DerValue pBES2Algorithms = new DerValue(encoded);
+ if (pBES2Algorithms.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+ if (!pkcs5PBES2_OID.equals(pBES2Algorithms.data.getOID())) {
+ throw new IOException("PBE parameter parsing error: "
+ + "expecting the object identifier for PBES2");
+ }
+ if (pBES2Algorithms.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+
+ DerValue pBES2_params = pBES2Algorithms.data.getDerValue();
+ if (pBES2_params.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+ kdfAlgo = parseKDF(pBES2_params.data.getDerValue());
+
+ if (pBES2_params.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+ cipherAlgo = parseES(pBES2_params.data.getDerValue());
+
+ pbes2AlgorithmName = new StringBuilder().append("PBEWith")
+ .append(kdfAlgo).append("And").append(cipherAlgo).toString();
+ }
+
+ private String parseKDF(DerValue keyDerivationFunc) throws IOException {
+ String kdfAlgo = null;
+
+ if (!pkcs5PBKDF2_OID.equals(keyDerivationFunc.data.getOID())) {
+ throw new IOException("PBE parameter parsing error: "
+ + "expecting the object identifier for PBKDF2");
+ }
+ if (keyDerivationFunc.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+ DerValue pBKDF2_params = keyDerivationFunc.data.getDerValue();
+ if (pBKDF2_params.tag != DerValue.tag_Sequence) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 SEQUENCE tag");
+ }
+ DerValue specified = pBKDF2_params.data.getDerValue();
+ // the 'specified' ASN.1 CHOICE for 'salt' is supported
+ if (specified.tag == DerValue.tag_OctetString) {
+ salt = specified.getOctetString();
+ } else {
+ // the 'otherSource' ASN.1 CHOICE for 'salt' is not supported
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 OCTET STRING tag");
+ }
+ iCount = pBKDF2_params.data.getInteger();
+ DerValue keyLength = pBKDF2_params.data.getDerValue();
+ if (keyLength.tag == DerValue.tag_Integer) {
+ keysize = keyLength.getInteger() * 8; // keysize (in bits)
+ }
+ if (pBKDF2_params.tag == DerValue.tag_Sequence) {
+ DerValue prf = pBKDF2_params.data.getDerValue();
+ kdfAlgo_OID = prf.data.getOID();
+ if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) {
+ kdfAlgo = "HmacSHA1";
+ } else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) {
+ kdfAlgo = "HmacSHA224";
+ } else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) {
+ kdfAlgo = "HmacSHA256";
+ } else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) {
+ kdfAlgo = "HmacSHA384";
+ } else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) {
+ kdfAlgo = "HmacSHA512";
+ } else {
+ throw new IOException("PBE parameter parsing error: "
+ + "expecting the object identifier for a HmacSHA key "
+ + "derivation function");
+ }
+ if (prf.data.available() != 0) {
+ // parameter is 'NULL' for all HmacSHA KDFs
+ DerValue parameter = prf.data.getDerValue();
+ if (parameter.tag != DerValue.tag_Null) {
+ throw new IOException("PBE parameter parsing error: "
+ + "not an ASN.1 NULL tag");
+ }
+ }
+ }
+
+ return kdfAlgo;
+ }
+
+ private String parseES(DerValue encryptionScheme) throws IOException {
+ String cipherAlgo = null;
+
+ cipherAlgo_OID = encryptionScheme.data.getOID();
+ if (aes128CBC_OID.equals(cipherAlgo_OID)) {
+ cipherAlgo = "AES_128";
+ // parameter is AES-IV 'OCTET STRING (SIZE(16))'
+ cipherParam =
+ new IvParameterSpec(encryptionScheme.data.getOctetString());
+ keysize = 128;
+ } else if (aes256CBC_OID.equals(cipherAlgo_OID)) {
+ cipherAlgo = "AES_256";
+ // parameter is AES-IV 'OCTET STRING (SIZE(16))'
+ cipherParam =
+ new IvParameterSpec(encryptionScheme.data.getOctetString());
+ keysize = 256;
+ } else {
+ throw new IOException("PBE parameter parsing error: "
+ + "expecting the object identifier for AES cipher");
+ }
+
+ return cipherAlgo;
+ }
+
+ protected void engineInit(byte[] encoded, String decodingMethod)
+ throws IOException
+ {
+ engineInit(encoded);
+ }
+
+ protected <T extends AlgorithmParameterSpec>
+ T engineGetParameterSpec(Class<T> paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) {
+ return paramSpec.cast(
+ new PBEParameterSpec(this.salt, this.iCount, this.cipherParam));
+ } else {
+ throw new InvalidParameterSpecException
+ ("Inappropriate parameter specification");
+ }
+ }
+
+ protected byte[] engineGetEncoded() throws IOException {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream pBES2Algorithms = new DerOutputStream();
+ pBES2Algorithms.putOID(pkcs5PBES2_OID);
+
+ DerOutputStream pBES2_params = new DerOutputStream();
+
+ DerOutputStream keyDerivationFunc = new DerOutputStream();
+ keyDerivationFunc.putOID(pkcs5PBKDF2_OID);
+
+ DerOutputStream pBKDF2_params = new DerOutputStream();
+ pBKDF2_params.putOctetString(salt); // choice: 'specified OCTET STRING'
+ pBKDF2_params.putInteger(iCount);
+ pBKDF2_params.putInteger(keysize / 8); // derived key length (in octets)
+
+ DerOutputStream prf = new DerOutputStream();
+ // algorithm is id-hmacWithSHA1/SHA224/SHA256/SHA384/SHA512
+ prf.putOID(kdfAlgo_OID);
+ // parameters is 'NULL'
+ prf.putNull();
+ pBKDF2_params.write(DerValue.tag_Sequence, prf);
+
+ keyDerivationFunc.write(DerValue.tag_Sequence, pBKDF2_params);
+ pBES2_params.write(DerValue.tag_Sequence, keyDerivationFunc);
+
+ DerOutputStream encryptionScheme = new DerOutputStream();
+ // algorithm is id-aes128-CBC or id-aes256-CBC
+ encryptionScheme.putOID(cipherAlgo_OID);
+ // parameters is 'AES-IV ::= OCTET STRING (SIZE(16))'
+ if (cipherParam != null && cipherParam instanceof IvParameterSpec) {
+ encryptionScheme.putOctetString(
+ ((IvParameterSpec)cipherParam).getIV());
+ } else {
+ throw new IOException("Wrong parameter type: IV expected");
+ }
+ pBES2_params.write(DerValue.tag_Sequence, encryptionScheme);
+
+ pBES2Algorithms.write(DerValue.tag_Sequence, pBES2_params);
+ out.write(DerValue.tag_Sequence, pBES2Algorithms);
+
+ return out.toByteArray();
+ }
+
+ protected byte[] engineGetEncoded(String encodingMethod)
+ throws IOException
+ {
+ return engineGetEncoded();
+ }
+
+ /*
+ * Returns a formatted string describing the parameters.
+ *
+ * The algorithn name pattern is: "PBEWith<prf>And<encryption>"
+ * where <prf> is one of: HmacSHA1, HmacSHA224, HmacSHA256, HmacSHA384,
+ * or HmacSHA512, and <encryption> is AES with a keysize suffix.
+ */
+ protected String engineToString() {
+ return pbes2AlgorithmName;
+ }
+
+ public static final class General extends PBES2Parameters {
+ public General() throws NoSuchAlgorithmException {
+ super();
+ }
+ }
+
+ public static final class HmacSHA1AndAES_128 extends PBES2Parameters {
+ public HmacSHA1AndAES_128() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA1AndAES_128");
+ }
+ }
+
+ public static final class HmacSHA224AndAES_128 extends PBES2Parameters {
+ public HmacSHA224AndAES_128() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA224AndAES_128");
+ }
+ }
+
+ public static final class HmacSHA256AndAES_128 extends PBES2Parameters {
+ public HmacSHA256AndAES_128() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA256AndAES_128");
+ }
+ }
+
+ public static final class HmacSHA384AndAES_128 extends PBES2Parameters {
+ public HmacSHA384AndAES_128() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA384AndAES_128");
+ }
+ }
+
+ public static final class HmacSHA512AndAES_128 extends PBES2Parameters {
+ public HmacSHA512AndAES_128() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA512AndAES_128");
+ }
+ }
+
+ public static final class HmacSHA1AndAES_256 extends PBES2Parameters {
+ public HmacSHA1AndAES_256() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA1AndAES_256");
+ }
+ }
+
+ public static final class HmacSHA224AndAES_256 extends PBES2Parameters {
+ public HmacSHA224AndAES_256() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA224AndAES_256");
+ }
+ }
+
+ public static final class HmacSHA256AndAES_256 extends PBES2Parameters {
+ public HmacSHA256AndAES_256() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA256AndAES_256");
+ }
+ }
+
+ public static final class HmacSHA384AndAES_256 extends PBES2Parameters {
+ public HmacSHA384AndAES_256() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA384AndAES_256");
+ }
+ }
+
+ public static final class HmacSHA512AndAES_256 extends PBES2Parameters {
+ public HmacSHA512AndAES_256() throws NoSuchAlgorithmException {
+ super("PBEWithHmacSHA512AndAES_256");
+ }
+ }
+}
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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
@@ -45,7 +45,7 @@
public final class PBEWithMD5AndDESCipher extends CipherSpi {
// the encapsulated DES cipher
- private PBECipherCore core;
+ private PBES1Core core;
/**
* Creates an instance of this cipher, and initializes its mode (CBC) and
@@ -58,7 +58,7 @@
*/
public PBEWithMD5AndDESCipher()
throws NoSuchAlgorithmException, NoSuchPaddingException {
- core = new PBECipherCore("DES");
+ core = new PBES1Core("DES");
}
/**
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. 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,7 +55,7 @@
*/
public final class PBEWithMD5AndTripleDESCipher extends CipherSpi {
- private PBECipherCore core;
+ private PBES1Core core;
/**
* Creates an instance of this cipher, and initializes its mode (CBC) and
@@ -70,7 +70,7 @@
throws NoSuchAlgorithmException, NoSuchPaddingException
{
// set the encapsulated cipher to do triple DES
- core = new PBECipherCore("DESede");
+ core = new PBES1Core("DESede");
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2Core.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.security.InvalidKeyException;
+import java.security.spec.KeySpec;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * This class implements a key factory for PBE keys derived using
+ * PBKDF2 with HmacSHA1/HmacSHA224/HmacSHA256/HmacSHA384/HmacSHA512
+ * pseudo random function (PRF) as defined in PKCS#5 v2.1.
+ *
+ * @author Valerie Peng
+ *
+ */
+abstract class PBKDF2Core extends SecretKeyFactorySpi {
+
+ private final String prfAlgo;
+
+ PBKDF2Core(String prfAlgo) {
+ this.prfAlgo = prfAlgo;
+ }
+
+ /**
+ * Generates a <code>SecretKey</code> object from the provided key
+ * specification (key material).
+ *
+ * @param keySpec the specification (key material) of the secret key
+ *
+ * @return the secret key
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this key factory to produce a public key.
+ */
+ protected SecretKey engineGenerateSecret(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (!(keySpec instanceof PBEKeySpec)) {
+ throw new InvalidKeySpecException("Invalid key spec");
+ }
+ PBEKeySpec ks = (PBEKeySpec) keySpec;
+ return new PBKDF2KeyImpl(ks, prfAlgo);
+ }
+
+ /**
+ * Returns a specification (key material) of the given key
+ * in the requested format.
+ *
+ * @param key the key
+ *
+ * @param keySpec the requested format in which the key material shall be
+ * returned
+ *
+ * @return the underlying key specification (key material) in the
+ * requested format
+ *
+ * @exception InvalidKeySpecException if the requested key
+ * specification is inappropriate for the given key, or the
+ * given key cannot be processed (e.g., the given key has an
+ * unrecognized algorithm or format).
+ */
+ protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl)
+ throws InvalidKeySpecException {
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ // Check if requested key spec is amongst the valid ones
+ if ((keySpecCl != null)
+ && PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
+ javax.crypto.interfaces.PBEKey pKey =
+ (javax.crypto.interfaces.PBEKey) key;
+ return new PBEKeySpec
+ (pKey.getPassword(), pKey.getSalt(),
+ pKey.getIterationCount(), pKey.getEncoded().length*8);
+ } else {
+ throw new InvalidKeySpecException("Invalid key spec");
+ }
+ } else {
+ throw new InvalidKeySpecException("Invalid key " +
+ "format/algorithm");
+ }
+ }
+
+ /**
+ * Translates a <code>SecretKey</code> object, whose provider may be
+ * unknown or potentially untrusted, into a corresponding
+ * <code>SecretKey</code> object of this key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted
+ *
+ * @return the translated key
+ *
+ * @exception InvalidKeyException if the given key cannot be processed by
+ * this key factory.
+ */
+ protected SecretKey engineTranslateKey(SecretKey key)
+ throws InvalidKeyException {
+ if ((key != null) &&
+ (key.getAlgorithm().equalsIgnoreCase("PBKDF2With" + prfAlgo)) &&
+ (key.getFormat().equalsIgnoreCase("RAW"))) {
+
+ // Check if key originates from this factory
+ if (key instanceof com.sun.crypto.provider.PBKDF2KeyImpl) {
+ return key;
+ }
+ // Check if key implements the PBEKey
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ javax.crypto.interfaces.PBEKey pKey =
+ (javax.crypto.interfaces.PBEKey) key;
+ try {
+ PBEKeySpec spec =
+ new PBEKeySpec(pKey.getPassword(),
+ pKey.getSalt(),
+ pKey.getIterationCount(),
+ pKey.getEncoded().length*8);
+ return new PBKDF2KeyImpl(spec, prfAlgo);
+ } catch (InvalidKeySpecException re) {
+ InvalidKeyException ike = new InvalidKeyException
+ ("Invalid key component(s)");
+ ike.initCause(re);
+ throw ike;
+ }
+ }
+ }
+ throw new InvalidKeyException("Invalid key format/algorithm");
+ }
+
+ public static final class HmacSHA1 extends PBKDF2Core {
+ public HmacSHA1() {
+ super("HmacSHA1");
+ }
+ }
+
+ public static final class HmacSHA224 extends PBKDF2Core {
+ public HmacSHA224() {
+ super("HmacSHA224");
+ }
+ }
+
+ public static final class HmacSHA256 extends PBKDF2Core {
+ public HmacSHA256() {
+ super("HmacSHA256");
+ }
+ }
+
+ public static final class HmacSHA384 extends PBKDF2Core {
+ public HmacSHA384() {
+ super("HmacSHA384");
+ }
+ }
+
+ public static final class HmacSHA512 extends PBKDF2Core {
+ public HmacSHA512() {
+ super("HmacSHA512");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.util.Arrays;
+import java.nio.ByteBuffer;
+
+import javax.crypto.MacSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * This is an implementation of the PBMAC1 algorithms as defined
+ * in PKCS#5 v2.1 standard.
+ */
+abstract class PBMAC1Core extends HmacCore {
+
+ private static final int DEFAULT_SALT_LENGTH = 20;
+ private static final int DEFAULT_COUNT = 4096;
+
+ private final String kdfAlgo;
+ private final String hashAlgo;
+ private final PBKDF2Core kdf;
+ private final int blockLength; // in octets
+
+ /**
+ * Creates an instance of PBMAC1 according to the selected
+ * password-based key derivation function.
+ */
+ PBMAC1Core(String kdfAlgo, String hashAlgo, int blockLength)
+ throws NoSuchAlgorithmException {
+
+ super(hashAlgo, blockLength);
+ this.kdfAlgo = kdfAlgo;
+ this.hashAlgo = hashAlgo;
+ this.blockLength = blockLength;
+
+ switch(kdfAlgo) {
+ case "HmacSHA1":
+ kdf = new PBKDF2Core.HmacSHA1();
+ break;
+ case "HmacSHA224":
+ kdf = new PBKDF2Core.HmacSHA224();
+ break;
+ case "HmacSHA256":
+ kdf = new PBKDF2Core.HmacSHA256();
+ break;
+ case "HmacSHA384":
+ kdf = new PBKDF2Core.HmacSHA384();
+ break;
+ case "HmacSHA512":
+ kdf = new PBKDF2Core.HmacSHA512();
+ break;
+ default:
+ throw new NoSuchAlgorithmException(
+ "No MAC implementation for " + kdfAlgo);
+ }
+ }
+
+ /**
+ * Initializes the HMAC with the given secret key and algorithm parameters.
+ *
+ * @param key the secret key.
+ * @param params the algorithm parameters.
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this MAC.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this MAC.
+ */
+ protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ char[] passwdChars;
+ byte[] salt = null;
+ int iCount = 0;
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ javax.crypto.interfaces.PBEKey pbeKey =
+ (javax.crypto.interfaces.PBEKey) key;
+ passwdChars = pbeKey.getPassword();
+ salt = pbeKey.getSalt(); // maybe null if unspecified
+ iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
+ } else if (key instanceof SecretKey) {
+ byte[] passwdBytes = key.getEncoded();
+ if ((passwdBytes == null) ||
+ !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
+ }
+ passwdChars = new char[passwdBytes.length];
+ for (int i=0; i<passwdChars.length; i++) {
+ passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
+ }
+ } else {
+ throw new InvalidKeyException("SecretKey of PBE type required");
+ }
+ if (params == null) {
+ // generate default for salt and iteration count if necessary
+ if (salt == null) {
+ salt = new byte[DEFAULT_SALT_LENGTH];
+ SunJCE.RANDOM.nextBytes(salt);
+ }
+ if (iCount == 0) iCount = DEFAULT_COUNT;
+ } else if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec type required");
+ } else {
+ PBEParameterSpec pbeParams = (PBEParameterSpec) params;
+ // make sure the parameter values are consistent
+ if (salt != null) {
+ if (!Arrays.equals(salt, pbeParams.getSalt())) {
+ throw new InvalidAlgorithmParameterException
+ ("Inconsistent value of salt between key and params");
+ }
+ } else {
+ salt = pbeParams.getSalt();
+ }
+ if (iCount != 0) {
+ if (iCount != pbeParams.getIterationCount()) {
+ throw new InvalidAlgorithmParameterException
+ ("Different iteration count between key and params");
+ }
+ } else {
+ iCount = pbeParams.getIterationCount();
+ }
+ }
+ // For security purpose, we need to enforce a minimum length
+ // for salt; just require the minimum salt length to be 8-byte
+ // which is what PKCS#5 recommends and openssl does.
+ if (salt.length < 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be at least 8 bytes long");
+ }
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
+
+ PBEKeySpec pbeSpec =
+ new PBEKeySpec(passwdChars, salt, iCount, blockLength);
+ // password char[] was cloned in PBEKeySpec constructor,
+ // so we can zero it out here
+ java.util.Arrays.fill(passwdChars, ' ');
+
+ SecretKey s = null;
+
+ try {
+ s = kdf.engineGenerateSecret(pbeSpec);
+
+ } catch (InvalidKeySpecException ikse) {
+ InvalidKeyException ike =
+ new InvalidKeyException("Cannot construct PBE key");
+ ike.initCause(ikse);
+ throw ike;
+ }
+ byte[] derivedKey = s.getEncoded();
+ SecretKey cipherKey = new SecretKeySpec(derivedKey, kdfAlgo);
+
+ super.engineInit(cipherKey, null);
+ }
+
+ public static final class HmacSHA1 extends PBMAC1Core {
+ public HmacSHA1() throws NoSuchAlgorithmException {
+ super("HmacSHA1", "SHA1", 64);
+ }
+ }
+
+ public static final class HmacSHA224 extends PBMAC1Core {
+ public HmacSHA224() throws NoSuchAlgorithmException {
+ super("HmacSHA224", "SHA-224", 64);
+ }
+ }
+
+ public static final class HmacSHA256 extends PBMAC1Core {
+ public HmacSHA256() throws NoSuchAlgorithmException {
+ super("HmacSHA256", "SHA-256", 64);
+ }
+ }
+
+ public static final class HmacSHA384 extends PBMAC1Core {
+ public HmacSHA384() throws NoSuchAlgorithmException {
+ super("HmacSHA384", "SHA-384", 128);
+ }
+ }
+
+ public static final class HmacSHA512 extends PBMAC1Core {
+ public HmacSHA512() throws NoSuchAlgorithmException {
+ super("HmacSHA512", "SHA-512", 128);
+ }
+ }
+}
--- a/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Thu Nov 15 00:54:54 2012 +0000
@@ -35,19 +35,24 @@
/**
* This class implements password-base encryption algorithm with
- * SHA1 digest and the following Ciphers in CBC mode
+ * SHA1 digest and the following Ciphers (in CBC mode, where applicable):
* - DESede cipher and
- * - RC2 Cipher with 40-bit effective key length
+ * - RC2 Cipher with 40-bit or 128-bit effective key length and
+ * - RC4 Cipher with 40-bit or 128-bit effective key length
* as defined by PKCS #12 version 1.0 standard.
*
* @author Valerie Peng
* @see javax.crypto.CipherSpi
*/
final class PKCS12PBECipherCore {
+
+ // TBD: replace CipherCore with a CipherSpi object to simplify maintenance
+
private CipherCore cipher;
private int blockSize;
private int keySize;
private String algo = null;
+ private String pbeAlgo = null;
private byte[] salt = null;
private int iCount = 0;
@@ -58,8 +63,16 @@
static final int CIPHER_IV = 2;
static final int MAC_KEY = 3;
+ // Uses default hash algorithm (SHA-1)
static byte[] derive(char[] chars, byte[] salt,
int ic, int n, int type) {
+ return derive(chars, salt, ic, n, type, "SHA-1", 64);
+ }
+
+ // Uses supplied hash algorithm
+ static byte[] derive(char[] chars, byte[] salt, int ic, int n, int type,
+ String hashAlgo, int blockLength) {
+
// Add in trailing NULL terminator. Special case:
// no terminator if password is "\0".
int length = chars.length*2;
@@ -75,21 +88,23 @@
passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF);
passwd[j+1] = (byte) (chars[i] & 0xFF);
}
- int v = 512 / 8;
- int u = 160 / 8;
- int c = roundup(n, u) / u;
- byte[] D = new byte[v];
- int s = roundup(salt.length, v);
- int p = roundup(passwd.length, v);
- byte[] I = new byte[s + p];
byte[] key = new byte[n];
- Arrays.fill(D, (byte)type);
- concat(salt, I, 0, s);
- concat(passwd, I, s, p);
+ try {
+ MessageDigest sha = MessageDigest.getInstance(hashAlgo);
- try {
- MessageDigest sha = MessageDigest.getInstance("SHA1");
+ int v = blockLength;
+ int u = sha.getDigestLength();
+ int c = roundup(n, u) / u;
+ byte[] D = new byte[v];
+ int s = roundup(salt.length, v);
+ int p = roundup(passwd.length, v);
+ byte[] I = new byte[s + p];
+
+ Arrays.fill(D, (byte)type);
+ concat(salt, I, 0, s);
+ concat(passwd, I, s, p);
+
byte[] Ai;
byte[] B = new byte[v];
byte[] tmp = new byte[v];
@@ -150,23 +165,30 @@
PKCS12PBECipherCore(String symmCipherAlg, int defKeySize)
throws NoSuchAlgorithmException {
+
algo = symmCipherAlg;
- SymmetricCipher symmCipher = null;
- if (algo.equals("DESede")) {
- symmCipher = new DESedeCrypt();
- } else if (algo.equals("RC2")) {
- symmCipher = new RC2Crypt();
+ if (algo.equals("RC4")) {
+ pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8;
} else {
- throw new NoSuchAlgorithmException("No Cipher implementation " +
+ SymmetricCipher symmCipher = null;
+ if (algo.equals("DESede")) {
+ symmCipher = new DESedeCrypt();
+ pbeAlgo = "PBEWithSHA1AndDESede";
+ } else if (algo.equals("RC2")) {
+ symmCipher = new RC2Crypt();
+ pbeAlgo = "PBEWithSHA1AndRC2_" + defKeySize * 8;
+ } else {
+ throw new NoSuchAlgorithmException("No Cipher implementation " +
"for PBEWithSHA1And" + algo);
- }
- blockSize = symmCipher.getBlockSize();
- cipher = new CipherCore(symmCipher, blockSize);
- cipher.setMode("CBC");
- try {
- cipher.setPadding("PKCS5Padding");
- } catch (NoSuchPaddingException nspe) {
- // should not happen
+ }
+ blockSize = symmCipher.getBlockSize();
+ cipher = new CipherCore(symmCipher, blockSize);
+ cipher.setMode("CBC");
+ try {
+ cipher.setPadding("PKCS5Padding");
+ } catch (NoSuchPaddingException nspe) {
+ // should not happen
+ }
}
keySize = defKeySize;
}
@@ -210,8 +232,7 @@
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
try {
- params = AlgorithmParameters.getInstance("PBEWithSHA1And" +
- (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
+ params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE");
} catch (GeneralSecurityException gse) {
// should never happen
throw new RuntimeException(
@@ -229,6 +250,13 @@
void implInit(int opmode, Key key, AlgorithmParameterSpec params,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
+ implInit(opmode, key, params, random, null);
+ }
+
+ void implInit(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random, CipherSpi cipherImpl)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
char[] passwdChars = null;
salt = null;
iCount = 0;
@@ -309,17 +337,29 @@
byte[] derivedKey = derive(passwdChars, salt, iCount,
keySize, CIPHER_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
- byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
+
+ if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
+ ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
+
+ } else {
+ byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
CIPHER_IV);
- IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
+ IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
- // initialize the underlying cipher
- cipher.init(opmode, cipherKey, ivSpec, random);
+ // initialize the underlying cipher
+ cipher.init(opmode, cipherKey, ivSpec, random);
+ }
}
void implInit(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
+ implInit(opmode, key, params, random, null);
+ }
+
+ void implInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random, CipherSpi cipherImpl)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
AlgorithmParameterSpec paramSpec = null;
if (params != null) {
try {
@@ -329,13 +369,19 @@
"requires PBE parameters");
}
}
- implInit(opmode, key, paramSpec, random);
+ implInit(opmode, key, paramSpec, random, cipherImpl);
}
void implInit(int opmode, Key key, SecureRandom random)
throws InvalidKeyException {
+ implInit(opmode, key, random, null);
+ }
+
+ void implInit(int opmode, Key key, SecureRandom random,
+ CipherSpi cipherImpl) throws InvalidKeyException {
try {
- implInit(opmode, key, (AlgorithmParameterSpec) null, random);
+ implInit(opmode, key, (AlgorithmParameterSpec) null, random,
+ cipherImpl);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException("requires PBE parameters");
}
@@ -526,4 +572,245 @@
return core.implWrap(key);
}
}
+
+ public static final class PBEWithSHA1AndRC2_128 extends CipherSpi {
+ private final PKCS12PBECipherCore core;
+ public PBEWithSHA1AndRC2_128() throws NoSuchAlgorithmException {
+ core = new PKCS12PBECipherCore("RC2", 16);
+ }
+ protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return core.implDoFinal(in, inOff, inLen);
+ }
+ protected int engineDoFinal(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return core.implDoFinal(in, inOff, inLen, out, outOff);
+ }
+ protected int engineGetBlockSize() {
+ return core.implGetBlockSize();
+ }
+ protected byte[] engineGetIV() {
+ return core.implGetIV();
+ }
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return core.implGetKeySize(key);
+ }
+ protected int engineGetOutputSize(int inLen) {
+ return core.implGetOutputSize(inLen);
+ }
+ protected AlgorithmParameters engineGetParameters() {
+ return core.implGetParameters();
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random);
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random);
+ }
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ core.implInit(opmode, key, random);
+ }
+ protected void engineSetMode(String mode)
+ throws NoSuchAlgorithmException {
+ core.implSetMode(mode);
+ }
+ protected void engineSetPadding(String paddingScheme)
+ throws NoSuchPaddingException {
+ core.implSetPadding(paddingScheme);
+ }
+ protected Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+ protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
+ return core.implUpdate(in, inOff, inLen);
+ }
+ protected int engineUpdate(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException {
+ return core.implUpdate(in, inOff, inLen, out, outOff);
+ }
+ protected byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ return core.implWrap(key);
+ }
+ }
+
+ public static final class PBEWithSHA1AndRC4_40 extends CipherSpi {
+ private static final int RC4_KEYSIZE = 5;
+ private final PKCS12PBECipherCore core;
+ private final ARCFOURCipher cipher;
+
+ public PBEWithSHA1AndRC4_40() throws NoSuchAlgorithmException {
+ core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
+ cipher = new ARCFOURCipher();
+ }
+ protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return cipher.engineDoFinal(in, inOff, inLen);
+ }
+ protected int engineDoFinal(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
+ }
+ protected int engineGetBlockSize() {
+ return cipher.engineGetBlockSize();
+ }
+ protected byte[] engineGetIV() {
+ return cipher.engineGetIV();
+ }
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return RC4_KEYSIZE;
+ }
+ protected int engineGetOutputSize(int inLen) {
+ return cipher.engineGetOutputSize(inLen);
+ }
+ protected AlgorithmParameters engineGetParameters() {
+ return core.implGetParameters();
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random, cipher);
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random, cipher);
+ }
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ core.implInit(opmode, key, random, cipher);
+ }
+ protected void engineSetMode(String mode)
+ throws NoSuchAlgorithmException {
+ if (mode.equalsIgnoreCase("ECB") == false) {
+ throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+ }
+ }
+ protected void engineSetPadding(String paddingScheme)
+ throws NoSuchPaddingException {
+ if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
+ throw new NoSuchPaddingException("Padding must be NoPadding");
+ }
+ }
+ protected Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+ protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
+ return cipher.engineUpdate(in, inOff, inLen);
+ }
+ protected int engineUpdate(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException {
+ return cipher.engineUpdate(in, inOff, inLen, out, outOff);
+ }
+ protected byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ return cipher.engineWrap(key);
+ }
+ }
+
+ public static final class PBEWithSHA1AndRC4_128 extends CipherSpi {
+ private static final int RC4_KEYSIZE = 16;
+ private final PKCS12PBECipherCore core;
+ private final ARCFOURCipher cipher;
+
+ public PBEWithSHA1AndRC4_128() throws NoSuchAlgorithmException {
+ core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
+ cipher = new ARCFOURCipher();
+ }
+ protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return cipher.engineDoFinal(in, inOff, inLen);
+ }
+ protected int engineDoFinal(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
+ }
+ protected int engineGetBlockSize() {
+ return cipher.engineGetBlockSize();
+ }
+ protected byte[] engineGetIV() {
+ return cipher.engineGetIV();
+ }
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return RC4_KEYSIZE;
+ }
+ protected int engineGetOutputSize(int inLen) {
+ return cipher.engineGetOutputSize(inLen);
+ }
+ protected AlgorithmParameters engineGetParameters() {
+ return core.implGetParameters();
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random, cipher);
+ }
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ core.implInit(opmode, key, params, random, cipher);
+ }
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ core.implInit(opmode, key, random, cipher);
+ }
+ protected void engineSetMode(String mode)
+ throws NoSuchAlgorithmException {
+ if (mode.equalsIgnoreCase("ECB") == false) {
+ throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+ }
+ }
+ protected void engineSetPadding(String paddingScheme)
+ throws NoSuchPaddingException {
+ if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
+ throw new NoSuchPaddingException("Padding must be NoPadding");
+ }
+ }
+ protected Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+ protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
+ return cipher.engineUpdate(in, inOff, inLen);
+ }
+ protected int engineUpdate(byte[] in, int inOff, int inLen,
+ byte[] out, int outOff)
+ throws ShortBufferException {
+ return cipher.engineUpdate(in, inOff, inLen, out, outOff);
+ }
+ protected byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ return cipher.engineWrap(key);
+ }
+ }
}
--- a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java Thu Nov 15 00:54:54 2012 +0000
@@ -77,10 +77,14 @@
"(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, "
+ "Diffie-Hellman, HMAC)";
+ private static final String OID_PKCS12_RC4_128 = "1.2.840.113549.1.12.1.1";
+ private static final String OID_PKCS12_RC4_40 = "1.2.840.113549.1.12.1.2";
+ private static final String OID_PKCS12_DESede = "1.2.840.113549.1.12.1.3";
+ private static final String OID_PKCS12_RC2_128 = "1.2.840.113549.1.12.1.5";
private static final String OID_PKCS12_RC2_40 = "1.2.840.113549.1.12.1.6";
- private static final String OID_PKCS12_DESede = "1.2.840.113549.1.12.1.3";
private static final String OID_PKCS5_MD5_DES = "1.2.840.113549.1.5.3";
private static final String OID_PKCS5_PBKDF2 = "1.2.840.113549.1.5.12";
+ private static final String OID_PKCS5_PBES2 = "1.2.840.113549.1.5.13";
private static final String OID_PKCS3 = "1.2.840.113549.1.3.1";
/* Are we debugging? -- for developers */
@@ -138,14 +142,26 @@
put("Cipher.DESedeWrap SupportedPaddings", "NOPADDING");
put("Cipher.DESedeWrap SupportedKeyFormats", "RAW");
+ // PBES1
+
put("Cipher.PBEWithMD5AndDES",
"com.sun.crypto.provider.PBEWithMD5AndDESCipher");
put("Alg.Alias.Cipher.OID."+OID_PKCS5_MD5_DES,
"PBEWithMD5AndDES");
put("Alg.Alias.Cipher."+OID_PKCS5_MD5_DES,
"PBEWithMD5AndDES");
+
put("Cipher.PBEWithMD5AndTripleDES",
"com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher");
+
+ put("Cipher.PBEWithSHA1AndDESede",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$" +
+ "PBEWithSHA1AndDESede");
+ put("Alg.Alias.Cipher.OID." + OID_PKCS12_DESede,
+ "PBEWithSHA1AndDESede");
+ put("Alg.Alias.Cipher." + OID_PKCS12_DESede,
+ "PBEWithSHA1AndDESede");
+
put("Cipher.PBEWithSHA1AndRC2_40",
"com.sun.crypto.provider.PKCS12PBECipherCore$" +
"PBEWithSHA1AndRC2_40");
@@ -153,13 +169,70 @@
"PBEWithSHA1AndRC2_40");
put("Alg.Alias.Cipher." + OID_PKCS12_RC2_40,
"PBEWithSHA1AndRC2_40");
- put("Cipher.PBEWithSHA1AndDESede",
+
+ put("Cipher.PBEWithSHA1AndRC2_128",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$" +
+ "PBEWithSHA1AndRC2_128");
+ put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+ put("Alg.Alias.Cipher." + OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+
+ put("Cipher.PBEWithSHA1AndRC4_40",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$" +
+ "PBEWithSHA1AndRC4_40");
+ put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+ put("Alg.Alias.Cipher." + OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+
+ put("Cipher.PBEWithSHA1AndRC4_128",
"com.sun.crypto.provider.PKCS12PBECipherCore$" +
- "PBEWithSHA1AndDESede");
- put("Alg.Alias.Cipher.OID." + OID_PKCS12_DESede,
- "PBEWithSHA1AndDESede");
- put("Alg.Alias.Cipher." + OID_PKCS12_DESede,
- "PBEWithSHA1AndDESede");
+ "PBEWithSHA1AndRC4_128");
+ put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+ put("Alg.Alias.Cipher." + OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+
+ //PBES2
+
+ put("Cipher.PBEWithHmacSHA1AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128");
+
+ put("Cipher.PBEWithHmacSHA224AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA224AndAES_128");
+
+ put("Cipher.PBEWithHmacSHA256AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA256AndAES_128");
+
+ put("Cipher.PBEWithHmacSHA384AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA384AndAES_128");
+
+ put("Cipher.PBEWithHmacSHA512AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA512AndAES_128");
+
+ put("Cipher.PBEWithHmacSHA1AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256");
+
+ put("Cipher.PBEWithHmacSHA224AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA224AndAES_256");
+
+ put("Cipher.PBEWithHmacSHA256AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA256AndAES_256");
+
+ put("Cipher.PBEWithHmacSHA384AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA384AndAES_256");
+
+ put("Cipher.PBEWithHmacSHA512AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$" +
+ "HmacSHA512AndAES_256");
put("Cipher.Blowfish",
"com.sun.crypto.provider.BlowfishCipher");
@@ -301,6 +374,7 @@
"DiffieHellman");
put("Alg.Alias.KeyPairGenerator."+OID_PKCS3,
"DiffieHellman");
+
/*
* Algorithm parameter generation engines
*/
@@ -371,6 +445,64 @@
put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_40,
"PBEWithSHA1AndRC2_40");
+ put("AlgorithmParameters.PBEWithSHA1AndRC2_128",
+ "com.sun.crypto.provider.PBEParameters");
+ put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+ put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+
+ put("AlgorithmParameters.PBEWithSHA1AndRC4_40",
+ "com.sun.crypto.provider.PBEParameters");
+ put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+ put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+
+ put("AlgorithmParameters.PBEWithSHA1AndRC4_128",
+ "com.sun.crypto.provider.PBEParameters");
+ put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+ put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+
+ put("AlgorithmParameters.PBES2",
+ "com.sun.crypto.provider.PBES2Parameters$General");
+ put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_PBES2,
+ "PBES2");
+ put("Alg.Alias.AlgorithmParameters." + OID_PKCS5_PBES2,
+ "PBES2");
+
+ put("AlgorithmParameters.PBEWithHmacSHA1AndAES_128",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128");
+
+ put("AlgorithmParameters.PBEWithHmacSHA224AndAES_128",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128");
+
+ put("AlgorithmParameters.PBEWithHmacSHA256AndAES_128",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128");
+
+ put("AlgorithmParameters.PBEWithHmacSHA384AndAES_128",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128");
+
+ put("AlgorithmParameters.PBEWithHmacSHA512AndAES_128",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128");
+
+ put("AlgorithmParameters.PBEWithHmacSHA1AndAES_256",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256");
+
+ put("AlgorithmParameters.PBEWithHmacSHA224AndAES_256",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256");
+
+ put("AlgorithmParameters.PBEWithHmacSHA256AndAES_256",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256");
+
+ put("AlgorithmParameters.PBEWithHmacSHA384AndAES_256",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256");
+
+ put("AlgorithmParameters.PBEWithHmacSHA512AndAES_256",
+ "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256");
+
put("AlgorithmParameters.Blowfish",
"com.sun.crypto.provider.BlowfishParameters");
@@ -378,6 +510,7 @@
"com.sun.crypto.provider.AESParameters");
put("Alg.Alias.AlgorithmParameters.Rijndael", "AES");
+
put("AlgorithmParameters.RC2",
"com.sun.crypto.provider.RC2Parameters");
@@ -393,6 +526,7 @@
put("Alg.Alias.KeyFactory.OID."+OID_PKCS3,
"DiffieHellman");
put("Alg.Alias.KeyFactory."+OID_PKCS3, "DiffieHellman");
+
/*
* Secret-key factories
*/
@@ -441,13 +575,90 @@
put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC2_40,
"PBEWithSHA1AndRC2_40");
+ put("SecretKeyFactory.PBEWithSHA1AndRC2_128",
+ "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_128"
+ );
+ put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+ put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC2_128,
+ "PBEWithSHA1AndRC2_128");
+
+ put("SecretKeyFactory.PBEWithSHA1AndRC4_40",
+ "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_40"
+ );
+
+ put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+ put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC4_40,
+ "PBEWithSHA1AndRC4_40");
+
+ put("SecretKeyFactory.PBEWithSHA1AndRC4_128",
+ "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_128"
+ );
+
+ put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+ put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC4_128,
+ "PBEWithSHA1AndRC4_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA1AndAES_128",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA1AndAES_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA224AndAES_128",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA224AndAES_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA256AndAES_128",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA256AndAES_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA384AndAES_128",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA384AndAES_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA512AndAES_128",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA512AndAES_128");
+
+ put("SecretKeyFactory.PBEWithHmacSHA1AndAES_256",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA1AndAES_256");
+
+ put("SecretKeyFactory.PBEWithHmacSHA224AndAES_256",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA224AndAES_256");
+
+ put("SecretKeyFactory.PBEWithHmacSHA256AndAES_256",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA256AndAES_256");
+
+ put("SecretKeyFactory.PBEWithHmacSHA384AndAES_256",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA384AndAES_256");
+
+ put("SecretKeyFactory.PBEWithHmacSHA512AndAES_256",
+ "com.sun.crypto.provider.PBEKeyFactory$" +
+ "PBEWithHmacSHA512AndAES_256");
+
+ // PBKDF2
+
put("SecretKeyFactory.PBKDF2WithHmacSHA1",
- "com.sun.crypto.provider.PBKDF2HmacSHA1Factory");
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA1");
put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS5_PBKDF2,
"PBKDF2WithHmacSHA1");
put("Alg.Alias.SecretKeyFactory." + OID_PKCS5_PBKDF2,
"PBKDF2WithHmacSHA1");
+ put("SecretKeyFactory.PBKDF2WithHmacSHA224",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA224");
+ put("SecretKeyFactory.PBKDF2WithHmacSHA256",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA256");
+ put("SecretKeyFactory.PBKDF2WithHmacSHA384",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA384");
+ put("SecretKeyFactory.PBKDF2WithHmacSHA512",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA512");
+
/*
* MAC
*/
@@ -475,6 +686,19 @@
put("Mac.HmacPBESHA1",
"com.sun.crypto.provider.HmacPKCS12PBESHA1");
+ // PBMAC1
+
+ put("Mac.PBEWithHmacSHA1",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA1");
+ put("Mac.PBEWithHmacSHA224",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA224");
+ put("Mac.PBEWithHmacSHA256",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA256");
+ put("Mac.PBEWithHmacSHA384",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA384");
+ put("Mac.PBEWithHmacSHA512",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA512");
+
put("Mac.SslMacMD5",
"com.sun.crypto.provider.SslMacCore$SslMacMD5");
put("Mac.SslMacSHA1",
@@ -487,6 +711,10 @@
put("Mac.HmacSHA384 SupportedKeyFormats", "RAW");
put("Mac.HmacSHA512 SupportedKeyFormats", "RAW");
put("Mac.HmacPBESHA1 SupportedKeyFormats", "RAW");
+ put("Mac.HmacPBESHA224 SupportedKeyFormats", "RAW");
+ put("Mac.HmacPBESHA256 SupportedKeyFormats", "RAW");
+ put("Mac.HmacPBESHA384 SupportedKeyFormats", "RAW");
+ put("Mac.HmacPBESHA512 SupportedKeyFormats", "RAW");
put("Mac.SslMacMD5 SupportedKeyFormats", "RAW");
put("Mac.SslMacSHA1 SupportedKeyFormats", "RAW");
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Thu Nov 15 00:54:54 2012 +0000
@@ -59,6 +59,9 @@
public final static Package.Version JAVA7_MAX_CLASS_VERSION =
Package.Version.of(51, 00);
+ public final static Package.Version JAVA8_MAX_CLASS_VERSION =
+ Package.Version.of(52, 00);
+
public final static int JAVA_PACKAGE_MAGIC = 0xCAFED00D;
public final static Package.Version JAVA5_PACKAGE_VERSION =
@@ -72,7 +75,7 @@
// upper limit, should point to the latest class version
public final static Package.Version JAVA_MAX_CLASS_VERSION =
- JAVA7_MAX_CLASS_VERSION;
+ JAVA8_MAX_CLASS_VERSION;
// upper limit should point to the latest package version, for version info!.
public final static Package.Version MAX_PACKAGE_VERSION =
--- a/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java Thu Nov 15 00:54:54 2012 +0000
@@ -542,14 +542,26 @@
try {
NamingEnumeration<InputStream> resources =
helper.getResources(cl, APP_RESOURCE_FILE_NAME);
- while (resources.hasMore()) {
- Properties props = new Properties();
- props.load(resources.next());
+ try {
+ while (resources.hasMore()) {
+ Properties props = new Properties();
+ InputStream istream = resources.next();
+ try {
+ props.load(istream);
+ } finally {
+ istream.close();
+ }
- if (result == null) {
- result = props;
- } else {
- mergeTables(result, props);
+ if (result == null) {
+ result = props;
+ } else {
+ mergeTables(result, props);
+ }
+ }
+ } finally {
+ while (resources.hasMore()) {
+ InputStream istream = (InputStream)resources.next();
+ istream.close();
}
}
@@ -557,13 +569,17 @@
InputStream istream =
helper.getJavaHomeLibStream(JRELIB_PROPERTY_FILE_NAME);
if (istream != null) {
- Properties props = new Properties();
- props.load(istream);
+ try {
+ Properties props = new Properties();
+ props.load(istream);
- if (result == null) {
- result = props;
- } else {
- mergeTables(result, props);
+ if (result == null) {
+ result = props;
+ } else {
+ mergeTables(result, props);
+ }
+ } finally {
+ istream.close();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import org.ietf.jgss.*;
+
+/**
+ * The extended GSSCredential interface for supporting additional
+ * functionalities not defined by {@code org.ietf.jgss.GSSCredential}.
+ * @since 1.8
+ */
+public interface ExtendedGSSCredential extends GSSCredential {
+ /**
+ * Impersonates a principal. In Kerberos, this can be implemented
+ * using the Microsoft S4U2self extension.
+ * <p>
+ * A {@link GSSException#NO_CRED GSSException.NO_CRED} will be thrown if the
+ * impersonation fails. A {@link GSSException#FAILURE GSSException.FAILURE}
+ * will be thrown if the impersonation method is not available to this
+ * credential object.
+ * @param name the name of the principal to impersonate
+ * @return a credential for that principal
+ * @throws GSSException containing the following
+ * major error codes:
+ * {@link GSSException#NO_CRED GSSException.NO_CRED}
+ * {@link GSSException#FAILURE GSSException.FAILURE}
+ */
+ public GSSCredential impersonate(GSSName name) throws GSSException;
+}
--- a/jdk/src/share/classes/java/lang/Character.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Character.java Thu Nov 15 00:54:54 2012 +0000
@@ -40,7 +40,7 @@
* a character's category (lowercase letter, digit, etc.) and for converting
* characters from uppercase to lowercase and vice versa.
* <p>
- * Character information is based on the Unicode Standard, version 6.1.0.
+ * Character information is based on the Unicode Standard, version 6.2.0.
* <p>
* The methods and data of class {@code Character} are defined by
* the information in the <i>UnicodeData</i> file that is part of the
@@ -3758,8 +3758,7 @@
0x0640, // 0640..0640; COMMON
0x0641, // 0641..064A; ARABIC
0x064B, // 064B..0655; INHERITED
- 0x0656, // 0656..065E; ARABIC
- 0x065F, // 065F..065F; INHERITED
+ 0x0656, // 0656..065F; ARABIC
0x0660, // 0660..0669; COMMON
0x066A, // 066A..066F; ARABIC
0x0670, // 0670..0670; INHERITED
@@ -4081,7 +4080,6 @@
ARABIC,
INHERITED,
ARABIC,
- INHERITED,
COMMON,
ARABIC,
INHERITED,
--- a/jdk/src/share/classes/java/lang/Math.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Math.java Thu Nov 15 00:54:54 2012 +0000
@@ -742,6 +742,7 @@
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows an int
+ * @since 1.8
*/
public static int addExact(int x, int y) {
int r = x + y;
@@ -760,6 +761,7 @@
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows a long
+ * @since 1.8
*/
public static long addExact(long x, long y) {
long r = x + y;
@@ -778,6 +780,7 @@
* @param y the second value to subtract from the first
* @return the result
* @throws ArithmeticException if the result overflows an int
+ * @since 1.8
*/
public static int subtractExact(int x, int y) {
int r = x - y;
@@ -797,6 +800,7 @@
* @param y the second value to subtract from the first
* @return the result
* @throws ArithmeticException if the result overflows a long
+ * @since 1.8
*/
public static long subtractExact(long x, long y) {
long r = x - y;
@@ -816,6 +820,7 @@
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows an int
+ * @since 1.8
*/
public static int multiplyExact(int x, int y) {
long r = (long)x * (long)y;
@@ -833,6 +838,7 @@
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows a long
+ * @since 1.8
*/
public static long multiplyExact(long x, long y) {
long r = x * y;
@@ -857,6 +863,7 @@
* @param value the long value
* @return the argument as an int
* @throws ArithmeticException if the {@code argument} overflows an int
+ * @since 1.8
*/
public static int toIntExact(long value) {
if ((int)value != value) {
@@ -866,6 +873,159 @@
}
/**
+ * Returns the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Integer.MIN_VALUE}.
+ * <p>
+ * Normal integer division operates under the round to zero rounding mode
+ * (truncation). This operation instead acts under the round toward
+ * negative infinity (floor) rounding mode.
+ * The floor rounding mode gives different results than truncation
+ * when the exact result is negative.
+ * <ul>
+ * <li>If the signs of the arguments are the same, the results of
+ * {@code floorDiv} and the {@code /} operator are the same. <br>
+ * For example, {@code floorDiv(4, 3) == 1} and {@code (4 / 3) == 1}.</li>
+ * <li>If the signs of the arguments are different, the quotient is negative and
+ * {@code floorDiv} returns the integer less than or equal to the quotient
+ * and the {@code /} operator returns the integer closest to zero.<br>
+ * For example, {@code floorDiv(-4, 3) == -2},
+ * whereas {@code (-4 / 3) == -1}.
+ * </li>
+ * </ul>
+ * <p>
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorMod(int, int)
+ * @see #floor(double)
+ * @since 1.8
+ */
+ public static int floorDiv(int x, int y) {
+ int r = x / y;
+ // if the signs are different and modulo not zero, round down
+ if ((x ^ y) < 0 && (r * y != x)) {
+ r--;
+ }
+ return r;
+ }
+
+ /**
+ * Returns the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Long.MIN_VALUE}.
+ * <p>
+ * Normal integer division operates under the round to zero rounding mode
+ * (truncation). This operation instead acts under the round toward
+ * negative infinity (floor) rounding mode.
+ * The floor rounding mode gives different results than truncation
+ * when the exact result is negative.
+ * <p>
+ * For examples, see {@link #floorDiv(int, int)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorMod(long, long)
+ * @see #floor(double)
+ * @since 1.8
+ */
+ public static long floorDiv(long x, long y) {
+ long r = x / y;
+ // if the signs are different and modulo not zero, round down
+ if ((x ^ y) < 0 && (r * y != x)) {
+ r--;
+ }
+ return r;
+ }
+
+ /**
+ * Returns the floor modulus of the {@code int} arguments.
+ * <p>
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ *
+ * <p>
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ * <ul>
+ * <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ * </ul>
+ * <p>
+ * The difference in values between {@code floorMod} and
+ * the {@code %} operator is due to the difference between
+ * {@code floorDiv} that returns the integer less than or equal to the quotient
+ * and the {@code /} operator that returns the integer closest to zero.
+ * <p>
+ * Examples:
+ * <ul>
+ * <li>If the signs of the arguments are the same, the results
+ * of {@code floorMod} and the {@code %} operator are the same. <br>
+ * <ul>
+ * <li>{@code floorMod(4, 3) == 1}; and {@code (4 % 3) == 1}</li>
+ * </ul>
+ * <li>If the signs of the arguments are different, the results differ from the {@code %} operator.<br>
+ * <ul>
+ * <li>{@code floorMod(+4, -3) == -2}; and {@code (+4 % -3) == +1} </li>
+ * <li>{@code floorMod(-4, +3) == +2}; and {@code (-4 % +3) == -1} </li>
+ * <li>{@code floorMod(-4, -3) == -1}; and {@code (-4 % -3) == -1 } </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * <p>
+ * If the signs of arguments are unknown and a positive modulus
+ * is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorDiv(int, int)
+ * @since 1.8
+ */
+ public static int floorMod(int x, int y) {
+ int r = x - floorDiv(x, y) * y;
+ return r;
+ }
+
+ /**
+ * Returns the floor modulus of the {@code long} arguments.
+ * <p>
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ *
+ * <p>
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ * <ul>
+ * <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ * </ul>
+ * <p>
+ * For examples, see {@link #floorMod(int, int)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorDiv(long, long)
+ * @since 1.8
+ */
+ public static long floorMod(long x, long y) {
+ return x - floorDiv(x, y) * y;
+ }
+
+ /**
* Returns the absolute value of an {@code int} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
--- a/jdk/src/share/classes/java/lang/StrictMath.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/lang/StrictMath.java Thu Nov 15 00:54:54 2012 +0000
@@ -365,7 +365,7 @@
* @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 sign the sign of the result
+ * @param increment value to add when the argument is non-integral
*/
private static double floorOrCeil(double a,
double negativeBoundary,
@@ -702,7 +702,7 @@
* <p>This method is properly synchronized to allow correct use by
* more than one thread. However, if many threads need to generate
* pseudorandom numbers at a great rate, it may reduce contention
- * for each thread to have its own pseudorandom number generator.
+ * for each thread to have its own pseudorandom-number generator.
*
* @return a pseudorandom {@code double} greater than or equal
* to {@code 0.0} and less than {@code 1.0}.
@@ -745,7 +745,7 @@
}
/**
- * Return the difference of the arguments,
+ * Returns the difference of the arguments,
* throwing an exception if the result overflows an {@code int}.
*
* @param x the first value
@@ -760,7 +760,7 @@
}
/**
- * Return the difference of the arguments,
+ * Returns the difference of the arguments,
* throwing an exception if the result overflows a {@code long}.
*
* @param x the first value
@@ -775,7 +775,7 @@
}
/**
- * Return the product of the arguments,
+ * Returns the product of the arguments,
* throwing an exception if the result overflows an {@code int}.
*
* @param x the first value
@@ -790,7 +790,7 @@
}
/**
- * Return the product of the arguments,
+ * Returns the product of the arguments,
* throwing an exception if the result overflows a {@code long}.
*
* @param x the first value
@@ -805,7 +805,7 @@
}
/**
- * Return the value of the {@code long} argument;
+ * Returns the value of the {@code long} argument;
* throwing an exception if the value overflows an {@code int}.
*
* @param value the long value
@@ -819,6 +819,107 @@
}
/**
+ * Returns the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Integer.MIN_VALUE}.
+ * <p>
+ * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
+ * a comparison to the integer division {@code /} operator.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see Math#floorDiv(int, int)
+ * @see Math#floor(double)
+ * @since 1.8
+ */
+ public static int floorDiv(int x, int y) {
+ return Math.floorDiv(x, y);
+ }
+
+ /**
+ * Returns the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Long.MIN_VALUE}.
+ * <p>
+ * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
+ * a comparison to the integer division {@code /} operator.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see Math#floorDiv(long, long)
+ * @see Math#floor(double)
+ * @since 1.8
+ */
+ public static long floorDiv(long x, long y) {
+ return Math.floorDiv(x, y);
+ }
+
+ /**
+ * Returns the floor modulus of the {@code int} arguments.
+ * <p>
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ * <p>
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ * <ul>
+ * <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ * </ul>
+ * <p>
+ * See {@link Math#floorMod(int, int) Math.floorMod} for examples and
+ * a comparison to the {@code %} operator.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see Math#floorMod(int, int)
+ * @see StrictMath#floorDiv(int, int)
+ * @since 1.8
+ */
+ public static int floorMod(int x, int y) {
+ return Math.floorMod(x , y);
+ }
+ /**
+ * Returns the floor modulus of the {@code long} arguments.
+ * <p>
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ * <p>
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ * <ul>
+ * <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ * </ul>
+ * <p>
+ * See {@link Math#floorMod(int, int) Math.floorMod} for examples and
+ * a comparison to the {@code %} operator.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see Math#floorMod(long, long)
+ * @see StrictMath#floorDiv(long, long)
+ * @since 1.8
+ */
+ public static long floorMod(long x, long y) {
+ return Math.floorMod(x, y);
+ }
+
+ /**
* Returns the absolute value of an {@code int} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
@@ -1543,7 +1644,7 @@
}
/**
- * Return {@code d} ×
+ * Returns {@code d} ×
* 2<sup>{@code scaleFactor}</sup> rounded as if performed
* by a single correctly rounded floating-point multiply to a
* member of the double value set. See the Java
@@ -1577,7 +1678,7 @@
}
/**
- * Return {@code f} ×
+ * Returns {@code f} ×
* 2<sup>{@code scaleFactor}</sup> rounded as if performed
* by a single correctly rounded floating-point multiply to a
* member of the float value set. See the Java
--- a/jdk/src/share/classes/java/lang/annotation/ElementType.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/ElementType.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
/** Method declaration */
METHOD,
- /** Parameter declaration */
+ /** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
@@ -59,5 +59,19 @@
ANNOTATION_TYPE,
/** Package declaration */
- PACKAGE
+ PACKAGE,
+
+ /**
+ * Type parameter declaration
+ *
+ * @since 1.8
+ */
+ TYPE_PARAMETER,
+
+ /**
+ * Use of a type
+ *
+ * @since 1.8
+ */
+ TYPE_USE
}
--- a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Thu Nov 15 00:54:54 2012 +0000
@@ -315,12 +315,14 @@
* Returns a {@code CertPathChecker} that the encapsulated
* {@code CertPathBuilderSpi} implementation uses to check the revocation
* status of certificates. A PKIX implementation returns objects of
- * type {@code PKIXRevocationChecker}.
+ * type {@code PKIXRevocationChecker}. Each invocation of this method
+ * returns a new instance of {@code CertPathChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description for an example.
*
+ * @return a {@code CertPathChecker}
* @throws UnsupportedOperationException if the service provider does not
* support this method
* @since 1.8
--- a/jdk/src/share/classes/java/security/cert/CertPathValidator.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidator.java Thu Nov 15 00:54:54 2012 +0000
@@ -327,12 +327,14 @@
* Returns a {@code CertPathChecker} that the encapsulated
* {@code CertPathValidatorSpi} implementation uses to check the revocation
* status of certificates. A PKIX implementation returns objects of
- * type {@code PKIXRevocationChecker}.
+ * type {@code PKIXRevocationChecker}. Each invocation of this method
+ * returns a new instance of {@code CertPathChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description for an example.
*
+ * @return a {@code CertPathChecker}
* @throws UnsupportedOperationException if the service provider does not
* support this method
* @since 1.8
--- a/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java Thu Nov 15 00:54:54 2012 +0000
@@ -63,8 +63,8 @@
* and then the {@code PKIXParameters} is passed along with the {@code CertPath}
* to be validated to the {@link CertPathValidator#validate validate} method
* of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
- * this manner, do not enable the default revocation checking mechanism (by
- * calling {@link PKIXParameters#setRevocationEnabled}.
+ * this manner, it will be used to check revocation irrespective of the setting
+ * of the {@link PKIXParameters#isRevocationEnabled RevocationEnabled} flag.
*
* <p>Note that when a {@code PKIXRevocationChecker} is added to
* {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
@@ -88,7 +88,7 @@
private URI ocspResponder;
private X509Certificate ocspResponderCert;
private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
- private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap();
+ private Map<X509Certificate, byte[]> ocspResponses = Collections.emptyMap();
private Set<Option> options = Collections.emptySet();
protected PKIXRevocationChecker() {}
@@ -169,40 +169,40 @@
}
/**
- * Sets the stapled OCSP responses. These responses are used to determine
+ * Sets the OCSP responses. These responses are used to determine
* the revocation status of the specified certificates when OCSP is used.
*
- * @param responses a map of stapled OCSP responses. Each key is an
+ * @param responses a map of OCSP responses. Each key is an
* {@code X509Certificate} that maps to the corresponding
* DER-encoded OCSP response for that certificate. A deep copy of
* the map is performed to protect against subsequent modification.
*/
- public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses)
+ public void setOCSPResponses(Map<X509Certificate, byte[]> responses)
{
if (responses == null) {
- this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap();
+ this.ocspResponses = Collections.<X509Certificate, byte[]>emptyMap();
} else {
Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
- this.ocspStapled = copy;
+ this.ocspResponses = copy;
}
}
/**
- * Gets the stapled OCSP responses. These responses are used to determine
+ * Gets the OCSP responses. These responses are used to determine
* the revocation status of the specified certificates when OCSP is used.
*
- * @return a map of stapled OCSP responses. Each key is an
+ * @return a map of OCSP responses. Each key is an
* {@code X509Certificate} that maps to the corresponding
* DER-encoded OCSP response for that certificate. A deep copy of
* the map is returned to protect against subsequent modification.
* Returns an empty map if no responses have been specified.
*/
- public Map<X509Certificate, byte[]> getOCSPStapledResponses() {
- Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size());
- for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) {
+ public Map<X509Certificate, byte[]> getOCSPResponses() {
+ Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size());
+ for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
return copy;
@@ -234,10 +234,10 @@
public Object clone() {
PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
copy.ocspExtensions = new ArrayList<>(ocspExtensions);
- copy.ocspStapled = new HashMap<>(ocspStapled);
- // deep-copy the encoded stapled responses, since they are mutable
+ copy.ocspResponses = new HashMap<>(ocspResponses);
+ // deep-copy the encoded responses, since they are mutable
for (Map.Entry<X509Certificate, byte[]> entry :
- copy.ocspStapled.entrySet())
+ copy.ocspResponses.entrySet())
{
byte[] encoded = entry.getValue();
entry.setValue(encoded.clone());
--- a/jdk/src/share/classes/javax/crypto/spec/PBEParameterSpec.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/crypto/spec/PBEParameterSpec.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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
@@ -41,6 +41,7 @@
private byte[] salt;
private int iterationCount;
+ private AlgorithmParameterSpec paramSpec = null;
/**
* Constructs a parameter set for password-based encryption as defined in
@@ -57,6 +58,25 @@
}
/**
+ * Constructs a parameter set for password-based encryption as defined in
+ * the PKCS #5 standard.
+ *
+ * @param salt the salt. The contents of <code>salt</code> are copied
+ * to protect against subsequent modification.
+ * @param iterationCount the iteration count.
+ * @param paramSpec the cipher algorithm parameter specification.
+ * @exception NullPointerException if <code>salt</code> is null.
+ *
+ * @since 1.8
+ */
+ public PBEParameterSpec(byte[] salt, int iterationCount,
+ AlgorithmParameterSpec paramSpec) {
+ this.salt = salt.clone();
+ this.iterationCount = iterationCount;
+ this.paramSpec = paramSpec;
+ }
+
+ /**
* Returns the salt.
*
* @return the salt. Returns a new array
@@ -74,4 +94,15 @@
public int getIterationCount() {
return this.iterationCount;
}
+
+ /**
+ * Returns the cipher algorithm parameter specification.
+ *
+ * @return the parameter specification, or null if none was set.
+ *
+ * @since 1.8
+ */
+ public AlgorithmParameterSpec getParameterSpec() {
+ return this.paramSpec;
+ }
}
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialArray.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialArray.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -29,7 +29,7 @@
import java.io.*;
import java.util.Map;
import java.net.URL;
-
+import java.util.Arrays;
/**
* A serialized version of an <code>Array</code>
@@ -525,6 +525,97 @@
}
/**
+ * Compares this SerialArray to the specified object. The result is {@code
+ * true} if and only if the argument is not {@code null} and is a {@code
+ * SerialArray} object whose elements are identical to this object's elements
+ *
+ * @param obj The object to compare this {@code SerialArray} against
+ *
+ * @return {@code true} if the given object represents a {@code SerialArray}
+ * equivalent to this SerialArray, {@code false} otherwise
+ *
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof SerialArray) {
+ SerialArray sa = (SerialArray)obj;
+ return baseType == sa.baseType &&
+ baseTypeName.equals(sa.baseTypeName) &&
+ Arrays.equals(elements, sa.elements);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code for this SerialArray. The hash code for a
+ * {@code SerialArray} object is computed using the hash codes
+ * of the elements of the {@code SerialArray} object
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return (((31 + Arrays.hashCode(elements)) * 31 + len) * 31 +
+ baseType) * 31 + baseTypeName.hashCode();
+ }
+
+ /**
+ * Returns a clone of this {@code SerialArray}. The copy will contain a
+ * reference to a clone of the underlying objects array, not a reference
+ * to the original underlying object array of this {@code SerialArray} object.
+ *
+ * @return a clone of this SerialArray
+ */
+ public Object clone() {
+ try {
+ SerialArray sa = (SerialArray) super.clone();
+ sa.elements = Arrays.copyOf(elements, len);
+ return sa;
+ } catch (CloneNotSupportedException ex) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+
+ }
+
+ /**
+ * readObject is called to restore the state of the {@code SerialArray} from
+ * a stream.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectInputStream.GetField fields = s.readFields();
+ Object[] tmp = (Object[])fields.get("elements", null);
+ if (tmp == null)
+ throw new InvalidObjectException("elements is null and should not be!");
+ elements = tmp.clone();
+ len = fields.get("len", 0);
+ if(elements.length != len)
+ throw new InvalidObjectException("elements is not the expected size");
+
+ baseType = fields.get("baseType", 0);
+ baseTypeName = (String)fields.get("baseTypeName", null);
+ }
+
+ /**
+ * writeObject is called to save the state of the {@code SerialArray}
+ * to a stream.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("elements", elements);
+ fields.put("len", len);
+ fields.put("baseType", baseType);
+ fields.put("baseTypeName", baseTypeName);
+ s.writeFields();
+ }
+
+ /**
* The identifier that assists in the serialization of this <code>SerialArray</code>
* object.
*/
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialDatalink.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialDatalink.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -100,10 +100,64 @@
return aURL;
}
+ /**
+ * Compares this {@code SerialDatalink} to the specified object.
+ * The result is {@code true} if and only if the argument is not
+ * {@code null} and is a {@code SerialDatalink} object whose URL is
+ * identical to this object's URL
+ *
+ * @param obj The object to compare this {@code SerialDatalink} against
+ *
+ * @return {@code true} if the given object represents a {@code SerialDatalink}
+ * equivalent to this SerialDatalink, {@code false} otherwise
+ *
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SerialDatalink) {
+ SerialDatalink sdl = (SerialDatalink) obj;
+ return url.equals(sdl.url);
+ }
+ return false;
+ }
/**
- * The identifier that assists in the serialization of this <code>SerialDatalink</code>
- * object.
+ * Returns a hash code for this {@code SerialDatalink}. The hash code for a
+ * {@code SerialDatalink} object is taken as the hash code of
+ * the {@code URL} it stores
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return 31 + url.hashCode();
+ }
+
+ /**
+ * Returns a clone of this {@code SerialDatalink}.
+ *
+ * @return a clone of this SerialDatalink
+ */
+ public Object clone() {
+ try {
+ SerialDatalink sdl = (SerialDatalink) super.clone();
+ return sdl;
+ } catch (CloneNotSupportedException ex) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * readObject and writeObject are called to restore the state
+ * of the {@code SerialDatalink}
+ * from a stream. Note: we leverage the default Serialized form
+ */
+
+ /**
+ * The identifier that assists in the serialization of this
+ * {@code SerialDatalink} object.
*/
static final long serialVersionUID = 2826907821828733626L;
}
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
import java.io.*;
import java.lang.reflect.*;
+import java.util.Arrays;
+import java.util.Vector;
import javax.sql.rowset.RowSetWarning;
/**
@@ -49,7 +51,7 @@
/**
* Placeholder for object to be serialized.
*/
- private final Object obj;
+ private Object obj;
/**
@@ -82,18 +84,9 @@
// any of these are static, this should invalidate
// the action of attempting to persist these fields
// in a serialized form
-
- boolean anyStaticFields = false;
fields = c.getFields();
- for (int i = 0; i < fields.length; i++ ) {
- if ( fields[i].getModifiers() == Modifier.STATIC ) {
- anyStaticFields = true;
- }
- }
-
-
- if (anyStaticFields) {
+ if (hasStaticFields(fields)) {
throw new SerialException("Located static fields in " +
"object instance. Cannot serialize");
}
@@ -132,7 +125,7 @@
}
/**
- * The identifier that assists in the serialization of this
+ * The identifier that assists in the serialization of this
* <code>SerialJavaObject</code> object.
*/
static final long serialVersionUID = -1465795139032831023L;
@@ -142,15 +135,117 @@
* object. When there are multiple warnings, each warning is chained to the
* previous warning.
*/
- java.util.Vector<RowSetWarning> chain;
+ Vector<RowSetWarning> chain;
+
+ /**
+ * Compares this SerialJavaObject to the specified object.
+ * The result is {@code true} if and only if the argument
+ * is not {@code null} and is a {@code SerialJavaObject}
+ * object that is identical to this object
+ *
+ * @param o The object to compare this {@code SerialJavaObject} against
+ *
+ * @return {@code true} if the given object represents a {@code SerialJavaObject}
+ * equivalent to this SerialJavaObject, {@code false} otherwise
+ *
+ */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof SerialJavaObject) {
+ SerialJavaObject sjo = (SerialJavaObject) o;
+ return obj.equals(sjo.obj);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code for this SerialJavaObject. The hash code for a
+ * {@code SerialJavaObject} object is taken as the hash code of
+ * the {@code Object} it stores
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return 31 + obj.hashCode();
+ }
+
+ /**
+ * Returns a clone of this {@code SerialJavaObject}.
+ *
+ * @return a clone of this SerialJavaObject
+ */
+
+ public Object clone() {
+ try {
+ SerialJavaObject sjo = (SerialJavaObject) super.clone();
+ sjo.fields = Arrays.copyOf(fields, fields.length);
+ if (chain != null)
+ sjo.chain = new Vector<>(chain);
+ return sjo;
+ } catch (CloneNotSupportedException ex) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
/**
* Registers the given warning.
*/
private void setWarning(RowSetWarning e) {
if (chain == null) {
- chain = new java.util.Vector<>();
+ chain = new Vector<>();
}
chain.add(e);
}
+
+ /**
+ * readObject is called to restore the state of the {@code SerialJavaObject}
+ * from a stream.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectInputStream.GetField fields1 = s.readFields();
+ @SuppressWarnings("unchecked")
+ Vector<RowSetWarning> tmp = (Vector<RowSetWarning>)fields1.get("chain", null);
+ if (tmp != null)
+ chain = new Vector<>(tmp);
+
+ obj = fields1.get("obj", null);
+ if (obj != null) {
+ fields = obj.getClass().getFields();
+ if(hasStaticFields(fields))
+ throw new IOException("Located static fields in " +
+ "object instance. Cannot serialize");
+ } else {
+ throw new IOException("Object cannot be null!");
+ }
+
+ }
+
+ /**
+ * writeObject is called to save the state of the {@code SerialJavaObject}
+ * to a stream.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException {
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("obj", obj);
+ fields.put("chain", chain);
+ s.writeFields();
+ }
+
+ /*
+ * Check to see if there are any Static Fields in this object
+ */
+ private static boolean hasStaticFields(Field[] fields) {
+ for (Field field : fields) {
+ if ( field.getModifiers() == Modifier.STATIC) {
+ return true;
+ }
+ }
+ return false;
+ }
}
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -163,7 +163,85 @@
}
/**
- * The identifier that assists in the serialization of this <code>SerialRef</code>
+ * Compares this SerialRef to the specified object. The result is {@code
+ * true} if and only if the argument is not {@code null} and is a {@code
+ * SerialRef} object that represents the same object as this
+ * object.
+ *
+ * @param obj The object to compare this {@code SerialRef} against
+ *
+ * @return {@code true} if the given object represents a {@code SerialRef}
+ * equivalent to this SerialRef, {@code false} otherwise
+ *
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if(obj instanceof SerialRef) {
+ SerialRef ref = (SerialRef)obj;
+ return baseTypeName.equals(ref.baseTypeName) &&
+ object.equals(ref.object);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code for this {@code SerialRef}.
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return (31 + object.hashCode()) * 31 + baseTypeName.hashCode();
+ }
+
+ /**
+ * Returns a clone of this {@code SerialRef}. .
+ * The underlying {@code Ref} object will be set to null.
+ *
+ * @return a clone of this SerialRef
+ */
+ public Object clone() {
+ try {
+ SerialRef ref = (SerialRef) super.clone();
+ ref.reference = null;
+ return ref;
+ } catch (CloneNotSupportedException ex) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+
+ }
+
+ /**
+ * readObject is called to restore the state of the SerialRef from
+ * a stream.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ ObjectInputStream.GetField fields = s.readFields();
+ object = fields.get("object", null);
+ baseTypeName = (String) fields.get("baseTypeName", null);
+ reference = (Ref) fields.get("reference", null);
+ }
+
+ /**
+ * writeObject is called to save the state of the SerialRef
+ * to a stream.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("baseTypeName", baseTypeName);
+ fields.put("object", object);
+ // Note: this check to see if it is an instance of Serializable
+ // is for backwards compatibiity
+ fields.put("reference", reference instanceof Serializable ? reference : null);
+ s.writeFields();
+ }
+
+ /**
+ * The identifier that assists in the serialization of this <code>SerialRef</code>
* object.
*/
static final long serialVersionUID = -4727123500609662274L;
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java Thu Nov 15 00:54:54 2012 +0000
@@ -250,6 +250,88 @@
}
/**
+ * Compares this SerialStruct to the specified object. The result is
+ * {@code true} if and only if the argument is not {@code null} and is a
+ * {@code SerialStruct} object whose attributes are identical to this
+ * object's attributes
+ *
+ * @param obj The object to compare this {@code SerialStruct} against
+ *
+ * @return {@code true} if the given object represents a {@code SerialStruct}
+ * equivalent to this SerialStruct, {@code false} otherwise
+ *
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SerialStruct) {
+ SerialStruct ss = (SerialStruct)obj;
+ return SQLTypeName.equals(ss.SQLTypeName) &&
+ Arrays.equals(attribs, ss.attribs);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code for this {@code SerialStruct}. The hash code for a
+ * {@code SerialStruct} object is computed using the hash codes
+ * of the attributes of the {@code SerialStruct} object and its
+ * {@code SQLTypeName}
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return ((31 + Arrays.hashCode(attribs)) * 31) * 31
+ + SQLTypeName.hashCode();
+ }
+
+ /**
+ * Returns a clone of this {@code SerialStruct}. The copy will contain a
+ * reference to a clone of the underlying attribs array, not a reference
+ * to the original underlying attribs array of this {@code SerialStruct} object.
+ *
+ * @return a clone of this SerialStruct
+ */
+ public Object clone() {
+ try {
+ SerialStruct ss = (SerialStruct) super.clone();
+ ss.attribs = Arrays.copyOf(attribs, attribs.length);
+ return ss;
+ } catch (CloneNotSupportedException ex) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+
+ }
+
+ /**
+ * readObject is called to restore the state of the {@code SerialStruct} from
+ * a stream.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectInputStream.GetField fields = s.readFields();
+ Object[] tmp = (Object[])fields.get("attribs", null);
+ attribs = tmp == null ? null : tmp.clone();
+ SQLTypeName = (String)fields.get("SQLTypeName", null);
+ }
+
+ /**
+ * writeObject is called to save the state of the {@code SerialStruct}
+ * to a stream.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException, ClassNotFoundException {
+
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("attribs", attribs);
+ fields.put("SQLTypeName", SQLTypeName);
+ s.writeFields();
+ }
+
+ /**
* The identifier that assists in the serialization of this
* <code>SerialStruct</code> object.
*/
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Thu Nov 15 00:54:54 2012 +0000
@@ -302,12 +302,10 @@
}
}
- public FileChannel truncate(long size) throws IOException {
+ public FileChannel truncate(long newSize) throws IOException {
ensureOpen();
- if (size < 0)
- throw new IllegalArgumentException();
- if (size > size())
- return this;
+ if (newSize < 0)
+ throw new IllegalArgumentException("Negative size");
if (!writable)
throw new NonWritableChannelException();
synchronized (positionLock) {
@@ -320,6 +318,14 @@
if (!isOpen())
return null;
+ // get current size
+ long size;
+ do {
+ size = nd.size(fd);
+ } while ((size == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+
// get current position
do {
p = position0(fd, -1);
@@ -328,16 +334,18 @@
return null;
assert p >= 0;
- // truncate file
- do {
- rv = nd.truncate(fd, size);
- } while ((rv == IOStatus.INTERRUPTED) && isOpen());
- if (!isOpen())
- return null;
+ // truncate file if given size is less than the current size
+ if (newSize < size) {
+ do {
+ rv = nd.truncate(fd, newSize);
+ } while ((rv == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+ }
- // set position to size if greater than size
- if (p > size)
- p = size;
+ // if position is beyond new size then adjust it
+ if (p > newSize)
+ p = newSize;
do {
rv = (int)position0(fd, p);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
@@ -779,6 +787,8 @@
throws IOException
{
ensureOpen();
+ if (mode == null)
+ throw new NullPointerException("Mode is null");
if (position < 0L)
throw new IllegalArgumentException("Negative position");
if (size < 0L)
@@ -787,6 +797,7 @@
throw new IllegalArgumentException("Position + size overflow");
if (size > Integer.MAX_VALUE)
throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
+
int imode = -1;
if (mode == MapMode.READ_ONLY)
imode = MAP_RO;
--- a/jdk/src/share/classes/sun/security/jgss/GSSCaller.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSCaller.java Thu Nov 15 00:54:54 2012 +0000
@@ -31,10 +31,19 @@
* different callers.
*/
public class GSSCaller {
- public static final GSSCaller CALLER_UNKNOWN = new GSSCaller();
- public static final GSSCaller CALLER_INITIATE = new GSSCaller();
- public static final GSSCaller CALLER_ACCEPT = new GSSCaller();
- public static final GSSCaller CALLER_SSL_CLIENT = new GSSCaller();
- public static final GSSCaller CALLER_SSL_SERVER = new GSSCaller();
+ public static final GSSCaller CALLER_UNKNOWN = new GSSCaller("UNKNOWN");
+ public static final GSSCaller CALLER_INITIATE = new GSSCaller("INITIATE");
+ public static final GSSCaller CALLER_ACCEPT = new GSSCaller("ACCEPT");
+ public static final GSSCaller CALLER_SSL_CLIENT = new GSSCaller("SSL_CLIENT");
+ public static final GSSCaller CALLER_SSL_SERVER = new GSSCaller("SSL_SERVER");
+
+ private String name;
+ GSSCaller(String s) {
+ name = s;
+ }
+ @Override
+ public String toString() {
+ return "GSSCaller{" + name + '}';
+ }
}
--- a/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java Thu Nov 15 00:54:54 2012 +0000
@@ -28,8 +28,9 @@
import org.ietf.jgss.*;
import sun.security.jgss.spi.*;
import java.util.*;
+import com.sun.security.jgss.*;
-public class GSSCredentialImpl implements GSSCredential {
+public class GSSCredentialImpl implements ExtendedGSSCredential {
private GSSManagerImpl gssManager = null;
private boolean destroyed = false;
@@ -122,6 +123,19 @@
}
}
+ public GSSCredential impersonate(GSSName name) throws GSSException {
+ if (destroyed) {
+ throw new IllegalStateException("This credential is " +
+ "no longer valid");
+ }
+ Oid mech = tempCred.getMechanism();
+ GSSNameSpi nameElement = (name == null ? null :
+ ((GSSNameImpl)name).getElement(mech));
+ GSSCredentialSpi cred = tempCred.impersonate(nameElement);
+ return (cred == null ?
+ null : new GSSCredentialImpl(gssManager, cred));
+ }
+
public GSSName getName() throws GSSException {
if (destroyed) {
throw new IllegalStateException("This credential is " +
--- a/jdk/src/share/classes/sun/security/jgss/HttpCaller.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/HttpCaller.java Thu Nov 15 00:54:54 2012 +0000
@@ -35,6 +35,7 @@
final private HttpCallerInfo hci;
public HttpCaller(HttpCallerInfo hci) {
+ super("HTTP_CLIENT");
this.hci = hci;
}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java Thu Nov 15 00:54:54 2012 +0000
@@ -25,6 +25,7 @@
package sun.security.jgss.krb5;
+import java.io.IOException;
import org.ietf.jgss.*;
import sun.security.jgss.GSSCaller;
import sun.security.jgss.spi.*;
@@ -177,4 +178,21 @@
public void destroy() throws DestroyFailedException {
screds.destroy();
}
+
+ /**
+ * Impersonation is only available on the initiator side. The
+ * service must starts as an initiator to get an initial TGT to complete
+ * the S4U2self protocol.
+ */
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ Credentials cred = screds.getInitCred();
+ if (cred != null) {
+ return Krb5InitCredential.getInstance(this.name, cred)
+ .impersonate(name);
+ } else {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Only an initiate credentials can impersonate");
+ }
+ }
}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java Thu Nov 15 00:54:54 2012 +0000
@@ -45,6 +45,7 @@
import javax.crypto.Cipher;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.*;
+import sun.security.krb5.internal.Ticket;
/**
* Implements the mechanism specific context class for the Kerberos v5
@@ -76,7 +77,7 @@
* values.
*/
- private boolean credDelegState = false;
+ private boolean credDelegState = false; // now only useful at client
private boolean mutualAuthState = true;
private boolean replayDetState = true;
private boolean sequenceDetState = true;
@@ -84,6 +85,8 @@
private boolean integState = true;
private boolean delegPolicyState = false;
+ private boolean isConstrainedDelegationTried = false;
+
private int mySeqNumber;
private int peerSeqNumber;
private int keySrc;
@@ -113,13 +116,11 @@
private Krb5CredElement myCred;
private Krb5CredElement delegatedCred; // Set only on acceptor side
- /* DESCipher instance used by the corresponding GSSContext */
- private Cipher desCipher = null;
-
// XXX See if the required info from these can be extracted and
// stored elsewhere
private Credentials serviceCreds;
private KrbApReq apReq;
+ Ticket serviceTicket;
final private GSSCaller caller;
private static final boolean DEBUG = Krb5Util.DEBUG;
@@ -248,7 +249,14 @@
* Is credential delegation enabled?
*/
public final boolean getCredDelegState() {
- return credDelegState;
+ if (isInitiator()) {
+ return credDelegState;
+ } else {
+ // Server side deleg state is not flagged by credDelegState.
+ // It can use constrained delegation.
+ tryConstrainedDelegation();
+ return delegatedCred != null;
+ }
}
/**
@@ -498,7 +506,8 @@
* Returns the delegated credential for the context. This
* is an optional feature of contexts which not all
* mechanisms will support. A context can be requested to
- * support credential delegation by using the <b>CRED_DELEG</b>.
+ * support credential delegation by using the <b>CRED_DELEG</b>,
+ * or it can request for a constrained delegation.
* This is only valid on the acceptor side of the context.
* @return GSSCredentialSpi object for the delegated credential
* @exception GSSException
@@ -507,11 +516,41 @@
public final GSSCredentialSpi getDelegCred() throws GSSException {
if (state != STATE_IN_PROCESS && state != STATE_DONE)
throw new GSSException(GSSException.NO_CONTEXT);
- if (delegatedCred == null)
+ if (isInitiator()) {
throw new GSSException(GSSException.NO_CRED);
+ }
+ tryConstrainedDelegation();
+ if (delegatedCred == null) {
+ throw new GSSException(GSSException.NO_CRED);
+ }
return delegatedCred;
}
+ private void tryConstrainedDelegation() {
+ if (state != STATE_IN_PROCESS && state != STATE_DONE) {
+ return;
+ }
+ // We will only try constrained delegation once (if necessary).
+ if (!isConstrainedDelegationTried) {
+ if (delegatedCred == null) {
+ if (DEBUG) {
+ System.out.println(">>> Constrained deleg from " + caller);
+ }
+ // The constrained delegation part. The acceptor needs to have
+ // isInitiator=true in order to get a TGT, either earlier at
+ // logon stage, if useSubjectCredsOnly, or now.
+ try {
+ delegatedCred = new Krb5ProxyCredential(
+ Krb5InitCredential.getInstance(
+ GSSCaller.CALLER_ACCEPT, myName, lifetime),
+ peerName, serviceTicket);
+ } catch (GSSException gsse) {
+ // OK, delegatedCred is null then
+ }
+ }
+ isConstrainedDelegationTried = true;
+ }
+ }
/**
* Tests if this is the initiator side of the context.
*
@@ -577,8 +616,15 @@
"No TGT available");
}
myName = (Krb5NameElement) myCred.getName();
- Credentials tgt =
- ((Krb5InitCredential) myCred).getKrb5Credentials();
+ Credentials tgt;
+ final Krb5ProxyCredential second;
+ if (myCred instanceof Krb5InitCredential) {
+ second = null;
+ tgt = ((Krb5InitCredential) myCred).getKrb5Credentials();
+ } else {
+ second = (Krb5ProxyCredential) myCred;
+ tgt = second.self.getKrb5Credentials();
+ }
checkPermission(peerName.getKrb5PrincipalName().getName(),
"initiate");
@@ -607,7 +653,9 @@
GSSCaller.CALLER_UNKNOWN,
// since it's useSubjectCredsOnly here,
// don't worry about the null
- myName.getKrb5PrincipalName().getName(),
+ second == null ?
+ myName.getKrb5PrincipalName().getName():
+ second.getName().getKrb5PrincipalName().getName(),
peerName.getKrb5PrincipalName().getName(),
acc);
}});
@@ -638,9 +686,17 @@
"the subject");
}
// Get Service ticket using the Kerberos protocols
- serviceCreds = Credentials.acquireServiceCreds(
+ if (second == null) {
+ serviceCreds = Credentials.acquireServiceCreds(
peerName.getKrb5PrincipalName().getName(),
tgt);
+ } else {
+ serviceCreds = Credentials.acquireS4U2proxyCreds(
+ peerName.getKrb5PrincipalName().getName(),
+ second.tkt,
+ second.getName().getKrb5PrincipalName(),
+ tgt);
+ }
if (GSSUtil.useSubjectCredsOnly(caller)) {
final Subject subject =
AccessController.doPrivileged(
@@ -776,6 +832,7 @@
retVal = new AcceptSecContextToken(this,
token.getKrbApReq()).encode();
}
+ serviceTicket = token.getKrbApReq().getCreds().getTicket();
myCred = null;
state = STATE_DONE;
} else {
@@ -802,8 +859,6 @@
return retVal;
}
-
-
/**
* Queries the context for largest data size to accomodate
* the specified protection and be <= maxTokSize.
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Thu Nov 15 00:54:54 2012 +0000
@@ -309,8 +309,7 @@
int initLifetime)
throws GSSException {
- String realm = null;
- final String clientPrincipal, tgsPrincipal = null;
+ final String clientPrincipal;
/*
* Find the TGT for the realm that the client is in. If the client
@@ -318,20 +317,8 @@
*/
if (name != null) {
clientPrincipal = (name.getKrb5PrincipalName()).getName();
- realm = (name.getKrb5PrincipalName()).getRealmAsString();
} else {
clientPrincipal = null;
- try {
- Config config = Config.getInstance();
- realm = config.getDefaultRealm();
- } catch (KrbException e) {
- GSSException ge =
- new GSSException(GSSException.NO_CRED, -1,
- "Attempt to obtain INITIATE credentials failed!" +
- " (" + e.getMessage() + ")");
- ge.initCause(e);
- throw ge;
- }
}
final AccessControlContext acc = AccessController.getContext();
@@ -343,9 +330,11 @@
return AccessController.doPrivileged(
new PrivilegedExceptionAction<KerberosTicket>() {
public KerberosTicket run() throws Exception {
+ // It's OK to use null as serverPrincipal. TGT is almost
+ // the first ticket for a principal and we use list.
return Krb5Util.getTicket(
realCaller,
- clientPrincipal, tgsPrincipal, acc);
+ clientPrincipal, null, acc);
}});
} catch (PrivilegedActionException e) {
GSSException ge =
@@ -356,4 +345,20 @@
throw ge;
}
}
+
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ try {
+ Krb5NameElement kname = (Krb5NameElement)name;
+ Credentials newCred = Credentials.acquireS4U2selfCreds(
+ kname.getKrb5PrincipalName(), krb5Credentials);
+ return new Krb5ProxyCredential(this, kname, newCred.getTicket());
+ } catch (IOException | KrbException ke) {
+ GSSException ge =
+ new GSSException(GSSException.FAILURE, -1,
+ "Attempt to obtain S4U2self credentials failed!");
+ ge.initCause(ke);
+ throw ge;
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.jgss.krb5;
+
+import org.ietf.jgss.*;
+import sun.security.jgss.spi.*;
+import java.util.Date;
+import sun.security.krb5.internal.Ticket;
+
+/**
+ * Implements the krb5 proxy credential element used in constrained
+ * delegation. It is used in both impersonation (where there is no Kerberos 5
+ * communication between the middle server and the client) and normal
+ * constrained delegation (where there is, but client has not called
+ * requestCredDeleg(true)).
+ * @since 1.8
+ */
+
+public class Krb5ProxyCredential
+ implements Krb5CredElement {
+
+ public final Krb5InitCredential self; // the middle server
+ private final Krb5NameElement client; // the client
+
+ // The ticket with cname=client and sname=self. This can be a normal
+ // service ticket or an S4U2self ticket.
+ public final Ticket tkt;
+
+ Krb5ProxyCredential(Krb5InitCredential self, Krb5NameElement client,
+ Ticket tkt) {
+ this.self = self;
+ this.tkt = tkt;
+ this.client = client;
+ }
+
+ // The client name behind the proxy
+ @Override
+ public final Krb5NameElement getName() throws GSSException {
+ return client;
+ }
+
+ @Override
+ public int getInitLifetime() throws GSSException {
+ // endTime of tkt is not used by KDC, and it's also not
+ // available in the case of kerberos constr deleg
+ return self.getInitLifetime();
+ }
+
+ @Override
+ public int getAcceptLifetime() throws GSSException {
+ return 0;
+ }
+
+ @Override
+ public boolean isInitiatorCredential() throws GSSException {
+ return true;
+ }
+
+ @Override
+ public boolean isAcceptorCredential() throws GSSException {
+ return false;
+ }
+
+ @Override
+ public final Oid getMechanism() {
+ return Krb5MechFactory.GSS_KRB5_MECH_OID;
+ }
+
+ @Override
+ public final java.security.Provider getProvider() {
+ return Krb5MechFactory.PROVIDER;
+ }
+
+ @Override
+ public void dispose() throws GSSException {
+ try {
+ self.destroy();
+ } catch (javax.security.auth.DestroyFailedException e) {
+ GSSException gssException =
+ new GSSException(GSSException.FAILURE, -1,
+ "Could not destroy credentials - " + e.getMessage());
+ gssException.initCause(e);
+ }
+ }
+
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ // Cannot impersonate multiple levels without the impersonatee's TGT.
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Only an initiate credentials can impersonate");
+ }
+}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Thu Nov 15 00:54:54 2012 +0000
@@ -206,7 +206,7 @@
* identity, which can be:
* 1. Some KerberosKeys (generated from password)
* 2. A KeyTab (for a typical service)
- * 3. A TGT (for a user2user service. Not supported yet)
+ * 3. A TGT (for S4U2proxy extension)
*
* Note that some creds can coexist. For example, a user2user service
* can use its keytab (or keys) if the client can successfully obtain a
@@ -219,7 +219,7 @@
private List<KeyTab> ktabs;
private List<KerberosKey> kk;
private Subject subj;
- //private KerberosTicket tgt; // user2user, not supported yet
+ private KerberosTicket tgt;
private static ServiceCreds getInstance(
Subject subj, String serverPrincipal) {
@@ -255,6 +255,8 @@
subj, null, null, KeyTab.class);
sc.kk = SubjectComber.findMany(
subj, serverPrincipal, null, KerberosKey.class);
+ sc.tgt = SubjectComber.find(subj, null, null, KerberosTicket.class);
+
if (sc.ktabs.isEmpty() && sc.kk.isEmpty()) {
return null;
}
@@ -310,10 +312,22 @@
return ekeys;
}
+ public Credentials getInitCred() {
+ if (tgt == null) {
+ return null;
+ }
+ try {
+ return ticketToCreds(tgt);
+ } catch (KrbException | IOException e) {
+ return null;
+ }
+ }
+
public void destroy() {
kp = null;
ktabs = null;
kk = null;
+ tgt = null;
}
}
/**
@@ -357,7 +371,7 @@
};
public static Credentials ticketToCreds(KerberosTicket kerbTicket)
- throws KrbException, IOException {
+ throws KrbException, IOException {
return new Credentials(
kerbTicket.getEncoded(),
kerbTicket.getClient().getName(),
--- a/jdk/src/share/classes/sun/security/jgss/spi/GSSCredentialSpi.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/spi/GSSCredentialSpi.java Thu Nov 15 00:54:54 2012 +0000
@@ -96,4 +96,13 @@
* @exception GSSException may be thrown
*/
public Oid getMechanism();
+
+ /**
+ * Impersonates another client.
+ *
+ * @param name the client to impersonate
+ * @return the new credential
+ * @exception GSSException may be thrown
+ */
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException;
}
--- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java Thu Nov 15 00:54:54 2012 +0000
@@ -1059,6 +1059,9 @@
if (mechContext != null) {
GSSCredentialImpl delegCred =
(GSSCredentialImpl)mechContext.getDelegCred();
+ if (delegCred == null) {
+ return null;
+ }
// determine delegated cred element usage
boolean initiate = false;
if (delegCred.getUsage() == GSSCredential.INITIATE_ONLY) {
--- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Thu Nov 15 00:54:54 2012 +0000
@@ -88,4 +88,9 @@
public Oid getMechanism() {
return GSSUtil.GSS_SPNEGO_MECH_OID;
}
+
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ return cred.impersonate(name);
+ }
}
--- a/jdk/src/share/classes/sun/security/jgss/wrapper/GSSCredElement.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/wrapper/GSSCredElement.java Thu Nov 15 00:54:54 2012 +0000
@@ -28,6 +28,7 @@
import java.security.Provider;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.spi.GSSCredentialSpi;
+import sun.security.jgss.spi.GSSNameSpi;
/**
* This class is essentially a wrapper class for the gss_cred_id_t
@@ -132,4 +133,10 @@
protected void finalize() throws Throwable {
dispose();
}
+
+ @Override
+ public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Not supported yet");
+ }
}
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java Thu Nov 15 00:54:54 2012 +0000
@@ -449,6 +449,18 @@
return CredentialsUtil.acquireServiceCreds(service, ccreds);
}
+ public static Credentials acquireS4U2selfCreds(PrincipalName user,
+ Credentials ccreds) throws KrbException, IOException {
+ return CredentialsUtil.acquireS4U2selfCreds(user, ccreds);
+ }
+
+ public static Credentials acquireS4U2proxyCreds(String service,
+ Ticket second, PrincipalName client, Credentials ccreds)
+ throws KrbException, IOException {
+ return CredentialsUtil.acquireS4U2proxyCreds(
+ service, second, client, ccreds);
+ }
+
public CredentialsCache getCache() {
return cache;
}
@@ -490,18 +502,19 @@
public String toString() {
StringBuffer buffer = new StringBuffer("Credentials:");
- buffer.append("\nclient=").append(client);
- buffer.append("\nserver=").append(server);
+ buffer.append( "\n client=").append(client);
+ buffer.append( "\n server=").append(server);
if (authTime != null) {
- buffer.append("\nauthTime=").append(authTime);
+ buffer.append("\n authTime=").append(authTime);
}
if (startTime != null) {
- buffer.append("\nstartTime=").append(startTime);
+ buffer.append("\n startTime=").append(startTime);
}
- buffer.append("\nendTime=").append(endTime);
- buffer.append("\nrenewTill=").append(renewTill);
- buffer.append("\nflags: ").append(flags);
- buffer.append("\nEType (int): ").append(key.getEType());
+ buffer.append( "\n endTime=").append(endTime);
+ buffer.append( "\n renewTill=").append(renewTill);
+ buffer.append( "\n flags=").append(flags);
+ buffer.append( "\nEType (skey)=").append(key.getEType());
+ buffer.append( "\n (tkt key)=").append(ticket.encPart.eType);
return buffer.toString();
}
--- a/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Thu Nov 15 00:54:54 2012 +0000
@@ -160,8 +160,6 @@
kvno = key.getKeyVersionNumber();
}
*/
-
- // currently destructive on cipher
public byte[] decrypt(
EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
@@ -175,7 +173,9 @@
EType etypeEngine = EType.getInstance(eType);
plain = etypeEngine.decrypt(cipher, key.getBytes(), usage);
- cipher = null;
+ // The service ticket will be used in S4U2proxy request. Therefore
+ // the raw ticket is still needed.
+ //cipher = null;
return etypeEngine.decryptedData(plain);
}
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Thu Nov 15 00:54:54 2012 +0000
@@ -287,8 +287,9 @@
cusec = authenticator.cusec;
authenticator.ctime.setMicroSeconds(authenticator.cusec);
- if (!authenticator.cname.equals(enc_ticketPart.cname))
+ if (!authenticator.cname.equals(enc_ticketPart.cname)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
+ }
KerberosTime currTime = new KerberosTime(KerberosTime.NOW);
if (!authenticator.ctime.inClockSkew(currTime))
--- a/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java Thu Nov 15 00:54:54 2012 +0000
@@ -64,7 +64,12 @@
for (int i = 1; i < 6; i++) {
if (req.reqBody.kdcOptions.get(i) !=
- rep.encKDCRepPart.flags.get(i)) {
+ rep.encKDCRepPart.flags.get(i)) {
+ if (Krb5.DEBUG) {
+ System.out.println("> KrbKdcRep.check: at #" + i
+ + ". request for " + req.reqBody.kdcOptions.get(i)
+ + ", received " + rep.encKDCRepPart.flags.get(i));
+ }
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
}
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Thu Nov 15 00:54:54 2012 +0000
@@ -87,7 +87,7 @@
check(false, req, rep);
this.creds = new Credentials(rep.ticket,
- req.reqBody.cname,
+ rep.cname,
rep.ticket.sname,
enc_part.key,
enc_part.flags,
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java Thu Nov 15 00:54:54 2012 +0000
@@ -35,6 +35,7 @@
import sun.security.krb5.internal.crypto.*;
import java.io.IOException;
import java.net.UnknownHostException;
+import java.util.Arrays;
/**
* This class encapsulates a Kerberos TGS-REQ that is sent from the
@@ -55,7 +56,7 @@
private byte[] obuf;
private byte[] ibuf;
- // Used in CredentialsUtil
+ // Used in CredentialsUtil
public KrbTgsReq(Credentials asCreds,
PrincipalName sname)
throws KrbException, IOException {
@@ -72,6 +73,45 @@
null); // EncryptionKey subSessionKey
}
+ // S4U2proxy
+ public KrbTgsReq(Credentials asCreds,
+ Ticket second,
+ PrincipalName sname)
+ throws KrbException, IOException {
+ this(KDCOptions.with(KDCOptions.CNAME_IN_ADDL_TKT,
+ KDCOptions.FORWARDABLE),
+ asCreds,
+ sname,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ new Ticket[] {second}, // the service ticket
+ null);
+ }
+
+ // S4U2user
+ public KrbTgsReq(Credentials asCreds,
+ PrincipalName sname,
+ PAData extraPA)
+ throws KrbException, IOException {
+ this(KDCOptions.with(KDCOptions.FORWARDABLE),
+ asCreds,
+ asCreds.getClient(),
+ sname,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ extraPA); // the PA-FOR-USER
+ }
+
// Called by Credentials, KrbCred
KrbTgsReq(
KDCOptions options,
@@ -85,14 +125,42 @@
AuthorizationData authorizationData,
Ticket[] additionalTickets,
EncryptionKey subKey) throws KrbException, IOException {
+ this(options, asCreds, asCreds.getClient(), sname,
+ from, till, rtime, eTypes, addresses,
+ authorizationData, additionalTickets, subKey, null);
+ }
- princName = asCreds.client;
+ private KrbTgsReq(
+ KDCOptions options,
+ Credentials asCreds,
+ PrincipalName cname,
+ PrincipalName sname,
+ KerberosTime from,
+ KerberosTime till,
+ KerberosTime rtime,
+ int[] eTypes,
+ HostAddresses addresses,
+ AuthorizationData authorizationData,
+ Ticket[] additionalTickets,
+ EncryptionKey subKey,
+ PAData extraPA) throws KrbException, IOException {
+
+ princName = cname;
servName = sname;
ctime = new KerberosTime(KerberosTime.NOW);
// check if they are valid arguments. The optional fields
// should be consistent with settings in KDCOptions.
+
+ // TODO: Is this necessary? If the TGT is not FORWARDABLE,
+ // you can still request for a FORWARDABLE ticket, just the
+ // KDC will give you a non-FORWARDABLE one. Even if you
+ // cannot use the ticket expected, it still contains info.
+ // This means there will be problem later. We already have
+ // flags check in KrbTgsRep. Of course, sometimes the KDC
+ // will not issue the ticket at all.
+
if (options.get(KDCOptions.FORWARDABLE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
@@ -130,13 +198,13 @@
} else {
if (rtime != null) rtime = null;
}
- if (options.get(KDCOptions.ENC_TKT_IN_SKEY)) {
+ if (options.get(KDCOptions.ENC_TKT_IN_SKEY) || options.get(KDCOptions.CNAME_IN_ADDL_TKT)) {
if (additionalTickets == null)
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
// in TGS_REQ there could be more than one additional
// tickets, but in file-based credential cache,
// there is only one additional ticket field.
- secondTicket = additionalTickets[0];
+ secondTicket = additionalTickets[0];
} else {
if (additionalTickets != null)
additionalTickets = null;
@@ -156,7 +224,8 @@
addresses,
authorizationData,
additionalTickets,
- subKey);
+ subKey,
+ extraPA);
obuf = tgsReqMessg.asn1Encode();
// XXX We need to revisit this to see if can't move it
@@ -221,7 +290,8 @@
HostAddresses addresses,
AuthorizationData authorizationData,
Ticket[] additionalTickets,
- EncryptionKey subKey)
+ EncryptionKey subKey,
+ PAData extraPA)
throws Asn1Exception, IOException, KdcErrException, KrbApErrException,
UnknownHostException, KrbCryptoException {
KerberosTime req_till = null;
@@ -318,10 +388,12 @@
null,
null).getMessage();
- PAData[] tgsPAData = new PAData[1];
- tgsPAData[0] = new PAData(Krb5.PA_TGS_REQ, tgs_ap_req);
-
- return new TGSReq(tgsPAData, reqBody);
+ PAData tgsPAData = new PAData(Krb5.PA_TGS_REQ, tgs_ap_req);
+ return new TGSReq(
+ extraPA != null ?
+ new PAData[] {extraPA, tgsPAData } :
+ new PAData[] {tgsPAData},
+ reqBody);
}
TGSReq getMessage() {
--- a/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java Thu Nov 15 00:54:54 2012 +0000
@@ -32,17 +32,7 @@
package sun.security.krb5.internal;
import sun.security.krb5.*;
-import sun.security.krb5.internal.ccache.CredentialsCache;
-import java.util.StringTokenizer;
-import sun.security.krb5.internal.ktab.*;
-import java.io.File;
import java.io.IOException;
-import java.util.Date;
-import java.util.Vector;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
/**
* This class is a utility that contains much of the TGS-Exchange
@@ -53,77 +43,158 @@
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
- /**
- * Acquires credentials for a specified service using initial credential. Wh
-en the service has a different realm
- * from the initial credential, we do cross-realm authentication - first, we
- use the current credential to get
- * a cross-realm credential from the local KDC, then use that cross-realm cr
-edential to request service credential
- * from the foreigh KDC.
- *
- * @param service the name of service principal using format components@real
-m
- * @param ccreds client's initial credential.
- * @exception Exception general exception will be thrown when any error occu
-rs.
- * @return a <code>Credentials</code> object.
- */
+ /**
+ * Used by a middle server to acquire credentials on behalf of a
+ * client to itself using the S4U2self extension.
+ * @param client the client to impersonate
+ * @param ccreds the TGT of the middle service
+ * @return the new creds (cname=client, sname=middle)
+ */
+ public static Credentials acquireS4U2selfCreds(PrincipalName client,
+ Credentials ccreds) throws KrbException, IOException {
+ String uRealm = client.getRealmString();
+ String localRealm = ccreds.getClient().getRealmString();
+ if (!uRealm.equals(localRealm)) {
+ // TODO: we do not support kerberos referral now
+ throw new KrbException("Cross realm impersonation not supported");
+ }
+ KrbTgsReq req = new KrbTgsReq(
+ ccreds,
+ ccreds.getClient(),
+ new PAData(Krb5.PA_FOR_USER,
+ new PAForUserEnc(client,
+ ccreds.getSessionKey()).asn1Encode()));
+ Credentials creds = req.sendAndGetCreds();
+ if (!creds.getClient().equals(client)) {
+ throw new KrbException("S4U2self request not honored by KDC");
+ }
+ return creds;
+ }
+
+ /**
+ * Used by a middle server to acquire a service ticket to a backend
+ * server using the S4U2proxy extension.
+ * @param backend the name of the backend service
+ * @param second the client's service ticket to the middle server
+ * @param ccreds the TGT of the middle server
+ * @return the creds (cname=client, sname=backend)
+ */
+ public static Credentials acquireS4U2proxyCreds(
+ String backend, Ticket second,
+ PrincipalName client, Credentials ccreds)
+ throws KrbException, IOException {
+ KrbTgsReq req = new KrbTgsReq(
+ ccreds,
+ second,
+ new PrincipalName(backend));
+ Credentials creds = req.sendAndGetCreds();
+ if (!creds.getClient().equals(client)) {
+ throw new KrbException("S4U2proxy request not honored by KDC");
+ }
+ return creds;
+ }
+
+ /**
+ * Acquires credentials for a specified service using initial
+ * credential. When the service has a different realm from the initial
+ * credential, we do cross-realm authentication - first, we use the
+ * current credential to get a cross-realm credential from the local KDC,
+ * then use that cross-realm credential to request service credential
+ * from the foreign KDC.
+ *
+ * @param service the name of service principal
+ * @param ccreds client's initial credential
+ */
public static Credentials acquireServiceCreds(
String service, Credentials ccreds)
- throws KrbException, IOException {
+ throws KrbException, IOException {
PrincipalName sname = new PrincipalName(service);
String serviceRealm = sname.getRealmString();
String localRealm = ccreds.getClient().getRealmString();
- /*
- if (!localRealm.equalsIgnoreCase(serviceRealm)) { //do cross-realm auth entication
- if (DEBUG) {
- System.out.println(">>>DEBUG: Credentails request cross realm ticket for " + "krbtgt/" + serviceRealm + "@" + localRealm);
- }
- Credentials crossCreds = serviceCreds(new ServiceName("krbtgt/" + serviceRealm + "@" + localRealm), ccreds);
- if (DEBUG) {
- printDebug(crossCreds);
- }
- Credentials result = serviceCreds(sname, crossCreds);
- if (DEBUG) {
- printDebug(result);
- }
- return result;
- }
- else return serviceCreds(sname, ccreds);
- */
-
- if (localRealm.equals(serviceRealm))
- {
- if (DEBUG)
- System.out.println(">>> Credentials acquireServiceCreds: same realm");
+ if (localRealm.equals(serviceRealm)) {
+ if (DEBUG) {
+ System.out.println(
+ ">>> Credentials acquireServiceCreds: same realm");
+ }
return serviceCreds(sname, ccreds);
}
+ Credentials theCreds = null;
+
+ boolean[] okAsDelegate = new boolean[1];
+ Credentials theTgt = getTGTforRealm(localRealm, serviceRealm,
+ ccreds, okAsDelegate);
+ if (theTgt != null) {
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "got right tgt");
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "obtaining service creds for " + sname);
+ }
+
+ try {
+ theCreds = serviceCreds(sname, theTgt);
+ } catch (Exception exc) {
+ if (DEBUG) {
+ System.out.println(exc);
+ }
+ theCreds = null;
+ }
+ }
+
+ if (theCreds != null) {
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "returning creds:");
+ Credentials.printDebug(theCreds);
+ }
+ if (!okAsDelegate[0]) {
+ theCreds.resetDelegate();
+ }
+ return theCreds;
+ }
+ throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED,
+ "No service creds");
+ }
+
+ /**
+ * Gets a TGT to another realm
+ * @param localRealm this realm
+ * @param serviceRealm the other realm
+ * @param ccreds TGT in this realm
+ * @param okAsDelegate an [out] argument to receive the okAsDelegate
+ * property. True only if all realms allow delegation.
+ * @return the TGT for the other realm, null if cannot find a path
+ * @throws KrbException if something goes wrong
+ */
+ private static Credentials getTGTforRealm(String localRealm,
+ String serviceRealm, Credentials ccreds, boolean[] okAsDelegate)
+ throws KrbException {
// Get a list of realms to traverse
String[] realms = Realm.getRealmsList(localRealm, serviceRealm);
- boolean okAsDelegate = true;
- if (realms == null || realms.length == 0)
- {
- if (DEBUG)
- System.out.println(">>> Credentials acquireServiceCreds: no realms list");
+ if (realms == null || realms.length == 0) {
+ if (DEBUG) {
+ System.out.println(
+ ">>> Credentials acquireServiceCreds: no realms list");
+ }
return null;
}
int i = 0, k = 0;
Credentials cTgt = null, newTgt = null, theTgt = null;
PrincipalName tempService = null;
- String realm = null, newTgtRealm = null, theTgtRealm = null;
+ String newTgtRealm = null;
- for (cTgt = ccreds, i = 0; i < realms.length;)
- {
+ okAsDelegate[0] = true;
+ for (cTgt = ccreds, i = 0; i < realms.length;) {
tempService = PrincipalName.tgsService(serviceRealm, realms[i]);
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: main loop: [" + i +"] tempService=" + tempService);
+ if (DEBUG) {
+ System.out.println(
+ ">>> Credentials acquireServiceCreds: main loop: ["
+ + i +"] tempService=" + tempService);
}
try {
@@ -132,11 +203,10 @@
newTgt = null;
}
- if (newTgt == null)
- {
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: no tgt; searching backwards");
+ if (newTgt == null) {
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "no tgt; searching backwards");
}
/*
@@ -144,17 +214,15 @@
* realm as close to the target as possible.
* That means traversing the realms list backwards.
*/
-
for (newTgt = null, k = realms.length - 1;
- newTgt == null && k > i; k--)
- {
-
+ newTgt == null && k > i; k--) {
tempService = PrincipalName.tgsService(realms[k], realms[i]);
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: inner loop: [" + k +"] tempService=" + tempService);
+ if (DEBUG) {
+ System.out.println(
+ ">>> Credentials acquireServiceCreds: "
+ + "inner loop: [" + k
+ + "] tempService=" + tempService);
}
-
try {
newTgt = serviceCreds(tempService, cTgt);
} catch (Exception exc) {
@@ -163,11 +231,10 @@
}
} // Ends 'if (newTgt == null)'
- if (newTgt == null)
- {
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: no tgt; cannot get creds");
+ if (newTgt == null) {
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "no tgt; cannot get creds");
}
break;
}
@@ -176,29 +243,24 @@
* We have a tgt. It may or may not be for the target.
* If it's for the target realm, we're done looking for a tgt.
*/
-
newTgtRealm = newTgt.getServer().getInstanceComponent();
- if (okAsDelegate && !newTgt.checkDelegate()) {
- if (DEBUG)
- {
+ if (okAsDelegate[0] && !newTgt.checkDelegate()) {
+ if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: " +
"global OK-AS-DELEGATE turned off at " +
newTgt.getServer());
}
- okAsDelegate = false;
+ okAsDelegate[0] = false;
}
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: got tgt");
- //printDebug(newTgt);
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "got tgt");
}
- if (newTgtRealm.equals(serviceRealm))
- {
+ if (newTgtRealm.equals(serviceRealm)) {
/* We got the right tgt */
theTgt = newTgt;
- theTgtRealm = newTgtRealm;
break;
}
@@ -207,17 +269,13 @@
* See if the realm of the new tgt is in the list of realms
* and continue looking from there.
*/
-
- for (k = i+1; k < realms.length; k++)
- {
- if (newTgtRealm.equals(realms[k]))
- {
+ for (k = i+1; k < realms.length; k++) {
+ if (newTgtRealm.equals(realms[k])) {
break;
}
}
- if (k < realms.length)
- {
+ if (k < realms.length) {
/*
* (re)set the counter so we start looking
* from the realm we just obtained a tgt for.
@@ -225,64 +283,24 @@
i = k;
cTgt = newTgt;
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: continuing with main loop counter reset to " + i);
+ if (DEBUG) {
+ System.out.println(">>> Credentials acquireServiceCreds: "
+ + "continuing with main loop counter reset to " + i);
}
-
continue;
}
- else
- {
+ else {
/*
* The new tgt's realm is not in the heirarchy of realms.
* It's probably not safe to get a tgt from
* a tgs that is outside the known list of realms.
* Give up now.
*/
-
break;
}
} // Ends outermost/main 'for' loop
- Credentials theCreds = null;
-
- if (theTgt != null)
- {
- /* We have the right tgt. Let's get the service creds */
-
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: got right tgt");
-
- //printDebug(theTgt);
-
- System.out.println(">>> Credentials acquireServiceCreds: obtaining service creds for " + sname);
- }
-
- try {
- theCreds = serviceCreds(sname, theTgt);
- } catch (Exception exc) {
- if (DEBUG)
- System.out.println(exc);
- theCreds = null;
- }
- }
-
- if (theCreds != null)
- {
- if (DEBUG)
- {
- System.out.println(">>> Credentials acquireServiceCreds: returning creds:");
- Credentials.printDebug(theCreds);
- }
- if (!okAsDelegate) {
- theCreds.resetDelegate();
- }
- return theCreds;
- }
- throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED,
- "No service creds");
+ return theTgt;
}
/*
--- a/jdk/src/share/classes/sun/security/krb5/internal/EncKDCRepPart.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/EncKDCRepPart.java Thu Nov 15 00:54:54 2012 +0000
@@ -160,9 +160,10 @@
if (der.getData().available() > 0) {
caddr = HostAddresses.parse(der.getData(), (byte) 0x0B, true);
}
- if (der.getData().available() > 0) {
+ // We observe extra data from MSAD
+ /*if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
- }
+ }*/
}
/**
--- a/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java Thu Nov 15 00:54:54 2012 +0000
@@ -139,13 +139,45 @@
public static final int UNUSED9 = 9;
public static final int UNUSED10 = 10;
public static final int UNUSED11 = 11;
+ public static final int CNAME_IN_ADDL_TKT = 14;
public static final int RENEWABLE_OK = 27;
public static final int ENC_TKT_IN_SKEY = 28;
public static final int RENEW = 30;
public static final int VALIDATE = 31;
+ private static final String[] names = {
+ "RESERVED", //0
+ "FORWARDABLE", //1;
+ "FORWARDED", //2;
+ "PROXIABLE", //3;
+ "PROXY", //4;
+ "ALLOW_POSTDATE", //5;
+ "POSTDATED", //6;
+ "UNUSED7", //7;
+ "RENEWABLE", //8;
+ "UNUSED9", //9;
+ "UNUSED10", //10;
+ "UNUSED11", //11;
+ null,null,
+ "CNAME_IN_ADDL_TKT",//14;
+ null,null,null,null,null,null,null,null,null,null,null,null,
+ "RENEWABLE_OK", //27;
+ "ENC_TKT_IN_SKEY", //28;
+ null,
+ "RENEW", //30;
+ "VALIDATE", //31;
+ };
+
private boolean DEBUG = Krb5.DEBUG;
+ public static KDCOptions with(int... flags) {
+ KDCOptions options = new KDCOptions();
+ for (int flag: flags) {
+ options.set(flag, true);
+ }
+ return options;
+ }
+
public KDCOptions() {
super(Krb5.KDC_OPTS_MAX + 1);
setDefault();
@@ -238,6 +270,20 @@
return super.get(option);
}
+ @Override public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("KDCOptions: ");
+ for (int i=0; i<Krb5.KDC_OPTS_MAX+1; i++) {
+ if (get(i)) {
+ if (names[i] != null) {
+ sb.append(names[i]).append(",");
+ } else {
+ sb.append(i).append(",");
+ }
+ }
+ }
+ return sb.toString();
+ }
private void setDefault() {
try {
--- a/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java Thu Nov 15 00:54:54 2012 +0000
@@ -158,6 +158,9 @@
public static final int PA_ETYPE_INFO = 11;
public static final int PA_ETYPE_INFO2 = 19;
+ // S4U2user info
+ public static final int PA_FOR_USER = 129;
+
//-------------------------------+-------------
//authorization data type |ad-type value
//-------------------------------+-------------
--- a/jdk/src/share/classes/sun/security/krb5/internal/PAData.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/PAData.java Thu Nov 15 00:54:54 2012 +0000
@@ -312,6 +312,9 @@
}
}
break;
+ case Krb5.PA_FOR_USER:
+ sb.append("\t PA-FOR-USER\n");
+ break;
default:
// Unknown Pre-auth type
break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/krb5/internal/PAForUserEnc.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.krb5.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import sun.security.krb5.*;
+import sun.security.krb5.internal.crypto.KeyUsage;
+import sun.security.krb5.internal.util.KerberosString;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+
+/**
+ * Implements the ASN.1 PA-FOR-USER type.
+ *
+ * <xmp>
+ * padata-type ::= PA-FOR-USER
+ * -- value 129
+ * padata-value ::= EncryptedData
+ * -- PA-FOR-USER-ENC
+ * PA-FOR-USER-ENC ::= SEQUENCE {
+ * userName[0] PrincipalName,
+ * userRealm[1] Realm,
+ * cksum[2] Checksum,
+ * auth-package[3] KerberosString
+ * }
+ * </xmp>
+ *
+ * <p>
+ * This definition reflects MS-SFU.
+ */
+
+public class PAForUserEnc {
+ final public PrincipalName name;
+ final private EncryptionKey key;
+ final public static String AUTH_PACKAGE = "Kerberos";
+
+ public PAForUserEnc(PrincipalName name, EncryptionKey key) {
+ this.name = name;
+ this.key = key;
+ }
+
+ /**
+ * Constructs a PA-FOR-USER object from a DER encoding.
+ * @param encoding the input object
+ * @param key the key to verify the checksum inside encoding
+ * @throws KrbException if the verification fails.
+ * Note: this method is now only used by test KDC, therefore
+ * the verification is ignored (at the moment).
+ */
+ public PAForUserEnc(DerValue encoding, EncryptionKey key)
+ throws Asn1Exception, KrbException, IOException {
+ DerValue der = null;
+ this.key = key;
+
+ if (encoding.getTag() != DerValue.tag_Sequence) {
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+
+ // Realm after name? Quite abnormal.
+ PrincipalName tmpName = null;
+ der = encoding.getData().getDerValue();
+ if ((der.getTag() & 0x1F) == 0x00) {
+ try {
+ tmpName = new PrincipalName(der.getData().getDerValue(),
+ new Realm("PLACEHOLDER"));
+ } catch (RealmException re) {
+ // Impossible
+ }
+ } else {
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+
+ der = encoding.getData().getDerValue();
+ if ((der.getTag() & 0x1F) == 0x01) {
+ try {
+ Realm realm = new Realm(der.getData().getDerValue());
+ name = new PrincipalName(
+ tmpName.getNameType(), tmpName.getNameStrings(), realm);
+ } catch (RealmException re) {
+ throw new IOException(re);
+ }
+ } else {
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+
+ der = encoding.getData().getDerValue();
+ if ((der.getTag() & 0x1F) == 0x02) {
+ // Deal with the checksum
+ } else {
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+
+ der = encoding.getData().getDerValue();
+ if ((der.getTag() & 0x1F) == 0x03) {
+ String authPackage = new KerberosString(der.getData().getDerValue()).toString();
+ if (!authPackage.equalsIgnoreCase(AUTH_PACKAGE)) {
+ throw new IOException("Incorrect auth-package");
+ }
+ } else {
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+ if (encoding.getData().available() > 0)
+ throw new Asn1Exception(Krb5.ASN1_BAD_ID);
+ }
+
+ public byte[] asn1Encode() throws Asn1Exception, IOException {
+ DerOutputStream bytes = new DerOutputStream();
+ bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), name.asn1Encode());
+ bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), name.getRealm().asn1Encode());
+
+ try {
+ Checksum cks = new Checksum(
+ Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR,
+ getS4UByteArray(),
+ key,
+ KeyUsage.KU_PA_FOR_USER_ENC_CKSUM);
+ bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), cks.asn1Encode());
+ } catch (KrbException ke) {
+ throw new IOException(ke);
+ }
+
+ DerOutputStream temp = new DerOutputStream();
+ temp.putDerValue(new KerberosString(AUTH_PACKAGE).toDerValue());
+ bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp);
+
+ temp = new DerOutputStream();
+ temp.write(DerValue.tag_Sequence, bytes);
+ return temp.toByteArray();
+ }
+
+ /**
+ * Returns S4UByteArray, the block to calculate checksum inside a
+ * PA-FOR-USER-ENC data structure. It includes:
+ * 1. userName.name-type encoded as a 4-byte integer in little endian
+ * byte order
+ * 2. all string values in the sequence of strings contained in the
+ * userName.name-string field
+ * 3. the string value of the userRealm field
+ * 4. the string value of auth-package field
+ */
+ public byte[] getS4UByteArray() {
+ try {
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ ba.write(new byte[4]);
+ for (String s: name.getNameStrings()) {
+ ba.write(s.getBytes("UTF-8"));
+ }
+ ba.write(name.getRealm().toString().getBytes("UTF-8"));
+ ba.write(AUTH_PACKAGE.getBytes("UTF-8"));
+ byte[] output = ba.toByteArray();
+ int pnType = name.getNameType();
+ output[0] = (byte)(pnType & 0xff);
+ output[1] = (byte)((pnType>>8) & 0xff);
+ output[2] = (byte)((pnType>>16) & 0xff);
+ output[3] = (byte)((pnType>>24) & 0xff);
+ return output;
+ } catch (IOException ioe) {
+ // not possible
+ throw new AssertionError("Cannot write ByteArrayOutputStream", ioe);
+ }
+ }
+
+ public String toString() {
+ return "PA-FOR-USER: " + name;
+ }
+}
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java Thu Nov 15 00:54:54 2012 +0000
@@ -54,6 +54,7 @@
public static final int KU_ENC_KRB_PRIV_PART = 13; // KrbPriv
public static final int KU_ENC_KRB_CRED_PART = 14; // KrbCred
public static final int KU_KRB_SAFE_CKSUM = 15; // KrbSafe
+ public static final int KU_PA_FOR_USER_ENC_CKSUM = 17; // S4U2user
public static final int KU_AD_KDC_ISSUED_CKSUM = 19;
public static final boolean isValid(int usage) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Thu Nov 15 00:54:54 2012 +0000
@@ -279,6 +279,9 @@
EncryptionKey key;
int size = entries.size();
ArrayList<EncryptionKey> keys = new ArrayList<>(size);
+ if (DEBUG) {
+ System.out.println("Looking for keys for: " + service);
+ }
for (int i = size-1; i >= 0; i--) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java Thu Nov 15 00:54:54 2012 +0000
@@ -39,7 +39,6 @@
import sun.security.timestamp.*;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
-import sun.security.x509.CertificateIssuerName;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509CRLImpl;
@@ -712,8 +711,8 @@
X509CertInfo tbsCert =
new X509CertInfo(cert.getTBSCertificate());
certIssuerName = (Principal)
- tbsCert.get(CertificateIssuerName.NAME + "." +
- CertificateIssuerName.DN_NAME);
+ tbsCert.get(X509CertInfo.ISSUER + "." +
+ X509CertInfo.DN_NAME);
} catch (Exception e) {
// error generating X500Name object from the cert's
// issuer DN, leave name as is.
--- a/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java Thu Nov 15 00:54:54 2012 +0000
@@ -67,7 +67,7 @@
private URI responderURI;
private X509Certificate responderCert;
private List<CertStore> certStores;
- private Map<X509Certificate, byte[]> ocspStapled;
+ private Map<X509Certificate, byte[]> ocspResponses;
private List<Extension> ocspExtensions;
private boolean legacy;
@@ -140,7 +140,7 @@
} else {
crlDP = true;
}
- ocspStapled = getOCSPStapledResponses();
+ ocspResponses = getOCSPResponses();
ocspExtensions = getOCSPExtensions();
this.anchor = anchor;
@@ -645,11 +645,11 @@
try {
certId = new CertId(issuerCert, currCert.getSerialNumberObject());
- // check if there is a stapled OCSP response available
- byte[] responseBytes = ocspStapled.get(cert);
+ // check if there is a cached OCSP response available
+ byte[] responseBytes = ocspResponses.get(cert);
if (responseBytes != null) {
if (debug != null) {
- debug.println("Found stapled OCSP response");
+ debug.println("Found cached OCSP response");
}
response = new OCSPResponse(responseBytes);
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Thu Nov 15 00:54:54 2012 +0000
@@ -2259,9 +2259,9 @@
X509CertInfo tbsCert = new
X509CertInfo(certChain[0].getTBSCertificate());
issuerName = (Principal)
- tbsCert.get(CertificateIssuerName.NAME + "." +
- CertificateIssuerName.DN_NAME);
- }
+ tbsCert.get(X509CertInfo.ISSUER + "." +
+ X509CertInfo.DN_NAME);
+ }
BigInteger serial = certChain[0].getSerialNumber();
String signatureAlgorithm;
--- a/jdk/src/share/classes/sun/security/tools/keytool/CertAndKeyGen.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/tools/keytool/CertAndKeyGen.java Thu Nov 15 00:54:54 2012 +0000
@@ -258,10 +258,10 @@
AlgorithmId algID = AlgorithmId.get(sigAlg);
info.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(algID));
- info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname));
+ info.set(X509CertInfo.SUBJECT, myname);
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
info.set(X509CertInfo.VALIDITY, interval);
- info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
+ info.set(X509CertInfo.ISSUER, myname);
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
cert = new X509CertImpl(info);
--- a/jdk/src/share/classes/sun/security/tools/keytool/Main.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/tools/keytool/Main.java Thu Nov 15 00:54:54 2012 +0000
@@ -1145,7 +1145,7 @@
X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
X509CertImpl.NAME + "." + X509CertImpl.INFO);
X500Name issuer = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
- CertificateSubjectName.DN_NAME);
+ X509CertInfo.DN_NAME);
Date firstDate = getStartDate(startDate);
Date lastDate = new Date();
@@ -1170,7 +1170,7 @@
info.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(
AlgorithmId.get(sigAlgName)));
- info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuer));
+ info.set(X509CertInfo.ISSUER, issuer);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
boolean canRead = false;
@@ -1193,8 +1193,8 @@
PKCS10 req = new PKCS10(rawReq);
info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo()));
- info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(
- dname==null?req.getSubjectName():new X500Name(dname)));
+ info.set(X509CertInfo.SUBJECT,
+ dname==null?req.getSubjectName():new X500Name(dname));
CertificateExtensions reqex = null;
Iterator<PKCS10Attribute> attrs = req.getAttributes().getAttributes().iterator();
while (attrs.hasNext()) {
@@ -1234,7 +1234,7 @@
X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
X509CertImpl.NAME + "." + X509CertImpl.INFO);
X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
- CertificateSubjectName.DN_NAME);
+ X509CertInfo.DN_NAME);
Date firstDate = getStartDate(startDate);
Date lastDate = (Date) firstDate.clone();
@@ -2405,16 +2405,16 @@
if (dname == null) {
// Get the owner name from the certificate
owner = (X500Name)certInfo.get(X509CertInfo.SUBJECT + "." +
- CertificateSubjectName.DN_NAME);
+ X509CertInfo.DN_NAME);
} else {
// Use the owner name specified at the command line
owner = new X500Name(dname);
certInfo.set(X509CertInfo.SUBJECT + "." +
- CertificateSubjectName.DN_NAME, owner);
+ X509CertInfo.DN_NAME, owner);
}
// Make issuer same as owner (self-signed!)
certInfo.set(X509CertInfo.ISSUER + "." +
- CertificateIssuerName.DN_NAME, owner);
+ X509CertInfo.DN_NAME, owner);
// The inner and outer signature algorithms have to match.
// The way we achieve that is really ugly, but there seems to be no
--- a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java Thu Nov 15 00:54:54 2012 +0000
@@ -96,12 +96,10 @@
*/
// x509.info.subject.dname
public static final String SUBJECT_DN = NAME + DOT + INFO + DOT +
- X509CertInfo.SUBJECT + DOT +
- CertificateSubjectName.DN_NAME;
+ X509CertInfo.SUBJECT + DOT + X509CertInfo.DN_NAME;
// x509.info.issuer.dname
public static final String ISSUER_DN = NAME + DOT + INFO + DOT +
- X509CertInfo.ISSUER + DOT +
- CertificateIssuerName.DN_NAME;
+ X509CertInfo.ISSUER + DOT + X509CertInfo.DN_NAME;
// x509.info.serialNumber.number
public static final String SERIAL_ID = NAME + DOT + INFO + DOT +
X509CertInfo.SERIAL_NUMBER + DOT +
@@ -890,9 +888,8 @@
if (info == null)
return null;
try {
- Principal subject = (Principal)info.get(
- CertificateSubjectName.NAME + DOT +
- CertificateSubjectName.DN_NAME);
+ Principal subject = (Principal)info.get(X509CertInfo.SUBJECT + DOT +
+ X509CertInfo.DN_NAME);
return subject;
} catch (Exception e) {
return null;
@@ -910,8 +907,8 @@
}
try {
X500Principal subject = (X500Principal)info.get(
- CertificateSubjectName.NAME + DOT +
- CertificateSubjectName.DN_PRINCIPAL);
+ X509CertInfo.SUBJECT + DOT +
+ "x500principal");
return subject;
} catch (Exception e) {
return null;
@@ -927,9 +924,8 @@
if (info == null)
return null;
try {
- Principal issuer = (Principal)info.get(
- CertificateIssuerName.NAME + DOT +
- CertificateIssuerName.DN_NAME);
+ Principal issuer = (Principal)info.get(X509CertInfo.ISSUER + DOT +
+ X509CertInfo.DN_NAME);
return issuer;
} catch (Exception e) {
return null;
@@ -947,8 +943,8 @@
}
try {
X500Principal issuer = (X500Principal)info.get(
- CertificateIssuerName.NAME + DOT +
- CertificateIssuerName.DN_PRINCIPAL);
+ X509CertInfo.ISSUER + DOT +
+ "x500principal");
return issuer;
} catch (Exception e) {
return null;
--- a/jdk/src/share/classes/sun/security/x509/X509CertInfo.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/x509/X509CertInfo.java Thu Nov 15 00:54:54 2012 +0000
@@ -68,12 +68,13 @@
public static final String IDENT = "x509.info";
// Certificate attribute names
public static final String NAME = "info";
+ public static final String DN_NAME = "dname";
public static final String VERSION = CertificateVersion.NAME;
public static final String SERIAL_NUMBER = CertificateSerialNumber.NAME;
public static final String ALGORITHM_ID = CertificateAlgorithmId.NAME;
- public static final String ISSUER = CertificateIssuerName.NAME;
+ public static final String ISSUER = "issuer";
+ public static final String SUBJECT = "subject";
public static final String VALIDITY = CertificateValidity.NAME;
- public static final String SUBJECT = CertificateSubjectName.NAME;
public static final String KEY = CertificateX509Key.NAME;
public static final String ISSUER_ID = "issuerID";
public static final String SUBJECT_ID = "subjectID";
@@ -83,9 +84,9 @@
protected CertificateVersion version = new CertificateVersion();
protected CertificateSerialNumber serialNum = null;
protected CertificateAlgorithmId algId = null;
- protected CertificateIssuerName issuer = null;
+ protected X500Name issuer = null;
+ protected X500Name subject = null;
protected CertificateValidity interval = null;
- protected CertificateSubjectName subject = null;
protected CertificateX509Key pubKey = null;
// X509.v2 & v3 extensions
@@ -399,11 +400,7 @@
break;
case ATTR_ISSUER:
- if (suffix == null) {
- setIssuer(val);
- } else {
- issuer.set(suffix, val);
- }
+ setIssuer(val);
break;
case ATTR_VALIDITY:
@@ -415,11 +412,7 @@
break;
case ATTR_SUBJECT:
- if (suffix == null) {
- setSubject(val);
- } else {
- subject.set(suffix, val);
- }
+ setSubject(val);
break;
case ATTR_KEY:
@@ -493,11 +486,7 @@
}
break;
case (ATTR_ISSUER):
- if (suffix == null) {
- issuer = null;
- } else {
- issuer.delete(suffix);
- }
+ issuer = null;
break;
case (ATTR_VALIDITY):
if (suffix == null) {
@@ -507,11 +496,7 @@
}
break;
case (ATTR_SUBJECT):
- if (suffix == null) {
- subject = null;
- } else {
- subject.delete(suffix);
- }
+ subject = null;
break;
case (ATTR_KEY):
if (suffix == null) {
@@ -571,13 +556,13 @@
if (suffix == null) {
return(subject);
} else {
- return(subject.get(suffix));
+ return(getX500Name(suffix, false));
}
case (ATTR_ISSUER):
if (suffix == null) {
return(issuer);
} else {
- return(issuer.get(suffix));
+ return(getX500Name(suffix, true));
}
case (ATTR_KEY):
if (suffix == null) {
@@ -618,6 +603,21 @@
}
/*
+ * Get the Issuer or Subject name
+ */
+ private Object getX500Name(String name, boolean getIssuer)
+ throws IOException {
+ if (name.equalsIgnoreCase(X509CertInfo.DN_NAME)) {
+ return getIssuer ? issuer : subject;
+ } else if (name.equalsIgnoreCase("x500principal")) {
+ return getIssuer ? issuer.asX500Principal()
+ : subject.asX500Principal();
+ } else {
+ throw new IOException("Attribute name not recognized.");
+ }
+ }
+
+ /*
* This routine unmarshals the certificate information.
*/
private void parse(DerValue val)
@@ -646,9 +646,8 @@
algId = new CertificateAlgorithmId(in);
// Issuer name
- issuer = new CertificateIssuerName(in);
- X500Name issuerDN = (X500Name)issuer.get(CertificateIssuerName.DN_NAME);
- if (issuerDN.isEmpty()) {
+ issuer = new X500Name(in);
+ if (issuer.isEmpty()) {
throw new CertificateParsingException(
"Empty issuer DN not allowed in X509Certificates");
}
@@ -657,10 +656,9 @@
interval = new CertificateValidity(in);
// subject name
- subject = new CertificateSubjectName(in);
- X500Name subjectDN = (X500Name)subject.get(CertificateSubjectName.DN_NAME);
+ subject = new X500Name(in);
if ((version.compare(CertificateVersion.V1) == 0) &&
- subjectDN.isEmpty()) {
+ subject.isEmpty()) {
throw new CertificateParsingException(
"Empty subject DN not allowed in v1 certificate");
}
@@ -712,13 +710,12 @@
/*
* Verify if X.509 V3 Certificate is compliant with RFC 3280.
*/
- private void verifyCert(CertificateSubjectName subject,
+ private void verifyCert(X500Name subject,
CertificateExtensions extensions)
throws CertificateParsingException, IOException {
// if SubjectName is empty, check for SubjectAlternativeNameExtension
- X500Name subjectDN = (X500Name)subject.get(CertificateSubjectName.DN_NAME);
- if (subjectDN.isEmpty()) {
+ if (subject.isEmpty()) {
if (extensions == null) {
throw new CertificateParsingException("X.509 Certificate is " +
"incomplete: subject field is empty, and certificate " +
@@ -859,11 +856,11 @@
* @exception CertificateException on invalid data.
*/
private void setIssuer(Object val) throws CertificateException {
- if (!(val instanceof CertificateIssuerName)) {
+ if (!(val instanceof X500Name)) {
throw new CertificateException(
"Issuer class type invalid.");
}
- issuer = (CertificateIssuerName)val;
+ issuer = (X500Name)val;
}
/**
@@ -887,11 +884,11 @@
* @exception CertificateException on invalid data.
*/
private void setSubject(Object val) throws CertificateException {
- if (!(val instanceof CertificateSubjectName)) {
+ if (!(val instanceof X500Name)) {
throw new CertificateException(
"Subject class type invalid.");
}
- subject = (CertificateSubjectName)val;
+ subject = (X500Name)val;
}
/**
--- a/jdk/src/share/classes/sun/security/x509/certAttributes.html Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/security/x509/certAttributes.html Thu Nov 15 00:54:54 2012 +0000
@@ -6,7 +6,7 @@
<h2><center>Certificate Attributes</center></h2>
<font size=3><center>July 1998</font></center>
<p>
-In JDK1.2 we provide an implementation of X.509 (version 3).
+In JDK1.2 we provide an implementation of X.509 (version 3).
The X509CertImpl class supports the following methods to
manipulate the various attributes of a certificate:
<pre>
@@ -86,9 +86,9 @@
<td>issuer</td>
<td>x509.info.issuer<br>
x509.info.issuer.dname</td>
-<td>CertificateIssuerName.IDENT<br>
+<td>none<br>
X509CertImpl.ISSUER_DN</td>
-<td>CertificateIssuerName<br>
+<td>X500Name<br>
X500Name</td>
</tr>
<tr>
@@ -109,9 +109,9 @@
<td>subject</td>
<td>x509.info.subject<br>
x509.info.subject.dname</td>
-<td>CertificateSubjectName.IDENT<br>
+<td>none<br>
X509CertImpl.SUBJECT_DN</td>
-<td>CertificateSubjectName<br>
+<td>X500Name<br>
X500Name</td>
</tr>
<tr>
@@ -127,18 +127,18 @@
<td>issuerUniqueID</td>
<td>x509.info.issuerID<br>
x509.info.issuerID.id</td>
-<td>CertificateIssuerUniqueIdentity.IDENT<br>
+<td>none<br>
none</td>
-<td>CertificateIssuerUniqueIdentity<br>
+<td>UniqueIdentity<br>
UniqueIdentity</td>
</tr>
<tr>
<td>subjectUniqueID</td>
<td>x509.info.subjectID<br>
x509.info.subjectID.id</td>
-<td>CertificateSubjectUniqueIdentity.IDENT<br>
+<td>none<br>
none</td>
-<td>CertificateSubjectUniqueIdentity<br>
+<td>UniqueIdentity<br>
UniqueIdentity</td>
</tr>
<tr>
--- a/jdk/src/share/classes/sun/tools/java/RuntimeConstants.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/tools/java/RuntimeConstants.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. 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
@@ -67,7 +67,7 @@
/* Class File Constants */
int JAVA_MAGIC = 0xcafebabe;
int JAVA_MIN_SUPPORTED_VERSION = 45;
- int JAVA_MAX_SUPPORTED_VERSION = 51;
+ int JAVA_MAX_SUPPORTED_VERSION = 52;
int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0;
/* Generate class file version for 1.1 by default */
--- a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Thu Nov 15 00:54:54 2012 +0000
@@ -329,9 +329,6 @@
tagset.add(token);
}
- // ensure en-US is there (mandated by the spec, e.g. Collator.getAvailableLocales())
- tagset.add("en-US");
-
return tagset;
}
--- a/jdk/src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Thu Nov 15 00:54:54 2012 +0000
@@ -26,6 +26,7 @@
package sun.util.locale.provider;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.IllformedLocaleException;
@@ -177,7 +178,7 @@
for (Class<? extends LocaleServiceProvider> c : spiClasses) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(c);
- all.addAll(pool.getAvailableLocaleList());
+ all.addAll(pool.getAvailableLocaleSet());
}
allAvailableLocales = all.toArray(new Locale[0]);
@@ -207,13 +208,23 @@
* @return an array of the available locales
*/
public Locale[] getAvailableLocales() {
- Set<Locale> locList = getAvailableLocaleList();
+ Set<Locale> locList = new HashSet<>();
+ locList.addAll(getAvailableLocaleSet());
+ // Make sure it all contains JRE's locales for compatibility.
+ locList.addAll(Arrays.asList(LocaleProviderAdapter.forJRE().getAvailableLocales()));
Locale[] tmp = new Locale[locList.size()];
locList.toArray(tmp);
return tmp;
}
- private synchronized Set<Locale> getAvailableLocaleList() {
+ /**
+ * Returns the union of locale sets that are available from
+ * each service provider. This method does NOT return the
+ * defensive copy.
+ *
+ * @return a set of available locales
+ */
+ private synchronized Set<Locale> getAvailableLocaleSet() {
if (availableLocales == null) {
availableLocales = new HashSet<>();
for (LocaleServiceProvider lsp : providers.values()) {
@@ -222,9 +233,6 @@
availableLocales.add(getLookupLocale(locale));
}
}
-
- // Remove Locale.ROOT for the compatibility.
- availableLocales.remove(Locale.ROOT);
}
return availableLocales;
@@ -295,7 +303,7 @@
List<Locale> lookupLocales = getLookupLocales(locale);
- Set<Locale> available = getAvailableLocaleList();
+ Set<Locale> available = getAvailableLocaleSet();
for (Locale current : lookupLocales) {
if (available.contains(current)) {
S providersObj;
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Thu Nov 15 00:54:54 2012 +0000
@@ -35,12 +35,19 @@
#define JAVA_MAGIC 0xCAFEBABE
#define JAVA_MIN_MAJOR_VERSION 45
#define JAVA_MIN_MINOR_VERSION 3
+
#define JAVA5_MAX_MAJOR_VERSION 49
#define JAVA5_MAX_MINOR_VERSION 0
-// NOTE: Assume for now
+
#define JAVA6_MAX_MAJOR_VERSION 50
#define JAVA6_MAX_MINOR_VERSION 0
+#define JAVA7_MAX_MAJOR_VERSION 51
+#define JAVA7_MAX_MINOR_VERSION 0
+
+#define JAVA8_MAX_MAJOR_VERSION 52
+#define JAVA8_MAX_MINOR_VERSION 0
+
// package file constants
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
#define JAVA5_PACKAGE_MAJOR_VERSION 150
--- a/jdk/src/share/native/java/lang/System.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/java/lang/System.c Thu Nov 15 00:54:54 2012 +0000
@@ -102,7 +102,7 @@
#define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/"
#endif
-#define JAVA_MAX_SUPPORTED_VERSION 51
+#define JAVA_MAX_SUPPORTED_VERSION 52
#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0
#ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */
--- a/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c Thu Nov 15 00:54:54 2012 +0000
@@ -26,6 +26,7 @@
#include "sun_security_jgss_wrapper_GSSLibStub.h"
#include "NativeUtil.h"
#include "NativeFunc.h"
+#include "jlong.h"
/* Constants for indicating what type of info is needed for inqueries */
const int TYPE_CRED_NAME = 10;
@@ -75,14 +76,14 @@
jclass jcls,
jbyteArray jbytes) {
gss_OID cOid;
- int i, len;
+ unsigned int i, len;
jbyte* bytes;
jthrowable gssEx;
jboolean found;
if (jbytes != NULL) {
found = JNI_FALSE;
- len = (*env)->GetArrayLength(env, jbytes) - 2;
+ len = (unsigned int)((*env)->GetArrayLength(env, jbytes) - 2);
bytes = (*env)->GetByteArrayElements(env, jbytes, NULL);
if (bytes != NULL) {
for (i = 0; i < ftab->mechs->count; i++) {
@@ -98,9 +99,9 @@
}
if (found != JNI_TRUE) {
checkStatus(env, NULL, GSS_S_BAD_MECH, 0, "[GSSLibStub_getMechPtr]");
- return NULL;
- } else return cOid;
- } else return GSS_C_NO_OID;
+ return ptr_to_jlong(NULL);
+ } else return ptr_to_jlong(cOid);
+ } else return ptr_to_jlong(GSS_C_NO_OID);
}
@@ -244,7 +245,7 @@
if (ftab->inquireNamesForMech != NULL) {
- mech = (gss_OID) (*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech);
+ mech = (gss_OID)jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
nameTypes = GSS_C_NO_OID_SET;
/* gss_inquire_names_for_mech(...) => N/A */
@@ -273,7 +274,7 @@
OM_uint32 minor, major;
gss_name_t nameHdl;
- nameHdl = (gss_name_t) pName;
+ nameHdl = (gss_name_t) jlong_to_ptr(pName);
sprintf(debugBuf, "[GSSLibStub_releaseName] %ld", (long) pName);
debug(env, debugBuf);
@@ -319,7 +320,7 @@
resetGSSBuffer(env, jnameVal, &nameVal);
checkStatus(env, jobj, major, minor, "[GSSLibStub_importName]");
- return (jlong) nameHdl;
+ return ptr_to_jlong(nameHdl);
}
@@ -339,8 +340,8 @@
int isEqual;
isEqual = 0;
- nameHdl1 = (gss_name_t) pName1;
- nameHdl2 = (gss_name_t) pName2;
+ nameHdl1 = (gss_name_t) jlong_to_ptr(pName1);
+ nameHdl2 = (gss_name_t) jlong_to_ptr(pName2);
sprintf(debugBuf, "[GSSLibStub_compareName] %ld %ld", (long) pName1,
(long) pName2);
@@ -370,12 +371,12 @@
gss_name_t nameHdl, mnNameHdl;
gss_OID mech;
- nameHdl = (gss_name_t) pName;
+ nameHdl = (gss_name_t) jlong_to_ptr(pName);
sprintf(debugBuf, "[GSSLibStub_canonicalizeName] %ld", (long) pName);
debug(env, debugBuf);
if (nameHdl != GSS_C_NO_NAME) {
- mech = (gss_OID) (*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech);
+ mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
mnNameHdl = GSS_C_NO_NAME;
/* gss_canonicalize_name(...) may return GSS_S_BAD_NAMETYPE,
@@ -391,7 +392,7 @@
checkStatus(env, jobj, major, minor, "[GSSLibStub_canonicalizeName]");
} else mnNameHdl = GSS_C_NO_NAME;
- return (jlong) mnNameHdl;
+ return ptr_to_jlong(mnNameHdl);
}
/*
@@ -408,7 +409,7 @@
gss_buffer_desc outBuf;
jbyteArray jresult;
- nameHdl = (gss_name_t) pName;
+ nameHdl = (gss_name_t) jlong_to_ptr(pName);
sprintf(debugBuf, "[GSSLibStub_exportName] %ld", (long) pName);
debug(env, debugBuf);
@@ -420,16 +421,16 @@
if (major == GSS_S_NAME_NOT_MN) {
debug(env, "[GSSLibStub_exportName] canonicalize and re-try");
- mNameHdl = (gss_name_t)
+ mNameHdl = (gss_name_t)jlong_to_ptr(
Java_sun_security_jgss_wrapper_GSSLibStub_canonicalizeName
- (env, jobj, pName);
+ (env, jobj, pName));
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
major = (*ftab->exportName)(&minor, mNameHdl, &outBuf);
Java_sun_security_jgss_wrapper_GSSLibStub_releaseName
- (env, jobj, (jlong) mNameHdl);
+ (env, jobj, ptr_to_jlong(mNameHdl));
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
return NULL;
@@ -460,7 +461,7 @@
jobject jtype;
jobjectArray jresult;
- nameHdl = (gss_name_t) pName;
+ nameHdl = (gss_name_t) jlong_to_ptr(pName);
sprintf(debugBuf, "[GSSLibStub_displayName] %ld", (long) pName);
debug(env, debugBuf);
@@ -512,10 +513,10 @@
debug(env, "[GSSLibStub_acquireCred]");
- mech = (gss_OID) (*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech);
+ mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
mechs = newGSSOIDSet(env, mech);
credUsage = (gss_cred_usage_t) usage;
- nameHdl = (gss_name_t) pName;
+ nameHdl = (gss_name_t) jlong_to_ptr(pName);
credHdl = GSS_C_NO_CREDENTIAL;
sprintf(debugBuf, "[GSSLibStub_acquireCred] pName=%ld, usage=%d",
@@ -534,7 +535,7 @@
debug(env, debugBuf);
checkStatus(env, jobj, major, minor, "[GSSLibStub_acquireCred]");
- return (jlong) credHdl;
+ return ptr_to_jlong(credHdl);
}
/*
@@ -550,9 +551,9 @@
OM_uint32 minor, major;
gss_cred_id_t credHdl;
- credHdl = (gss_cred_id_t) pCred;
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
- sprintf(debugBuf, "[GSSLibStub_releaseCred] %ld", pCred);
+ sprintf(debugBuf, "[GSSLibStub_releaseCred] %ld", (long int)pCred);
debug(env, debugBuf);
if (credHdl != GSS_C_NO_CREDENTIAL) {
@@ -562,7 +563,7 @@
checkStatus(env, jobj, major, minor, "[GSSLibStub_releaseCred]");
}
- return (jlong) credHdl;
+ return ptr_to_jlong(credHdl);
}
/*
@@ -570,7 +571,7 @@
*/
void inquireCred(JNIEnv *env, jobject jobj, gss_cred_id_t pCred,
jint type, void *result) {
- OM_uint32 minor, major;
+ OM_uint32 minor, major=GSS_C_QOP_DEFAULT;
OM_uint32 routineErr;
gss_cred_id_t credHdl;
@@ -617,9 +618,9 @@
gss_name_t nameHdl;
gss_cred_id_t credHdl;
- credHdl = (gss_cred_id_t) pCred;
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
- sprintf(debugBuf, "[GSSLibStub_getCredName] %ld", pCred);
+ sprintf(debugBuf, "[GSSLibStub_getCredName] %ld", (long int)pCred);
debug(env, debugBuf);
nameHdl = GSS_C_NO_NAME;
@@ -633,7 +634,7 @@
sprintf(debugBuf, "[GSSLibStub_getCredName] pName=%ld", (long) nameHdl);
debug(env, debugBuf);
- return (jlong) nameHdl;
+ return ptr_to_jlong(nameHdl);
}
/*
@@ -649,9 +650,9 @@
gss_cred_id_t credHdl;
OM_uint32 lifetime;
- credHdl = (gss_cred_id_t) pCred;
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
- sprintf(debugBuf, "[GSSLibStub_getCredTime] %ld", pCred);
+ sprintf(debugBuf, "[GSSLibStub_getCredTime] %ld", (long int)pCred);
debug(env, debugBuf);
lifetime = 0;
@@ -677,9 +678,9 @@
gss_cred_usage_t usage;
gss_cred_id_t credHdl;
- credHdl = (gss_cred_id_t) pCred;
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
- sprintf(debugBuf, "[GSSLibStub_getCredUsage] %ld", pCred);
+ sprintf(debugBuf, "[GSSLibStub_getCredUsage] %ld", (long int)pCred);
debug(env, debugBuf);
inquireCred(env, jobj, credHdl, TYPE_CRED_USAGE, &usage);
@@ -738,13 +739,13 @@
return NULL;
}
- mech2 = (gss_OID) (*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech);
+ mech2 = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
if (sameMech(env, mech, mech2) == JNI_TRUE) {
/* mech match - return the context object */
return (*env)->NewObject(env, CLS_NativeGSSContext,
MID_NativeGSSContext_ctor,
- (jlong) contextHdl, jobj);
+ ptr_to_jlong(contextHdl), jobj);
} else {
/* mech mismatch - clean up then return null */
major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER);
@@ -784,11 +785,11 @@
*/
debug(env, "[GSSLibStub_initContext]");
- credHdl = (gss_cred_id_t) pCred;
- contextHdl = (gss_ctx_id_t)
- (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext);
- targetName = (gss_name_t) pName;
- mech = (gss_OID) (*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech);
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(
+ (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext));
+ targetName = (gss_name_t) jlong_to_ptr(pName);
+ mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jobj, FID_GSSLibStub_pMech));
flags = (OM_uint32) (*env)->GetIntField(env, jcontextSpi,
FID_NativeGSSContext_flags);
time = getGSSTime((*env)->GetIntField(env, jcontextSpi,
@@ -821,7 +822,7 @@
if (GSS_ERROR(major) == GSS_S_COMPLETE) {
/* update member values if needed */
(*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
- (jlong) contextHdl);
+ ptr_to_jlong(contextHdl));
(*env)->SetIntField(env, jcontextSpi, FID_NativeGSSContext_flags, aFlags);
sprintf(debugBuf, "[GSSLibStub_initContext] set flags=0x%x", aFlags);
debug(env, debugBuf);
@@ -879,7 +880,7 @@
OM_uint32 aFlags;
OM_uint32 aTime;
gss_cred_id_t delCred;
- jobject jsrcName;
+ jobject jsrcName=GSS_C_NO_NAME;
jobject jdelCred;
jobject jMech;
jbyteArray jresult;
@@ -889,9 +890,9 @@
debug(env, "[GSSLibStub_acceptContext]");
- contextHdl = (gss_ctx_id_t)
- (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext);
- credHdl = (gss_cred_id_t) pCred;
+ contextHdl = (gss_ctx_id_t)jlong_to_ptr(
+ (*env)->GetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext));
+ credHdl = (gss_cred_id_t) jlong_to_ptr(pCred);
initGSSBuffer(env, jinToken, &inToken);
cb = getGSSCB(env, jcb);
srcName = GSS_C_NO_NAME;
@@ -922,7 +923,7 @@
if (GSS_ERROR(major) == GSS_S_COMPLETE) {
/* update member values if needed */
(*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
- (jlong) contextHdl);
+ ptr_to_jlong(contextHdl));
sprintf(debugBuf, "[GSSLibStub_acceptContext] set pContext=%ld",
(long)contextHdl);
debug(env, debugBuf);
@@ -940,7 +941,7 @@
NULL, NULL);
jtargetName = (*env)->NewObject(env, CLS_GSSNameElement,
MID_GSSNameElement_ctor,
- (jlong) targetName, jobj);
+ ptr_to_jlong(targetName), jobj);
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
@@ -955,7 +956,7 @@
if (srcName != GSS_C_NO_NAME) {
jsrcName = (*env)->NewObject(env, CLS_GSSNameElement,
MID_GSSNameElement_ctor,
- (jlong) srcName, jobj);
+ ptr_to_jlong(srcName), jobj);
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
return NULL;
@@ -981,7 +982,7 @@
if (delCred != GSS_C_NO_CREDENTIAL) {
jdelCred = (*env)->NewObject(env, CLS_GSSCredElement,
MID_GSSCredElement_ctor,
- (jlong) delCred, jsrcName, jMech);
+ ptr_to_jlong(delCred), jsrcName, jMech);
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
return NULL;
@@ -1031,7 +1032,7 @@
jlong result[6];
jlongArray jresult;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_inquireContext] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1051,8 +1052,8 @@
(long)targetName);
debug(env, debugBuf);
- result[0] = (jlong) srcName;
- result[1] = (jlong) targetName;
+ result[0] = ptr_to_jlong(srcName);
+ result[1] = ptr_to_jlong(targetName);
result[2] = (jlong) isInitiator;
result[3] = (jlong) isEstablished;
result[4] = (jlong) flags;
@@ -1081,9 +1082,9 @@
gss_OID mech;
gss_ctx_id_t contextHdl;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
- sprintf(debugBuf, "[GSSLibStub_getContextMech] %ld", pContext);
+ sprintf(debugBuf, "[GSSLibStub_getContextMech] %ld", (long int)pContext);
debug(env, debugBuf);
major = (*ftab->inquireContext)(&minor, contextHdl, NULL, NULL,
@@ -1111,7 +1112,7 @@
gss_name_t nameHdl;
gss_ctx_id_t contextHdl;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_getContextName] %ld, isSrc=%d",
(long)contextHdl, isSrc);
@@ -1129,13 +1130,13 @@
checkStatus(env, jobj, major, minor, "[GSSLibStub_inquireContextAll]");
/* return immediately if an exception has occurred */
if ((*env)->ExceptionCheck(env)) {
- return (long)NULL;
+ return ptr_to_jlong(NULL);
}
sprintf(debugBuf, "[GSSLibStub_getContextName] pName=%ld", (long) nameHdl);
debug(env, debugBuf);
- return (jlong) nameHdl;
+ return ptr_to_jlong(nameHdl);
}
/*
@@ -1151,7 +1152,7 @@
gss_ctx_id_t contextHdl;
OM_uint32 time;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_getContextTime] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1180,17 +1181,17 @@
OM_uint32 minor, major;
gss_ctx_id_t contextHdl;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_deleteContext] %ld", (long)contextHdl);
debug(env, debugBuf);
- if (contextHdl == GSS_C_NO_CONTEXT) return GSS_C_NO_CONTEXT;
+ if (contextHdl == GSS_C_NO_CONTEXT) return ptr_to_jlong(GSS_C_NO_CONTEXT);
/* gss_delete_sec_context(...) => GSS_S_NO_CONTEXT(!) */
major = (*ftab->deleteSecContext)(&minor, &contextHdl, GSS_C_NO_BUFFER);
checkStatus(env, jobj, major, minor, "[GSSLibStub_deleteContext]");
- return (jlong) contextHdl;
+ return (jlong) ptr_to_jlong(contextHdl);
}
/*
@@ -1211,7 +1212,7 @@
OM_uint32 outSize, maxInSize;
gss_qop_t qop;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_wrapSizeLimit] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1244,7 +1245,7 @@
gss_buffer_desc interProcToken;
jbyteArray jresult;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_exportContext] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1281,7 +1282,7 @@
gss_buffer_desc msgToken;
jbyteArray jresult;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_getMic] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1290,7 +1291,7 @@
checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_getMic]");
return NULL;
}
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
qop = (gss_qop_t) jqop;
initGSSBuffer(env, jmsg, &msg);
@@ -1326,7 +1327,7 @@
gss_buffer_desc msgToken;
gss_qop_t qop;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_verifyMic] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1376,7 +1377,7 @@
gss_ctx_id_t contextHdl;
jbyteArray jresult;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_wrap] %ld", (long)contextHdl);
debug(env, debugBuf);
@@ -1427,7 +1428,7 @@
gss_qop_t qop;
jbyteArray jresult;
- contextHdl = (gss_ctx_id_t) pContext;
+ contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext);
sprintf(debugBuf, "[GSSLibStub_unwrap] %ld", (long)contextHdl);
debug(env, debugBuf);
--- a/jdk/src/share/native/sun/security/jgss/wrapper/NativeUtil.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/jgss/wrapper/NativeUtil.c Thu Nov 15 00:54:54 2012 +0000
@@ -25,6 +25,7 @@
#include "NativeUtil.h"
#include "NativeFunc.h"
+#include "jlong.h"
const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */
const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */
@@ -412,7 +413,7 @@
OM_uint32 result;
/* special handle values equal to JAVA_MAX */
- if (jtime == JAVA_MAX) {
+ if (jtime == (jint)JAVA_MAX) {
result = GSS_C_INDEFINITE;
} else {
result = jtime;
@@ -482,7 +483,7 @@
messageContext = 0;
if (jstub != NULL) {
- mech = (gss_OID) (*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech);
+ mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech));
} else {
mech = GSS_C_NO_OID;
}
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c Thu Nov 15 00:54:54 2012 +0000
@@ -422,6 +422,7 @@
jfieldID jFieldID;
jlong jType;
jobject jPValue;
+ memset(&ckAttribute, 0, sizeof(CK_ATTRIBUTE));
// TBD: what if jAttribute == NULL?!
@@ -1577,6 +1578,7 @@
CK_RSA_PKCS_PSS_PARAMS ckParam;
jfieldID fieldID;
jlong jHashAlg, jMgf, jSLen;
+ memset(&ckParam, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
/* get hashAlg */
jRsaPkcsPssParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_PSS_PARAMS);
@@ -1617,6 +1619,7 @@
jfieldID fieldID;
jlong jLong;
jobject jSharedData, jPublicData;
+ memset(&ckParam, 0, sizeof(CK_ECDH1_DERIVE_PARAMS));
/* get kdf */
jEcdh1DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH1_DERIVE_PARAMS);
@@ -1663,6 +1666,7 @@
jfieldID fieldID;
jlong jKdf, jPrivateDataLen, jPrivateData;
jobject jSharedData, jPublicData, jPublicData2;
+ memset(&ckParam, 0, sizeof(CK_ECDH2_DERIVE_PARAMS));
/* get kdf */
jEcdh2DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH2_DERIVE_PARAMS);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_crypt.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_crypt.c Thu Nov 15 00:54:54 2012 +0000
@@ -180,14 +180,14 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directIn != 0) {
- inBufP = (CK_BYTE_PTR) directIn;
+ inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
} else {
inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
if (inBufP == NULL) { return 0; }
}
if (directOut != 0) {
- outBufP = (CK_BYTE_PTR) directOut;
+ outBufP = (CK_BYTE_PTR) jlong_to_ptr(directOut);
} else {
outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
if (outBufP == NULL) {
@@ -249,7 +249,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directOut != 0) {
- outBufP = (CK_BYTE_PTR) directOut;
+ outBufP = (CK_BYTE_PTR) jlong_to_ptr(directOut);
} else {
outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
if (outBufP == NULL) { return 0; }
@@ -401,14 +401,14 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directIn != 0) {
- inBufP = (CK_BYTE_PTR) directIn;
+ inBufP = (CK_BYTE_PTR) jlong_to_ptr(directIn);
} else {
inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
if (inBufP == NULL) { return 0; }
}
if (directOut != 0) {
- outBufP = (CK_BYTE_PTR) directOut;
+ outBufP = (CK_BYTE_PTR) jlong_to_ptr(directOut);
} else {
outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
if (outBufP == NULL) {
@@ -465,7 +465,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directOut != 0) {
- outBufP = (CK_BYTE_PTR) directOut;
+ outBufP = (CK_BYTE_PTR) jlong_to_ptr(directOut);
} else {
outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
if (outBufP == NULL) { return 0; }
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c Thu Nov 15 00:54:54 2012 +0000
@@ -51,6 +51,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include "jlong.h"
#include "sun_security_pkcs11_wrapper_PKCS11.h"
@@ -178,7 +179,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directIn != 0) {
- rv = (*ckpFunctions->C_DigestUpdate)(ckSessionHandle, (CK_BYTE_PTR)directIn, jInLen);
+ rv = (*ckpFunctions->C_DigestUpdate)(ckSessionHandle, (CK_BYTE_PTR)jlong_to_ptr(directIn), jInLen);
ckAssertReturnValueOK(env, rv);
return;
}
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c Thu Nov 15 00:54:54 2012 +0000
@@ -253,10 +253,12 @@
(JNIEnv *env, jobject obj)
{
CK_INFO ckLibInfo;
- jobject jInfoObject;
+ jobject jInfoObject=NULL;
CK_RV rv;
+ CK_FUNCTION_LIST_PTR ckpFunctions;
+ memset(&ckLibInfo, 0, sizeof(CK_INFO));
- CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
+ ckpFunctions = getFunctionList(env, obj);
if (ckpFunctions == NULL) { return NULL; }
rv = (*ckpFunctions->C_GetInfo)(&ckLibInfo);
@@ -384,7 +386,7 @@
{
CK_SLOT_ID ckSlotID;
CK_SLOT_INFO ckSlotInfo;
- jobject jSlotInfoObject;
+ jobject jSlotInfoObject=NULL;
CK_RV rv;
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
@@ -396,7 +398,7 @@
if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
jSlotInfoObject = ckSlotInfoPtrToJSlotInfo(env, &ckSlotInfo);
}
- return jSlotInfoObject ;
+ return jSlotInfoObject;
}
/*
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c Thu Nov 15 00:54:54 2012 +0000
@@ -256,7 +256,7 @@
{
CK_SESSION_HANDLE ckSessionHandle;
CK_SESSION_INFO ckSessionInfo;
- jobject jSessionInfo;
+ jobject jSessionInfo=NULL;
CK_RV rv;
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c Thu Nov 15 00:54:54 2012 +0000
@@ -51,6 +51,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include "jlong.h"
#include "sun_security_pkcs11_wrapper_PKCS11.h"
@@ -198,7 +199,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directIn != 0) {
- rv = (*ckpFunctions->C_SignUpdate)(ckSessionHandle, (CK_BYTE_PTR)directIn, jInLen);
+ rv = (*ckpFunctions->C_SignUpdate)(ckSessionHandle, (CK_BYTE_PTR) jlong_to_ptr(directIn), jInLen);
ckAssertReturnValueOK(env, rv);
return;
}
@@ -262,7 +263,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
- if ((jExpectedLength > 0) && (jExpectedLength < ckSignatureLength)) {
+ if ((jExpectedLength > 0) && ((CK_ULONG)jExpectedLength < ckSignatureLength)) {
ckSignatureLength = jExpectedLength;
}
@@ -496,7 +497,7 @@
ckSessionHandle = jLongToCKULong(jSessionHandle);
if (directIn != 0) {
- rv = (*ckpFunctions->C_VerifyUpdate)(ckSessionHandle, (CK_BYTE_PTR)directIn, jInLen);
+ rv = (*ckpFunctions->C_VerifyUpdate)(ckSessionHandle, (CK_BYTE_PTR)jlong_to_ptr(directIn), jInLen);
ckAssertReturnValueOK(env, rv);
return;
}
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c Thu Nov 15 00:54:54 2012 +0000
@@ -106,7 +106,7 @@
if (moduleData == NULL) {
return ;
}
- (*env)->SetLongField(env, pkcs11Implementation, pNativeDataID, (jlong)moduleData);
+ (*env)->SetLongField(env, pkcs11Implementation, pNativeDataID, ptr_to_jlong(moduleData));
}
@@ -120,7 +120,7 @@
return NULL;
}
jData = (*env)->GetLongField(env, pkcs11Implementation, pNativeDataID);
- return (ModuleData*)jData;
+ return (ModuleData*)jlong_to_ptr(jData);
}
CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation) {
--- a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Thu Nov 15 00:54:54 2012 +0000
@@ -34,7 +34,7 @@
#include "j2secmod.h"
void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) {
- void *hModule = (void*)jHandle;
+ void *hModule = (void*)jlong_to_ptr(jHandle);
void *fAddress = dlsym(hModule, functionName);
if (fAddress == NULL) {
char errorMessage[256];
@@ -53,7 +53,7 @@
void *hModule = dlopen(libName, RTLD_NOLOAD);
dprintf2("-handle for %s: %u\n", libName, hModule);
(*env)->ReleaseStringUTFChars(env, jLibName, libName);
- return (jlong)hModule;
+ return ptr_to_jlong(hModule);
}
JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssLoadLibrary
@@ -72,5 +72,5 @@
return 0;
}
- return (jlong)hModule;
+ return ptr_to_jlong(hModule);
}
--- a/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Thu Nov 15 00:54:54 2012 +0000
@@ -79,7 +79,7 @@
{
void *hModule;
char *error;
- CK_C_GetFunctionList C_GetFunctionList;
+ CK_C_GetFunctionList C_GetFunctionList=NULL;
CK_RV rv;
ModuleData *moduleData;
jobject globalPKCS11ImplementationReference;
--- a/jdk/test/ProblemList.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/ProblemList.txt Thu Nov 15 00:54:54 2012 +0000
@@ -137,11 +137,6 @@
# 7196801
java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all
-# Exclude until hotspot/jdk repos are sync'd w.r.t. JAVA_MAX_SUPPORTED_VERSION
-# Needed when hotspot fix 7054345 is present. Remove when the JDK source is
-# updated accordingly.
-java/lang/System/Versions.java generic-all
-
############################################################################
# jdk_management
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEInvalidParamsTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEInvalidParamsTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. 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 6209660
+ * @bug 6209660 6383200
* @summary Ensure that InvalidAlgorithmParameterException is
* thrown as javadoc specified when parameters of the wrong
* type are used.
@@ -38,9 +38,21 @@
private static final char[] PASSWORD = { 'p', 'a', 's', 's' };
private static final String[] PBE_ALGOS = {
- "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40"
+ "PBEWithMD5AndDES",
+ "PBEWithSHA1AndDESede",
+ "PBEWithSHA1AndRC2_40",
+ "PBEWithSHA1AndRC2_128",
+ "PBEWithSHA1AndRC4_40",
+ "PBEWithSHA1AndRC4_128",
// skip "PBEWithMD5AndTripleDES" since it requires Unlimited
// version of JCE jurisdiction policy files.
+ "PBEWithHmacSHA1AndAES_128",
+ "PBEWithHmacSHA224AndAES_128",
+ "PBEWithHmacSHA256AndAES_128",
+ "PBEWithHmacSHA384AndAES_128",
+ "PBEWithHmacSHA512AndAES_128"
+ // skip "PBEWithHmacSHAxxxAndAES_256" since they require Unlimited
+ // version of JCE jurisdiction policy files.
};
private static final IvParameterSpec INVALID_PARAMS =
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEKeysAlgorithmNames.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEKeysAlgorithmNames.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. 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 6341599
+ * @bug 6341599 6383200
* @summary JCE Reference Guide has recommendations, not requirements,
* for algorithm names
* @author Brad R. Wetmore
@@ -38,8 +38,15 @@
"PBEWithMD5AndDES",
"PBEWithSHA1AndDESede",
"PBEWithSHA1AndRC2_40",
+ "PBEWithSHA1AndRC2_128",
+ "PBEWithMD5AndTripleDES",
+ "PBEWithSHA1AndRC4_40",
+ "PBEWithSHA1AndRC4_128",
"PBKDF2WithHmacSHA1",
- "PBEWithMD5AndTripleDES"
+ "PBKDF2WithHmacSHA224",
+ "PBKDF2WithHmacSHA256",
+ "PBKDF2WithHmacSHA384",
+ "PBKDF2WithHmacSHA512"
};
public static void main(String[] argv) throws Exception {
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEParametersTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBEParametersTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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 4944783
+ * @bug 4944783 6383200
* @summary ensure that the AlgorithmParameters object returned by
* PBE ciphers have the matching algorithm name.
* @author Valerie Peng
@@ -37,9 +37,21 @@
private static final char[] PASSWORD = { 'p', 'a', 's', 's' };
private static final String[] PBE_ALGOS = {
- "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40"
+ "PBEWithMD5AndDES",
+ "PBEWithSHA1AndDESede",
+ "PBEWithSHA1AndRC2_40",
+ "PBEWithSHA1AndRC2_128",
+ "PBEWithSHA1AndRC4_40",
+ "PBEWithSHA1AndRC4_128",
// skip "PBEWithMD5AndTripleDES" since it requires Unlimited
// version of JCE jurisdiction policy files.
+ "PBEWithHmacSHA1AndAES_128",
+ "PBEWithHmacSHA224AndAES_128",
+ "PBEWithHmacSHA256AndAES_128",
+ "PBEWithHmacSHA384AndAES_128",
+ "PBEWithHmacSHA512AndAES_128"
+ // skip "PBEWithHmacSHAxxxAndAES_256" since they require Unlimited
+ // version of JCE jurisdiction policy files.
};
public static void main(String[] args) throws Exception {
PBEKeySpec ks = new PBEKeySpec(PASSWORD);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBES2Test.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6383200
+ * @summary PBE: need new algorithm support in password based encryption
+ */
+import java.security.*;
+import java.util.Arrays;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class PBES2Test {
+
+ private static final String[] algos = {
+ "PBEWithHmacSHA1AndAES_128",
+ "PBEWithHmacSHA224AndAES_128",
+ "PBEWithHmacSHA256AndAES_128",
+ "PBEWithHmacSHA384AndAES_128",
+ "PBEWithHmacSHA512AndAES_128"
+ };
+ private static final byte[] ivBytes = {
+ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
+ 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
+ };
+
+ public static final void main(String[] args) throws Exception {
+ for (String algo : algos) {
+ test(algo, true); // salt, ic, IV supplied by the application
+ test(algo, false); // salt, ic, IV generated by the implementation
+ }
+ }
+
+ private static final void test(String algo, boolean suppliedParams)
+ throws Exception {
+
+ System.out.println("***********************************************");
+ System.out.println(algo +
+ (suppliedParams ? " [algorithm parameters are supplied]\n"
+ : " [algorithm parameters are generated]\n"));
+ int iterationCount = 1000;
+ byte[] salt = new byte[]{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 };
+
+ // Create PBE key
+ PBEKeySpec pbeKeySpec = new PBEKeySpec("mypassword".toCharArray());
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algo);
+ SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
+ byte[] pbeKeyBytes = pbeKey.getEncoded();
+ System.out.println(" key[" + pbeKeyBytes.length + "]: " +
+ String.format("0x%0" + (pbeKeyBytes.length * 2) + "x",
+ new java.math.BigInteger(1, pbeKeyBytes)));
+
+ // Create PBE cipher
+ System.out.println("Encrypting...");
+ Cipher pbeCipher = Cipher.getInstance(algo);
+ if (suppliedParams) {
+ pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey,
+ new PBEParameterSpec(salt, iterationCount,
+ new IvParameterSpec(ivBytes)));
+ } else {
+ pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey);
+ }
+
+ // Encrypt
+ byte[] cleartext = "This is just an example".getBytes();
+ System.out.println(" text[" + cleartext.length + "]: " +
+ String.format("0x%0" + (cleartext.length * 2) + "x",
+ new java.math.BigInteger(1, cleartext)));
+
+ byte[] ciphertext = pbeCipher.doFinal(cleartext);
+ System.out.println("c'text[" + ciphertext.length + "]: " +
+ String.format("0x%0" + (ciphertext.length * 2) + "x",
+ new java.math.BigInteger(1, ciphertext)));
+
+ AlgorithmParameters aps = pbeCipher.getParameters();
+
+ byte[] iv;
+ if (suppliedParams) {
+ iv = ivBytes;
+ } else {
+ PBEParameterSpec pbeSpec =
+ aps.getParameterSpec(PBEParameterSpec.class);
+ salt = pbeSpec.getSalt();
+ iterationCount = pbeSpec.getIterationCount();
+ IvParameterSpec ivSpec =
+ (IvParameterSpec) pbeSpec.getParameterSpec();
+ iv = ivSpec.getIV();
+ }
+ System.out.println(" salt[" + salt.length + "]: " +
+ String.format("0x%0" + (salt.length * 2) + "x",
+ new java.math.BigInteger(1, salt)));
+ System.out.println("iterationCount=" + iterationCount);
+ System.out.println(" iv[" + iv.length + "]: " +
+ String.format("0x%0" + (iv.length * 2) + "x",
+ new java.math.BigInteger(1, iv)));
+
+ // Decrypt
+ System.out.println("Decrypting...");
+ Cipher pbeCipher2 = Cipher.getInstance(algo);
+ pbeCipher2.init(Cipher.DECRYPT_MODE, pbeKey, aps);
+ byte[] cleartext2 = pbeCipher2.doFinal(ciphertext);
+ System.out.println(" text[" + cleartext2.length + "]: " +
+ String.format("0x%0" + (cleartext2.length * 2) + "x",
+ new java.math.BigInteger(1, cleartext2)));
+
+ if (Arrays.equals(cleartext, cleartext2)) {
+ System.out.println(
+ "\nPass: decrypted ciphertext matches the original text\n");
+ } else {
+ throw new Exception(
+ "Fail: decrypted ciphertext does NOT match the original text");
+ }
+ }
+}
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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,9 +23,9 @@
/**
* @test
- * @bug 4893959
- * @summary basic test for PBEWithSHA1AndDESede and
- * PBEWithSHA1AndRC2_40
+ * @bug 4893959 6383200
+ * @summary basic test for PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40/128
+ * and PBEWithSHA1AndRC4_40/128
* @author Valerie Peng
*/
@@ -87,6 +87,9 @@
System.out.println("Testing provider " + p.getName() + "...");
runTest("PBEWithSHA1AndDESede", input, PASSWD, p);
runTest("PBEWithSHA1AndRC2_40", input, PASSWD, p);
+ runTest("PBEWithSHA1AndRC2_128", input, PASSWD, p);
+ runTest("PBEWithSHA1AndRC4_40", input, PASSWD, p);
+ runTest("PBEWithSHA1AndRC4_128", input, PASSWD, p);
System.out.println("All tests passed");
long stop = System.currentTimeMillis();
System.out.println("Done (" + (stop - start) + " ms).");
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Oid.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Oid.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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,9 +23,9 @@
/**
* @test
- * @bug 4898810
- * @summary ensure PBEWithSHA1AndDESede and PBEWithSHA1AndRC2_40
- * is registered under correct OID.
+ * @bug 4898810 6383200
+ * @summary ensure PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40/128
+ * and PBEWithSHA1AndRC4_40/128 are registered under correct OID.
* @author Valerie Peng
*/
@@ -37,12 +37,20 @@
import javax.crypto.interfaces.PBEKey;
public class PKCS12Oid {
- private static String OID_PBEWithSHAAnd40BitRC2CBC = "1.2.840.113549.1.12.1.6";
- private static String OID_PBEWithSHAAnd3KeyTripleDESCBC = "1.2.840.113549.1.12.1.3";
+ private static String OID_PKCS12 = "1.2.840.113549.1.12.1.";
+ private static String OID_PBEWithSHAAnd128BitRC4 = OID_PKCS12 + "1";
+ private static String OID_PBEWithSHAAnd40BitRC4 = OID_PKCS12 + "2";
+ private static String OID_PBEWithSHAAnd3KeyTripleDESCBC = OID_PKCS12 + "3";
+ private static String OID_PBEWithSHAAnd128BitRC2CBC = OID_PKCS12 + "5";
+ private static String OID_PBEWithSHAAnd40BitRC2CBC = OID_PKCS12 + "6";
public static void main(String[] argv) throws Exception {
Cipher c = Cipher.getInstance(OID_PBEWithSHAAnd40BitRC2CBC, "SunJCE");
c = Cipher.getInstance(OID_PBEWithSHAAnd3KeyTripleDESCBC, "SunJCE");
+
+ c = Cipher.getInstance(OID_PBEWithSHAAnd128BitRC4, "SunJCE");
+ c = Cipher.getInstance(OID_PBEWithSHAAnd40BitRC4, "SunJCE");
+ c = Cipher.getInstance(OID_PBEWithSHAAnd128BitRC2CBC, "SunJCE");
System.out.println("All tests passed");
}
}
--- a/jdk/test/com/sun/crypto/provider/Mac/HmacPBESHA1.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Mac/HmacPBESHA1.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -36,34 +36,45 @@
import javax.crypto.spec.*;
public class HmacPBESHA1 {
- private static final String MAC_ALGO = "HmacPBESHA1";
+ private static final String[] MAC_ALGOS = {
+ "HmacPBESHA1",
+ "PBEWithHmacSHA1",
+ "PBEWithHmacSHA224",
+ "PBEWithHmacSHA256",
+ "PBEWithHmacSHA384",
+ "PBEWithHmacSHA512"
+ };
+ private static final int[] MAC_LENGTHS = { 20, 20, 28, 32, 48, 64 };
private static final String KEY_ALGO = "PBE";
private static final String PROVIDER = "SunJCE";
- private SecretKey key = null;
+ private static SecretKey key = null;
public static void main(String argv[]) throws Exception {
- HmacPBESHA1 test = new HmacPBESHA1();
- test.run();
- System.out.println("Test Passed");
+ for (int i = 0; i < MAC_ALGOS.length; i++) {
+ runtest(MAC_ALGOS[i], MAC_LENGTHS[i]);
+ }
+ System.out.println("\nTest Passed");
}
- public void run() throws Exception {
+ private static void runtest(String algo, int length) throws Exception {
+ System.out.println("Testing: " + algo);
if (key == null) {
char[] password = { 't', 'e', 's', 't' };
PBEKeySpec keySpec = new PBEKeySpec(password);
- SecretKeyFactory kf = SecretKeyFactory.getInstance(KEY_ALGO, PROVIDER);
+ SecretKeyFactory kf =
+ SecretKeyFactory.getInstance(KEY_ALGO, PROVIDER);
key = kf.generateSecret(keySpec);
}
- Mac mac = Mac.getInstance(MAC_ALGO, PROVIDER);
+ Mac mac = Mac.getInstance(algo, PROVIDER);
byte[] plainText = new byte[30];
mac.init(key);
mac.update(plainText);
byte[] value1 = mac.doFinal();
- if (value1.length != 20) {
- throw new Exception("incorrect MAC output length, " +
- "expected 20, got " + value1.length);
+ if (value1.length != length) {
+ throw new Exception("incorrect MAC output length, expected " +
+ length + ", got " + value1.length);
}
mac.update(plainText);
byte[] value2 = mac.doFinal();
--- a/jdk/test/com/sun/crypto/provider/Mac/HmacSaltLengths.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/com/sun/crypto/provider/Mac/HmacSaltLengths.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -38,6 +38,15 @@
public class HmacSaltLengths {
+ private static final String[] ALGOS = {
+ "HmacPBESHA1",
+ "PBEWithHmacSHA1",
+ "PBEWithHmacSHA224",
+ "PBEWithHmacSHA256",
+ "PBEWithHmacSHA384",
+ "PBEWithHmacSHA512"
+ };
+
private static void runTest(String alg, byte[] plaintext,
char[] password, Provider p)
throws Exception {
@@ -81,7 +90,9 @@
long start = System.currentTimeMillis();
Provider p = Security.getProvider("SunJCE");
System.out.println("Testing provider " + p.getName() + "...");
- runTest("HmacPBESHA1", input, PASSWD, p);
+ for (String algo : ALGOS) {
+ runTest(algo, input, PASSWD, p);
+ }
System.out.println("All tests passed");
long stop = System.currentTimeMillis();
System.out.println("Done (" + (stop - start) + " ms).");
--- a/jdk/test/java/lang/Character/CheckProp.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/Character/CheckProp.java Thu Nov 15 00:54:54 2012 +0000
@@ -24,7 +24,7 @@
/**
* @test
- * @bug 7037261 7070436
+ * @bug 7037261 7070436 7198195
* @summary Check j.l.Character.isLowerCase/isUppercase/isAlphabetic/isIdeographic
*/
--- a/jdk/test/java/lang/Character/CheckScript.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/Character/CheckScript.java Thu Nov 15 00:54:54 2012 +0000
@@ -24,7 +24,7 @@
/**
* @test
- * @bug 6945564 6959267 7033561 7070436
+ * @bug 6945564 6959267 7033561 7070436 7198195
* @summary Check that the j.l.Character.UnicodeScript
*/
--- a/jdk/test/java/lang/Character/PropList.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/Character/PropList.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# PropList-6.1.0.txt
-# Date: 2011-11-30, 01:49:54 GMT [MD]
+# PropList-6.2.0.txt
+# Date: 2012-05-23, 20:34:59 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
--- a/jdk/test/java/lang/Character/PropertyValueAliases.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/Character/PropertyValueAliases.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# PropertyValueAliases-6.1.0.txt
-# Date: 2011-12-07, 23:40:57 GMT [MD]
+# PropertyValueAliases-6.2.0.txt
+# Date: 2012-08-14, 16:05:11 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
#
@@ -73,6 +73,7 @@
age; 5.2 ; V5_2
age; 6.0 ; V6_0
age; 6.1 ; V6_1
+age; 6.2 ; V6_2
age; NA ; Unassigned
# Alphabetic (Alpha)
@@ -382,7 +383,8 @@
ccc; 122; CCC122 ; CCC122
ccc; 129; CCC129 ; CCC129
ccc; 130; CCC130 ; CCC130
-ccc; 132; CCC133 ; CCC133
+ccc; 132; CCC132 ; CCC132
+ccc; 133; CCC133 ; CCC133 # RESERVED
ccc; 200; ATBL ; Attached_Below_Left
ccc; 202; ATB ; Attached_Below
ccc; 214; ATA ; Attached_Above
@@ -592,6 +594,7 @@
GCB; LV ; LV
GCB; LVT ; LVT
GCB; PP ; Prepend
+GCB; RI ; Regional_Indicator
GCB; SM ; SpacingMark
GCB; T ; T
GCB; V ; V
@@ -862,6 +865,7 @@
lb ; PO ; Postfix_Numeric
lb ; PR ; Prefix_Numeric
lb ; QU ; Quotation
+lb ; RI ; Regional_Indicator
lb ; SA ; Complex_Context
lb ; SG ; Surrogate
lb ; SP ; Space
@@ -880,10 +884,6 @@
Lower; N ; No ; F ; False
Lower; Y ; Yes ; T ; True
-# Lowercase_Mapping (lc)
-
-# @missing: 0000..10FFFF; Lowercase_Mapping; <code point>
-
# Math (Math)
Math; N ; No ; F ; False
@@ -1159,10 +1159,6 @@
Term; N ; No ; F ; False
Term; Y ; Yes ; T ; True
-# Titlecase_Mapping (tc)
-
-# @missing: 0000..10FFFF; Titlecase_Mapping; <code point>
-
# Unicode_1_Name (na1)
# @missing: 0000..10FFFF; Unicode_1_Name; <none>
@@ -1177,10 +1173,6 @@
Upper; N ; No ; F ; False
Upper; Y ; Yes ; T ; True
-# Uppercase_Mapping (uc)
-
-# @missing: 0000..10FFFF; Uppercase_Mapping; <code point>
-
# Variation_Selector (VS)
VS ; N ; No ; F ; False
@@ -1205,6 +1197,7 @@
WB ; MN ; MidNum
WB ; NL ; Newline
WB ; NU ; Numeric
+WB ; RI ; Regional_Indicator
WB ; XX ; Other
# XID_Continue (XIDC)
--- a/jdk/test/java/lang/Character/Scripts.txt Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/Character/Scripts.txt Thu Nov 15 00:54:54 2012 +0000
@@ -1,8 +1,8 @@
-# Scripts-6.1.0.txt
-# Date: 2011-11-27, 05:10:50 GMT [MD]
+# Scripts-6.2.0.txt
+# Date: 2012-06-04, 17:21:29 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2011 Unicode, Inc.
+# Copyright (c) 1991-2012 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
@@ -146,7 +146,7 @@
208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS
208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS
-20A0..20B9 ; Common # Sc [26] EURO-CURRENCY SIGN..INDIAN RUPEE SIGN
+20A0..20BA ; Common # Sc [27] EURO-CURRENCY SIGN..TURKISH LIRA SIGN
2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
2102 ; Common # L& DOUBLE-STRUCK CAPITAL C
2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA
@@ -576,7 +576,7 @@
E0001 ; Common # Cf LANGUAGE TAG
E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
-# Total code points: 6412
+# Total code points: 6413
# ================================================
@@ -760,7 +760,7 @@
061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK
0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
-0656..065E ; Arabic # Mn [9] ARABIC SUBSCRIPT ALEF..ARABIC FATHA WITH TWO DOTS
+0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW
066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
@@ -827,7 +827,7 @@
1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
-# Total code points: 1234
+# Total code points: 1235
# ================================================
@@ -1477,7 +1477,6 @@
0300..036F ; Inherited # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
0485..0486 ; Inherited # Mn [2] COMBINING CYRILLIC DASIA PNEUMATA..COMBINING CYRILLIC PSILI PNEUMATA
064B..0655 ; Inherited # Mn [11] ARABIC FATHATAN..ARABIC HAMZA BELOW
-065F ; Inherited # Mn ARABIC WAVY HAMZA BELOW
0670 ; Inherited # Mn ARABIC LETTER SUPERSCRIPT ALEF
0951..0952 ; Inherited # Mn [2] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI STRESS SIGN ANUDATTA
1CD0..1CD2 ; Inherited # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
@@ -1504,7 +1503,7 @@
1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 524
+# Total code points: 523
# ================================================
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Math/DivModTests.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * @test Test Math and StrictMath Floor Div / Modulo operations.
+ * @bug 6282196
+ * @summary Basic tests for Floor division and modulo methods for both Math
+ * and StrictMath for int and long datatypes.
+ */
+public class DivModTests {
+
+ /**
+ * The count of test errors.
+ */
+ private static int errors = 0;
+
+ /**
+ * @param args the command line arguments are unused
+ */
+ public static void main(String[] args) {
+ errors = 0;
+ testIntFloorDivMod();
+ testLongFloorDivMod();
+
+ if (errors > 0) {
+ throw new RuntimeException(errors + " errors found in DivMod methods.");
+ }
+ }
+
+ /**
+ * Report a test failure and increment the error count.
+ * @param message the formatting string
+ * @param args the variable number of arguments for the message.
+ */
+ static void fail(String message, Object... args) {
+ errors++;
+ System.out.printf(message, args);
+ }
+
+ /**
+ * Test the integer floorDiv and floorMod methods.
+ * Math and StrictMath tested and the same results are expected for both.
+ */
+ static void testIntFloorDivMod() {
+ testIntFloorDivMod(4, 0, new ArithmeticException("/ by zero"), new ArithmeticException("/ by zero")); // Should throw ArithmeticException
+ testIntFloorDivMod(4, 3, 1, 1);
+ testIntFloorDivMod(3, 3, 1, 0);
+ testIntFloorDivMod(2, 3, 0, 2);
+ testIntFloorDivMod(1, 3, 0, 1);
+ testIntFloorDivMod(0, 3, 0, 0);
+ testIntFloorDivMod(4, -3, -2, -2);
+ testIntFloorDivMod(3, -3, -1, 0);
+ testIntFloorDivMod(2, -3, -1, -1);
+ testIntFloorDivMod(1, -3, -1, -2);
+ testIntFloorDivMod(0, -3, 0, 0);
+ testIntFloorDivMod(-1, 3, -1, 2);
+ testIntFloorDivMod(-2, 3, -1, 1);
+ testIntFloorDivMod(-3, 3, -1, 0);
+ testIntFloorDivMod(-4, 3, -2, 2);
+ testIntFloorDivMod(-1, -3, 0, -1);
+ testIntFloorDivMod(-2, -3, 0, -2);
+ testIntFloorDivMod(-3, -3, 1, 0);
+ testIntFloorDivMod(-4, -3, 1, -1);
+ testIntFloorDivMod(Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+ testIntFloorDivMod(Integer.MAX_VALUE, -1, -Integer.MAX_VALUE, 0);
+ testIntFloorDivMod(Integer.MAX_VALUE, 3, 715827882, 1);
+ testIntFloorDivMod(Integer.MAX_VALUE - 1, 3, 715827882, 0);
+ testIntFloorDivMod(Integer.MIN_VALUE, 3, -715827883, 1);
+ testIntFloorDivMod(Integer.MIN_VALUE + 1, 3, -715827883, 2);
+ testIntFloorDivMod(Integer.MIN_VALUE + 1, -1, Integer.MAX_VALUE, 0);
+ // Special case of integer overflow
+ testIntFloorDivMod(Integer.MIN_VALUE, -1, Integer.MIN_VALUE, 0);
+ }
+
+ /**
+ * Test FloorDiv and then FloorMod with int data.
+ */
+ static void testIntFloorDivMod(int x, int y, Object divExpected, Object modExpected) {
+ testIntFloorDiv(x, y, divExpected);
+ testIntFloorMod(x, y, modExpected);
+ }
+
+ /**
+ * Test FloorDiv with int data.
+ */
+ static void testIntFloorDiv(int x, int y, Object expected) {
+ Object result = doFloorDiv(x, y);
+ if (!resultEquals(result, expected)) {
+ fail("FAIL: Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
+ }
+
+ Object strict_result = doStrictFloorDiv(x, y);
+ if (!resultEquals(strict_result, expected)) {
+ fail("FAIL: StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+ }
+ }
+
+ /**
+ * Test FloorMod with int data.
+ */
+ static void testIntFloorMod(int x, int y, Object expected) {
+ Object result = doFloorMod(x, y);
+ if (!resultEquals(result, expected)) {
+ fail("FAIL: Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
+ }
+
+ Object strict_result = doStrictFloorMod(x, y);
+ if (!resultEquals(strict_result, expected)) {
+ fail("FAIL: StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+ }
+
+ try {
+ // Verify result against double precision floor function
+ int tmp = x / y; // Force ArithmeticException for divide by zero
+ double ff = x - Math.floor((double)x / (double)y) * y;
+ int fr = (int)ff;
+ if (fr != result) {
+ fail("FAIL: Math.floorMod(%d, %d) = %s differs from Math.floor(x, y): %d%n", x, y, result, fr);
+ }
+ } catch (ArithmeticException ae) {
+ if (y != 0) {
+ fail("FAIL: Math.floorMod(%d, %d); unexpected %s%n", x, y, ae);
+ }
+ }
+ }
+
+ /**
+ * Test the floorDiv and floorMod methods for primitive long.
+ */
+ static void testLongFloorDivMod() {
+ testLongFloorDivMod(4L, 0L, new ArithmeticException("/ by zero"), new ArithmeticException("/ by zero")); // Should throw ArithmeticException
+ testLongFloorDivMod(4L, 3L, 1L, 1L);
+ testLongFloorDivMod(3L, 3L, 1L, 0L);
+ testLongFloorDivMod(2L, 3L, 0L, 2L);
+ testLongFloorDivMod(1L, 3L, 0L, 1L);
+ testLongFloorDivMod(0L, 3L, 0L, 0L);
+ testLongFloorDivMod(4L, -3L, -2L, -2L);
+ testLongFloorDivMod(3L, -3L, -1L, 0l);
+ testLongFloorDivMod(2L, -3L, -1L, -1L);
+ testLongFloorDivMod(1L, -3L, -1L, -2L);
+ testLongFloorDivMod(0L, -3L, 0L, 0L);
+ testLongFloorDivMod(-1L, 3L, -1L, 2L);
+ testLongFloorDivMod(-2L, 3L, -1L, 1L);
+ testLongFloorDivMod(-3L, 3L, -1L, 0L);
+ testLongFloorDivMod(-4L, 3L, -2L, 2L);
+ testLongFloorDivMod(-1L, -3L, 0L, -1L);
+ testLongFloorDivMod(-2L, -3L, 0L, -2L);
+ testLongFloorDivMod(-3L, -3L, 1L, 0L);
+ testLongFloorDivMod(-4L, -3L, 1L, -1L);
+
+ testLongFloorDivMod(Long.MAX_VALUE, 1, Long.MAX_VALUE, 0L);
+ testLongFloorDivMod(Long.MAX_VALUE, -1, -Long.MAX_VALUE, 0L);
+ testLongFloorDivMod(Long.MAX_VALUE, 3L, Long.MAX_VALUE / 3L, 1L);
+ testLongFloorDivMod(Long.MAX_VALUE - 1L, 3L, (Long.MAX_VALUE - 1L) / 3L, 0L);
+ testLongFloorDivMod(Long.MIN_VALUE, 3L, Long.MIN_VALUE / 3L - 1L, 1L);
+ testLongFloorDivMod(Long.MIN_VALUE + 1L, 3L, Long.MIN_VALUE / 3L - 1L, 2L);
+ testLongFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
+ // Special case of integer overflow
+ testLongFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
+ }
+
+ /**
+ * Test the integer floorDiv and floorMod methods.
+ * Math and StrictMath are tested and the same results are expected for both.
+ */
+ static void testLongFloorDivMod(long x, long y, Object divExpected, Object modExpected) {
+ testLongFloorDiv(x, y, divExpected);
+ testLongFloorMod(x, y, modExpected);
+ }
+
+ /**
+ * Test FloorDiv with long arguments against expected value.
+ * The expected value is usually a Long but in some cases is
+ * an ArithmeticException.
+ *
+ * @param x dividend
+ * @param y modulus
+ * @param expected expected value,
+ */
+ static void testLongFloorDiv(long x, long y, Object expected) {
+ Object result = doFloorDiv(x, y);
+ if (!resultEquals(result, expected)) {
+ fail("FAIL: long Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
+ }
+
+ Object strict_result = doStrictFloorDiv(x, y);
+ if (!resultEquals(strict_result, expected)) {
+ fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+ }
+ }
+
+ /**
+ * Test FloorMod of long arguments against expected value.
+ * The expected value is usually a Long but in some cases is
+ * an ArithmeticException.
+ *
+ * @param x dividend
+ * @param y modulus
+ * @param expected expected value
+ */
+ static void testLongFloorMod(long x, long y, Object expected) {
+ Object result = doFloorMod(x, y);
+ if (!resultEquals(result, expected)) {
+ fail("FAIL: long Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
+ }
+
+ Object strict_result = doStrictFloorMod(x, y);
+ if (!resultEquals(strict_result, expected)) {
+ fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+ }
+
+ try {
+ // Verify the result against BigDecimal rounding mode.
+ BigDecimal xD = new BigDecimal(x);
+ BigDecimal yD = new BigDecimal(y);
+ BigDecimal resultD = xD.divide(yD, RoundingMode.FLOOR);
+ resultD = resultD.multiply(yD);
+ resultD = xD.subtract(resultD);
+ long fr = resultD.longValue();
+ if (fr != result) {
+ fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n",x, y, result, fr);
+
+ }
+ } catch (ArithmeticException ae) {
+ if (y != 0) {
+ fail("FAIL: long Math.floorMod(%d, %d); unexpected ArithmeticException from bigdecimal");
+ }
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doFloorDiv(int x, int y) {
+ try {
+ return Math.floorDiv(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doFloorDiv(long x, long y) {
+ try {
+ return Math.floorDiv(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doFloorMod(int x, int y) {
+ try {
+ return Math.floorMod(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doFloorMod(long x, long y) {
+ try {
+ return Math.floorMod(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doStrictFloorDiv(int x, int y) {
+ try {
+ return StrictMath.floorDiv(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doStrictFloorDiv(long x, long y) {
+ try {
+ return StrictMath.floorDiv(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doStrictFloorMod(int x, int y) {
+ try {
+ return StrictMath.floorMod(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Invoke floorDiv and return the result or any exception.
+ * @param x the x value
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
+ static Object doStrictFloorMod(long x, long y) {
+ try {
+ return StrictMath.floorMod(x, y);
+ } catch (ArithmeticException ae) {
+ return ae;
+ }
+ }
+
+ /**
+ * Returns a boolean by comparing the result and the expected value.
+ * The equals method is not defined for ArithmeticException but it is
+ * desirable to have equals return true if the expected and the result
+ * both threw the same exception (class and message.)
+ *
+ * @param result the result from testing the method
+ * @param expected the expected value
+ * @return true if the result is equal to the expected values; false otherwise.
+ */
+ static boolean resultEquals(Object result, Object expected) {
+ if (result.getClass() != expected.getClass()) {
+ fail("FAIL: Result type mismatch, %s; expected: %s%n",
+ result.getClass().getName(), expected.getClass().getName());
+ return false;
+ }
+
+ if (result.equals(expected)) {
+ return true;
+ }
+ // Handle special case to compare ArithmeticExceptions
+ if (result instanceof ArithmeticException && expected instanceof ArithmeticException) {
+ ArithmeticException ae1 = (ArithmeticException)result;
+ ArithmeticException ae2 = (ArithmeticException)expected;
+ return ae1.getMessage().equals(ae2.getMessage());
+ }
+ return false;
+ }
+
+}
--- a/jdk/test/java/lang/invoke/BigArityTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/invoke/BigArityTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -26,7 +26,7 @@
/* @test
* @summary High arity invocations, up to the maximum of 255 arguments
* @compile BigArityTest.java
- * @run junit/othervm -DBigArityTest.ITERATION_COUNT=1 test.java.lang.invoke.BigArityTest
+ * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -esa -DBigArityTest.ITERATION_COUNT=1 test.java.lang.invoke.BigArityTest
*/
package test.java.lang.invoke;
--- a/jdk/test/java/lang/invoke/CallSiteTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/invoke/CallSiteTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -28,7 +28,7 @@
*
* @build indify.Indify
* @compile CallSiteTest.java
- * @run main/othervm
+ * @run main/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
* indify.Indify
* --expand-properties --classpath ${test.classes}
* --java test.java.lang.invoke.CallSiteTest
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -26,7 +26,7 @@
/* @test
* @summary unit tests for java.lang.invoke.MethodHandles
* @compile MethodHandlesTest.java remote/RemoteExample.java
- * @run junit/othervm test.java.lang.invoke.MethodHandlesTest
+ * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -esa test.java.lang.invoke.MethodHandlesTest
*/
package test.java.lang.invoke;
--- a/jdk/test/java/lang/invoke/RicochetTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/lang/invoke/RicochetTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -25,7 +25,7 @@
/* @test
* @summary unit tests for recursive method handles
- * @run junit/othervm -DRicochetTest.MAX_ARITY=50 test.java.lang.invoke.RicochetTest
+ * @run junit/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -DRicochetTest.MAX_ARITY=10 test.java.lang.invoke.RicochetTest
*/
/*
* @ignore The following test creates an unreasonable number of adapters in -Xcomp mode (7049122)
--- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,29 +27,16 @@
* @library ..
*/
-import java.io.*;
import java.net.*;
-import java.nio.*;
import java.nio.channels.*;
-import java.nio.charset.*;
import java.util.*;
public class AdaptDatagramSocket {
static java.io.PrintStream out = System.out;
-
static Random rand = new Random();
- static final int ECHO_PORT = 7;
- static final int DISCARD_PORT = 9;
- static final String REMOTE_HOST = TestUtil.HOST;
-
- static final InetSocketAddress echoAddress
- = new InetSocketAddress(REMOTE_HOST, ECHO_PORT);
- static final InetSocketAddress discardAddress
- = new InetSocketAddress(REMOTE_HOST, DISCARD_PORT);
-
static String toString(DatagramPacket dp) {
return ("DatagramPacket[off=" + dp.getOffset()
+ ", len=" + dp.getLength()
@@ -88,10 +75,11 @@
out.println("rtt: " + (System.currentTimeMillis() - start));
out.println("post op: " + toString(op) + " ip: " + toString(ip));
- for (int i = 0; i < ip.getLength(); i++)
+ for (int i = 0; i < ip.getLength(); i++) {
if (ip.getData()[ip.getOffset() + i]
!= op.getData()[op.getOffset() + i])
throw new Exception("Incorrect data received");
+ }
if (!(ip.getSocketAddress().equals(dst))) {
throw new Exception("Incorrect sender address, expected: " + dst
@@ -130,8 +118,9 @@
ds.setSoTimeout(timeout);
out.println("timeout: " + ds.getSoTimeout());
- for (int i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++) {
test(ds, dst, shouldTimeout);
+ }
// Leave the socket open so that we don't reuse the old src address
//ds.close();
@@ -139,10 +128,23 @@
}
public static void main(String[] args) throws Exception {
- test(echoAddress, 0, false, false);
- test(echoAddress, 0, false, true);
- test(echoAddress, 5000, false, false);
- test(discardAddress, 10, true, false);
+ // need an UDP echo server
+ try (TestServers.UdpEchoServer echoServer
+ = TestServers.UdpEchoServer.startNewServer(100)) {
+ final InetSocketAddress address
+ = new InetSocketAddress(echoServer.getAddress(),
+ echoServer.getPort());
+ test(address, 0, false, false);
+ test(address, 0, false, true);
+ test(address, 5000, false, false);
+ }
+ try (TestServers.UdpDiscardServer discardServer
+ = TestServers.UdpDiscardServer.startNewServer()) {
+ final InetSocketAddress address
+ = new InetSocketAddress(discardServer.getAddress(),
+ discardServer.getPort());
+ test(address, 10, true, false);
+ }
}
}
--- a/jdk/test/java/nio/channels/DatagramChannel/IsBound.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/DatagramChannel/IsBound.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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
@@ -34,21 +34,25 @@
public class IsBound {
public static void main(String argv[]) throws Exception {
- InetSocketAddress isa = new InetSocketAddress(
- InetAddress.getByName(TestUtil.HOST), 13);
- ByteBuffer bb = ByteBuffer.allocateDirect(256);
- bb.put("hello".getBytes());
- bb.flip();
+ try (TestServers.UdpDayTimeServer daytimeServer
+ = TestServers.UdpDayTimeServer.startNewServer(100)) {
+ InetSocketAddress isa = new InetSocketAddress(
+ daytimeServer.getAddress(),
+ daytimeServer.getPort());
+ ByteBuffer bb = ByteBuffer.allocateDirect(256);
+ bb.put("hello".getBytes());
+ bb.flip();
- DatagramChannel dc = DatagramChannel.open();
- dc.send(bb, isa);
- if(!dc.socket().isBound())
- throw new Exception("Test failed");
- dc.close();
+ DatagramChannel dc = DatagramChannel.open();
+ dc.send(bb, isa);
+ if(!dc.socket().isBound())
+ throw new Exception("Test failed");
+ dc.close();
- dc = DatagramChannel.open();
- if(dc.socket().isBound())
- throw new Exception("Test failed");
- dc.close();
+ dc = DatagramChannel.open();
+ if(dc.socket().isBound())
+ throw new Exception("Test failed");
+ dc.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/DatagramChannel/IsConnected.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/DatagramChannel/IsConnected.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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
@@ -28,21 +28,23 @@
*/
import java.net.*;
-import java.nio.*;
import java.nio.channels.*;
public class IsConnected {
public static void main(String argv[]) throws Exception {
- InetSocketAddress isa = new InetSocketAddress(
- InetAddress.getByName(TestUtil.HOST), 13);
- DatagramChannel dc = DatagramChannel.open();
- dc.configureBlocking(true);
- dc.connect(isa);
- if (!dc.isConnected())
- throw new RuntimeException("channel.isConnected inconsistent");
- if (!dc.socket().isConnected())
- throw new RuntimeException("socket.isConnected inconsistent");
- dc.close();
+ try (TestServers.UdpDayTimeServer daytimeServer
+ = TestServers.UdpDayTimeServer.startNewServer(100)) {
+ InetSocketAddress isa = new InetSocketAddress(
+ daytimeServer.getAddress(), daytimeServer.getPort());
+ DatagramChannel dc = DatagramChannel.open();
+ dc.configureBlocking(true);
+ dc.connect(isa);
+ if (!dc.isConnected())
+ throw new RuntimeException("channel.isConnected inconsistent");
+ if (!dc.socket().isConnected())
+ throw new RuntimeException("socket.isConnected inconsistent");
+ dc.close();
+ }
}
}
--- a/jdk/test/java/nio/channels/FileChannel/MapTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/FileChannel/MapTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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
@@ -22,6 +22,7 @@
*/
/* @test
+ * @bug 4429043 8002180
* @summary Test file mapping with FileChannel
* @run main/othervm MapTest
*/
@@ -29,7 +30,10 @@
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.*;
-import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.Files;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.charset.StandardCharsets.*;
import java.util.Random;
@@ -39,6 +43,7 @@
public class MapTest {
+ private static PrintStream out = System.out;
private static PrintStream err = System.err;
private static Random generator = new Random();
@@ -51,15 +56,21 @@
blah = File.createTempFile("blah", null);
blah.deleteOnExit();
initTestFile(blah);
- err.println("Test file " + blah + " initialized");
- testZero();
- err.println("Zero size: OK");
- testRead();
- err.println("Read: OK");
- testWrite();
- err.println("Write: OK");
- testHighOffset();
- err.println("High offset: OK");
+ try {
+ out.println("Test file " + blah + " initialized");
+ testZero();
+ out.println("Zero size: OK");
+ testRead();
+ out.println("Read: OK");
+ testWrite();
+ out.println("Write: OK");
+ testHighOffset();
+ out.println("High offset: OK");
+ testExceptions();
+ out.println("Exceptions: OK");
+ } finally {
+ blah.delete();
+ }
}
/**
@@ -77,30 +88,25 @@
* ability to index into a file of multiple pages is tested.
*/
private static void initTestFile(File blah) throws Exception {
- FileOutputStream fos = new FileOutputStream(blah);
- BufferedWriter awriter
- = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
-
- for(int i=0; i<4000; i++) {
- String number = new Integer(i).toString();
- for (int h=0; h<4-number.length(); h++)
- awriter.write("0");
- awriter.write(""+i);
- awriter.newLine();
+ try (BufferedWriter writer = Files.newBufferedWriter(blah.toPath(), ISO_8859_1)) {
+ for (int i=0; i<4000; i++) {
+ String number = new Integer(i).toString();
+ for (int h=0; h<4-number.length(); h++)
+ writer.write("0");
+ writer.write(""+i);
+ writer.newLine();
+ }
}
- awriter.flush();
- awriter.close();
}
/**
* Tests zero size file mapping
*/
private static void testZero() throws Exception {
- FileInputStream fis = new FileInputStream(blah);
- FileChannel c = fis.getChannel();
- MappedByteBuffer b = c.map(FileChannel.MapMode.READ_ONLY, 0, 0);
- c.close();
- fis.close();
+ try (FileInputStream fis = new FileInputStream(blah)) {
+ FileChannel fc = fis.getChannel();
+ MappedByteBuffer b = fc.map(MapMode.READ_ONLY, 0, 0);
+ }
}
/**
@@ -108,33 +114,32 @@
* from the ByteBuffer gets the right line number
*/
private static void testRead() throws Exception {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.setLength(4);
for (int x=0; x<1000; x++) {
- FileInputStream fis = new FileInputStream(blah);
- FileChannel c = fis.getChannel();
+ try (FileInputStream fis = new FileInputStream(blah)) {
+ FileChannel fc = fis.getChannel();
- long offset = generator.nextInt(10000);
- long expectedResult = offset / CHARS_PER_LINE;
- offset = expectedResult * CHARS_PER_LINE;
+ long offset = generator.nextInt(10000);
+ long expectedResult = offset / CHARS_PER_LINE;
+ offset = expectedResult * CHARS_PER_LINE;
- MappedByteBuffer b = c.map(FileChannel.MapMode.READ_ONLY,
- offset, 100);
+ MappedByteBuffer b = fc.map(MapMode.READ_ONLY,
+ offset, 100);
- for (int i=0; i<4; i++) {
- byte aByte = b.get(i);
- sb.setCharAt(i, (char)aByte);
- }
+ for (int i=0; i<4; i++) {
+ byte aByte = b.get(i);
+ sb.setCharAt(i, (char)aByte);
+ }
- int result = Integer.parseInt(sb.toString());
- if (result != expectedResult) {
- err.println("I expected "+expectedResult);
- err.println("I got "+result);
- throw new Exception("Read test failed");
+ int result = Integer.parseInt(sb.toString());
+ if (result != expectedResult) {
+ err.println("I expected "+expectedResult);
+ err.println("I got "+result);
+ throw new Exception("Read test failed");
+ }
}
- c.close();
- fis.close();
}
}
@@ -143,46 +148,159 @@
* written out to the file can be read back in
*/
private static void testWrite() throws Exception {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.setLength(4);
for (int x=0; x<1000; x++) {
- RandomAccessFile raf = new RandomAccessFile(blah, "rw");
- FileChannel c = raf.getChannel();
+ try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {
+ FileChannel fc = raf.getChannel();
+
+ long offset = generator.nextInt(1000);
+ MappedByteBuffer b = fc.map(MapMode.READ_WRITE,
+ offset, 100);
- long offset = generator.nextInt(1000);
- MappedByteBuffer b = c.map(FileChannel.MapMode.READ_WRITE,
- offset, 100);
+ for (int i=0; i<4; i++) {
+ b.put(i, (byte)('0' + i));
+ }
- for (int i=0; i<4; i++) {
- b.put(i, (byte)('0' + i));
+ for (int i=0; i<4; i++) {
+ byte aByte = b.get(i);
+ sb.setCharAt(i, (char)aByte);
+ }
+ if (!sb.toString().equals("0123"))
+ throw new Exception("Write test failed");
}
-
- for (int i=0; i<4; i++) {
- byte aByte = b.get(i);
- sb.setCharAt(i, (char)aByte);
- }
- if (!sb.toString().equals("0123"))
- throw new Exception("Write test failed");
- c.close();
- raf.close();
}
}
private static void testHighOffset() throws Exception {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.setLength(4);
for (int x=0; x<1000; x++) {
- RandomAccessFile raf = new RandomAccessFile(blah, "rw");
- FileChannel fc = raf.getChannel();
- long offset = 66000;
- MappedByteBuffer b = fc.map(FileChannel.MapMode.READ_WRITE,
- offset, 100);
+ try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {
+ FileChannel fc = raf.getChannel();
+ long offset = 66000;
+ MappedByteBuffer b = fc.map(MapMode.READ_WRITE,
+ offset, 100);
+ }
+ }
+ }
+
+ /**
+ * Test exceptions specified by map method
+ */
+ private static void testExceptions() throws Exception {
+ // check exceptions when channel opened for read access
+ try (FileChannel fc = FileChannel.open(blah.toPath(), READ)) {
+ testExceptions(fc);
+
+ checkException(fc, MapMode.READ_WRITE, 0L, fc.size(),
+ NonWritableChannelException.class);
+
+ checkException(fc, MapMode.READ_WRITE, -1L, fc.size(),
+ NonWritableChannelException.class, IllegalArgumentException.class);
+
+ checkException(fc, MapMode.READ_WRITE, 0L, -1L,
+ NonWritableChannelException.class, IllegalArgumentException.class);
+
+ checkException(fc, MapMode.PRIVATE, 0L, fc.size(),
+ NonWritableChannelException.class);
- fc.close();
- raf.close();
+ checkException(fc, MapMode.PRIVATE, -1L, fc.size(),
+ NonWritableChannelException.class, IllegalArgumentException.class);
+
+ checkException(fc, MapMode.PRIVATE, 0L, -1L,
+ NonWritableChannelException.class, IllegalArgumentException.class);
+ }
+
+ // check exceptions when channel opened for write access
+ try (FileChannel fc = FileChannel.open(blah.toPath(), WRITE)) {
+ testExceptions(fc);
+
+ checkException(fc, MapMode.READ_ONLY, 0L, fc.size(),
+ NonReadableChannelException.class);
+
+ checkException(fc, MapMode.READ_ONLY, -1L, fc.size(),
+ NonReadableChannelException.class, IllegalArgumentException.class);
+
+ /*
+ * implementation/spec mismatch, these tests disabled for now
+ */
+ //checkException(fc, MapMode.READ_WRITE, 0L, fc.size(),
+ // NonWritableChannelException.class);
+ //checkException(fc, MapMode.PRIVATE, 0L, fc.size(),
+ // NonWritableChannelException.class);
+ }
+
+ // check exceptions when channel opened for read and write access
+ try (FileChannel fc = FileChannel.open(blah.toPath(), READ, WRITE)) {
+ testExceptions(fc);
}
}
+ private static void testExceptions(FileChannel fc) throws IOException {
+ checkException(fc, null, 0L, fc.size(),
+ NullPointerException.class);
+
+ checkException(fc, MapMode.READ_ONLY, -1L, fc.size(),
+ IllegalArgumentException.class);
+
+ checkException(fc, null, -1L, fc.size(),
+ IllegalArgumentException.class, NullPointerException.class);
+
+ checkException(fc, MapMode.READ_ONLY, 0L, -1L,
+ IllegalArgumentException.class);
+
+ checkException(fc, null, 0L, -1L,
+ IllegalArgumentException.class, NullPointerException.class);
+
+ checkException(fc, MapMode.READ_ONLY, 0L, Integer.MAX_VALUE + 1L,
+ IllegalArgumentException.class);
+
+ checkException(fc, null, 0L, Integer.MAX_VALUE + 1L,
+ IllegalArgumentException.class, NullPointerException.class);
+
+ checkException(fc, MapMode.READ_ONLY, Long.MAX_VALUE, 1L,
+ IllegalArgumentException.class);
+
+ checkException(fc, null, Long.MAX_VALUE, 1L,
+ IllegalArgumentException.class, NullPointerException.class);
+
+ }
+
+ /**
+ * Checks that FileChannel map throws one of the expected exceptions
+ * when invoked with the given inputs.
+ */
+ private static void checkException(FileChannel fc,
+ MapMode mode,
+ long position,
+ long size,
+ Class<?>... expected)
+ throws IOException
+ {
+ Exception exc = null;
+ try {
+ fc.map(mode, position, size);
+ } catch (Exception actual) {
+ exc = actual;
+ }
+ if (exc != null) {
+ for (Class<?> clazz: expected) {
+ if (clazz.isInstance(exc)) {
+ return;
+ }
+ }
+ }
+ System.err.println("Expected one of");
+ for (Class<?> clazz: expected) {
+ System.out.println(clazz);
+ }
+ if (exc == null) {
+ throw new RuntimeException("No expection thrown");
+ } else {
+ throw new RuntimeException("Unexpected exception thrown", exc);
+ }
+ }
}
--- a/jdk/test/java/nio/channels/FileChannel/Truncate.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/FileChannel/Truncate.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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
@@ -22,14 +22,16 @@
*/
/* @test
- * @bug 6191269 6709457
+ * @bug 6191269 6709457 8000330
* @summary Test truncate method of FileChannel
*/
import java.io.*;
import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
+import java.nio.channels.*;
+import java.nio.file.Files;
import static java.nio.file.StandardOpenOption.*;
+import static java.nio.charset.StandardCharsets.*;
import java.util.Random;
@@ -46,6 +48,7 @@
try {
basicTest(blah);
appendTest(blah);
+ exceptionTests(blah);
} finally {
blah.delete();
}
@@ -66,15 +69,22 @@
if (fc.size() != testSize)
throw new RuntimeException("Size failed");
- long position = generator.nextInt((int)testSize);
+ long position = generator.nextInt((int)testSize*2);
fc.position(position);
- long newSize = generator.nextInt((int)testSize);
+ long newSize = generator.nextInt((int)testSize*2);
fc.truncate(newSize);
- if (fc.size() != newSize)
- throw new RuntimeException("Truncate failed");
+ // check new size
+ if (newSize > testSize) {
+ if (fc.size() != testSize)
+ throw new RuntimeException("Attempt to expand file changed size");
+ } else {
+ if (fc.size() != newSize)
+ throw new RuntimeException("Unexpected size after truncate");
+ }
+ // check new position
if (position > newSize) {
if (fc.position() != newSize)
throw new RuntimeException("Position greater than size");
@@ -115,20 +125,90 @@
}
/**
+ * Test exceptions specified by truncate method
+ */
+ static void exceptionTests(File blah) throws Exception {
+ // check exceptions when channel opened for read access
+ try (FileChannel fc = FileChannel.open(blah.toPath(), READ)) {
+ long size = fc.size();
+
+ // open channel
+ checkException(fc, 0L, NonWritableChannelException.class);
+
+ checkException(fc, -1L, NonWritableChannelException.class,
+ IllegalArgumentException.class);
+
+ checkException(fc, size+1L, NonWritableChannelException.class);
+
+ // closed channel
+ fc.close();
+
+ checkException(fc, 0L, ClosedChannelException.class);
+
+ checkException(fc, -1L, ClosedChannelException.class,
+ IllegalArgumentException.class);
+
+ checkException(fc, size+1L, ClosedChannelException.class);
+ }
+
+ // check exceptions when channel opened for write access
+ try (FileChannel fc = FileChannel.open(blah.toPath(), WRITE)) {
+ long size = fc.size();
+
+ // open channel
+ checkException(fc, -1L, IllegalArgumentException.class);
+
+ // closed channel
+ fc.close();
+
+ checkException(fc, 0L, ClosedChannelException.class);
+
+ checkException(fc, -1L, ClosedChannelException.class,
+ IllegalArgumentException.class);
+
+ checkException(fc, size+1L, ClosedChannelException.class);
+ }
+ }
+
+ /**
+ * Checks that FileChannel truncate throws one of the expected exceptions
+ * when invoked with the given size.
+ */
+ private static void checkException(FileChannel fc, long size, Class<?>... expected)
+ throws IOException
+ {
+ Exception exc = null;
+ try {
+ fc.truncate(size);
+ } catch (Exception actual) {
+ exc = actual;
+ }
+ if (exc != null) {
+ for (Class<?> clazz: expected) {
+ if (clazz.isInstance(exc)) {
+ return;
+ }
+ }
+ }
+ System.err.println("Expected one of");
+ for (Class<?> clazz: expected) {
+ System.err.println(clazz);
+ }
+ if (exc == null) {
+ throw new RuntimeException("No expection thrown");
+ } else {
+ throw new RuntimeException("Unexpected exception thrown", exc);
+ }
+ }
+
+ /**
* Creates file blah of specified size in bytes.
- *
*/
private static void initTestFile(File blah, long size) throws Exception {
- if (blah.exists())
- blah.delete();
- FileOutputStream fos = new FileOutputStream(blah);
- BufferedWriter awriter
- = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
-
- for(int i=0; i<size; i++) {
- awriter.write("e");
+ try (BufferedWriter writer = Files.newBufferedWriter(blah.toPath(), ISO_8859_1)) {
+ for(int i=0; i<size; i++) {
+ writer.write("e");
+ }
}
- awriter.flush();
- awriter.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/Alias.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/Selector/Alias.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,11 @@
* @library ..
*/
-import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
import java.util.*;
-import java.nio.channels.spi.SelectorProvider;
public class Alias {
@@ -40,18 +39,26 @@
static int LIMIT = 20; // Hangs after just 1 if problem is present
public static void main(String[] args) throws Exception {
- test1();
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ test1(daytimeServer);
+ }
}
- public static void test1() throws Exception {
+ static void test1(TestServers.DayTimeServer daytimeServer) throws Exception {
Selector selector = SelectorProvider.provider().openSelector();
- InetAddress myAddress=InetAddress.getByName(TestUtil.HOST);
- InetSocketAddress isa = new InetSocketAddress(myAddress,13);
+ InetAddress myAddress = daytimeServer.getAddress();
+ InetSocketAddress isa
+ = new InetSocketAddress(myAddress,
+ daytimeServer.getPort());
for (int j=0; j<LIMIT; j++) {
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
boolean result = sc.connect(isa);
+
+ // On some platforms - given that we're using a local server,
+ // we may not enter into the if () { } statement below...
if (!result) {
SelectionKey key = sc.register(selector,
SelectionKey.OP_CONNECT);
--- a/jdk/test/java/nio/channels/Selector/BasicConnect.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/Selector/BasicConnect.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,10 @@
* @library ..
*/
-import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.SelectorProvider;
-import java.nio.charset.*;
import java.util.*;
@@ -44,52 +42,57 @@
public class BasicConnect {
- static final int PORT = 7; // echo
- static final String HOST = TestUtil.HOST;
-
public static void main(String[] args) throws Exception {
Selector connectSelector =
SelectorProvider.provider().openSelector();
- InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(HOST), PORT);
- SocketChannel sc = SocketChannel.open();
- sc.configureBlocking(false);
- boolean result = sc.connect(isa);
- while (!result) {
- SelectionKey connectKey = sc.register(connectSelector,
- SelectionKey.OP_CONNECT);
- int keysAdded = connectSelector.select();
- if (keysAdded > 0) {
- Set readyKeys = connectSelector.selectedKeys();
- Iterator i = readyKeys.iterator();
- while (i.hasNext()) {
- SelectionKey sk = (SelectionKey)i.next();
- i.remove();
- SocketChannel nextReady = (SocketChannel)sk.channel();
- result = nextReady.finishConnect();
- if (result)
- sk.cancel();
+ try (TestServers.EchoServer echoServer
+ = TestServers.EchoServer.startNewServer(100)) {
+ InetSocketAddress isa
+ = new InetSocketAddress(echoServer.getAddress(),
+ echoServer.getPort());
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ boolean result = sc.connect(isa);
+ if (result) {
+ System.out.println("Socket immediately connected on "
+ + System.getProperty("os.name")
+ + ": " + sc);
+ }
+ while (!result) {
+ SelectionKey connectKey = sc.register(connectSelector,
+ SelectionKey.OP_CONNECT);
+ int keysAdded = connectSelector.select();
+ if (keysAdded > 0) {
+ Set readyKeys = connectSelector.selectedKeys();
+ Iterator i = readyKeys.iterator();
+ while (i.hasNext()) {
+ SelectionKey sk = (SelectionKey)i.next();
+ i.remove();
+ SocketChannel nextReady = (SocketChannel)sk.channel();
+ result = nextReady.finishConnect();
+ if (result)
+ sk.cancel();
+ }
}
}
- }
- byte[] bs = new byte[] { (byte)0xca, (byte)0xfe,
- (byte)0xba, (byte)0xbe };
- ByteBuffer bb = ByteBuffer.wrap(bs);
- sc.configureBlocking(true);
- sc.write(bb);
- bb.rewind();
+ byte[] bs = new byte[] { (byte)0xca, (byte)0xfe,
+ (byte)0xba, (byte)0xbe };
+ ByteBuffer bb = ByteBuffer.wrap(bs);
+ sc.configureBlocking(true);
+ sc.write(bb);
+ bb.rewind();
- ByteBuffer bb2 = ByteBuffer.allocateDirect(100);
- int n = sc.read(bb2);
- bb2.flip();
+ ByteBuffer bb2 = ByteBuffer.allocateDirect(100);
+ int n = sc.read(bb2);
+ bb2.flip();
- sc.close();
- connectSelector.close();
+ sc.close();
+ connectSelector.close();
- if (!bb.equals(bb2))
- throw new Exception("Echoed bytes incorrect: Sent "
- + bb + ", got " + bb2);
+ if (!bb.equals(bb2))
+ throw new Exception("Echoed bytes incorrect: Sent "
+ + bb + ", got " + bb2);
+ }
}
-
}
--- a/jdk/test/java/nio/channels/Selector/Connect.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/Selector/Connect.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,11 @@
* @library ..
*/
-import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
import java.util.*;
-import java.nio.channels.spi.SelectorProvider;
public class Connect {
@@ -40,12 +39,18 @@
static int LIMIT = 100;
public static void main(String[] args) throws Exception {
- scaleTest();
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(50)) {
+ scaleTest(daytimeServer);
+ }
}
- public static void scaleTest() throws Exception {
- InetAddress myAddress=InetAddress.getByName(TestUtil.HOST);
- InetSocketAddress isa = new InetSocketAddress(myAddress,13);
+ static void scaleTest(TestServers.DayTimeServer daytimeServer)
+ throws Exception
+ {
+ InetAddress myAddress = daytimeServer.getAddress();
+ InetSocketAddress isa
+ = new InetSocketAddress(myAddress, daytimeServer.getPort());
for (int j=0; j<LIMIT; j++) {
SocketChannel sc = SocketChannel.open();
--- a/jdk/test/java/nio/channels/Selector/ConnectWrite.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/Selector/ConnectWrite.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,23 +27,25 @@
* @library ..
*/
-import java.io.*;
import java.net.*;
-import java.nio.*;
import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
import java.util.*;
-import java.nio.channels.spi.SelectorProvider;
public class ConnectWrite {
public static void main(String[] args) throws Exception {
- test1(13);
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(25)) {
+ test1(daytimeServer);
+ }
}
- public static void test1(int port) throws Exception {
+ static void test1(TestServers.DayTimeServer daytimeServer) throws Exception {
Selector selector = SelectorProvider.provider().openSelector();
- InetAddress myAddress=InetAddress.getByName(TestUtil.HOST);
- InetSocketAddress isa = new InetSocketAddress(myAddress, port);
+ InetAddress myAddress = daytimeServer.getAddress();
+ InetSocketAddress isa
+ = new InetSocketAddress(myAddress, daytimeServer.getPort());
SocketChannel sc = SocketChannel.open();
try {
sc.configureBlocking(false);
--- a/jdk/test/java/nio/channels/Selector/KeysReady.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/Selector/KeysReady.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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
@@ -28,21 +28,15 @@
*/
import java.net.*;
-import java.io.*;
-import java.nio.*;
import java.nio.channels.*;
-import java.nio.charset.*;
import java.nio.channels.spi.SelectorProvider;
public class KeysReady {
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
- static void test() throws Exception {
+ static void test(TestServers.DayTimeServer dayTimeServer) throws Exception {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(dayTimeServer.getAddress(),
+ dayTimeServer.getPort());
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(isa);
@@ -64,7 +58,10 @@
}
public static void main(String[] args) throws Exception {
- test();
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(50)) {
+ test(daytimeServer);
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Thu Nov 15 00:54:54 2012 +0000
@@ -35,19 +35,16 @@
static java.io.PrintStream out = System.out;
- static final int ECHO_PORT = 7;
- static final int DAYTIME_PORT = 13;
- static final String REMOTE_HOST = TestUtil.HOST;
- static final String VERY_REMOTE_HOST = TestUtil.FAR_HOST;
-
- static void test(String hn, int timeout, boolean shouldTimeout)
+ static void test(TestServers.DayTimeServer dayTimeServer,
+ int timeout,
+ boolean shouldTimeout)
throws Exception
{
out.println();
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(hn),
- DAYTIME_PORT);
+ = new InetSocketAddress(dayTimeServer.getAddress(),
+ dayTimeServer.getPort());
SocketChannel sc = SocketChannel.open();
Socket so = sc.socket();
out.println("opened: " + so);
@@ -116,13 +113,16 @@
}
}
- static void testRead(String hn, int timeout, boolean shouldTimeout)
+ static void testRead(TestServers.EchoServer echoServer,
+ int timeout,
+ boolean shouldTimeout)
throws Exception
{
out.println();
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(hn), ECHO_PORT);
+ = new InetSocketAddress(echoServer.getAddress(),
+ echoServer.getPort());
SocketChannel sc = SocketChannel.open();
sc.connect(isa);
Socket so = sc.socket();
@@ -134,22 +134,38 @@
out.println("timeout: " + so.getSoTimeout());
testRead(so, shouldTimeout);
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++) {
testRead(so, shouldTimeout);
+ }
sc.close();
}
public static void main(String[] args) throws Exception {
- test(REMOTE_HOST, 0, false);
- test(REMOTE_HOST, 1000, false);
- test(VERY_REMOTE_HOST, 10, true);
+ try (TestServers.DayTimeServer dayTimeServer
+ = TestServers.DayTimeServer.startNewServer()) {
+ test(dayTimeServer, 0, false);
+ test(dayTimeServer, 1000, false);
+ }
- testRead(REMOTE_HOST, 0, false);
- testRead(REMOTE_HOST, 8000, false);
- testRead(VERY_REMOTE_HOST, 10, true);
+ try (TestServers.DayTimeServer lingerDayTimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ // this test no longer really test the connection timeout
+ // since there is no way to prevent the server from eagerly
+ // accepting connection...
+ test(lingerDayTimeServer, 10, true);
+ }
- }
+ try (TestServers.EchoServer echoServer
+ = TestServers.EchoServer.startNewServer()) {
+ testRead(echoServer, 0, false);
+ testRead(echoServer, 8000, false);
+ }
+ try (TestServers.EchoServer lingerEchoServer
+ = TestServers.EchoServer.startNewServer(100)) {
+ testRead(lingerEchoServer, 10, true);
+ }
+ }
}
--- a/jdk/test/java/nio/channels/SocketChannel/Basic.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/Basic.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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
@@ -36,13 +36,10 @@
static java.io.PrintStream out = System.out;
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
- static void test() throws Exception {
+ static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
SocketChannel sc = SocketChannel.open(isa);
out.println("opened: " + sc);
/*
@@ -76,7 +73,10 @@
}
public static void main(String[] args) throws Exception {
- test();
+ try (TestServers.DayTimeServer dayTimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ test(dayTimeServer);
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/BufferSize.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/BufferSize.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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
@@ -28,17 +28,10 @@
*/
import java.nio.channels.*;
-import java.net.*;
public class BufferSize {
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
public static void main(String[] args) throws Exception {
- InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
ServerSocketChannel sc = ServerSocketChannel.open();
try {
sc.socket().setReceiveBufferSize(-1);
--- a/jdk/test/java/nio/channels/SocketChannel/Connect.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/Connect.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,9 +27,9 @@
* @library ..
*/
+import java.net.*;
import java.nio.*;
import java.nio.channels.*;
-import java.net.*;
import java.util.*;
public class Connect {
@@ -37,21 +37,26 @@
private static final long INCREMENTAL_DELAY = 30L * 1000L;
public static void main(String args[]) throws Exception {
- test1(TestUtil.HOST);
+ try (TestServers.EchoServer echoServer
+ = TestServers.EchoServer.startNewServer(1000)) {
+ test1(echoServer);
+ }
try {
- test1(TestUtil.REFUSING_HOST);
+ TestServers.RefusingServer refusingServer
+ = TestServers.RefusingServer.startNewServer();
+ test1(refusingServer);
throw new Exception("Refused connection throws no exception");
} catch (ConnectException ce) {
// Correct result
}
}
- static void test1(String hostname) throws Exception {
+ static void test1(TestServers.AbstractServer server) throws Exception {
Selector selector;
SocketChannel sc;
SelectionKey sk;
InetSocketAddress isa = new InetSocketAddress(
- InetAddress.getByName (hostname), 80);
+ server.getAddress(), server.getPort());
sc = SocketChannel.open();
sc.configureBlocking(false);
--- a/jdk/test/java/nio/channels/SocketChannel/ConnectState.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/ConnectState.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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
@@ -30,20 +30,39 @@
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
public class ConnectState {
static PrintStream log = System.err;
- static String REMOTE_HOST = TestUtil.HOST;
- static int REMOTE_PORT = 7; // echo
static InetSocketAddress remote;
final static int ST_UNCONNECTED = 0;
final static int ST_PENDING = 1;
final static int ST_CONNECTED = 2;
final static int ST_CLOSED = 3;
+ final static int ST_PENDING_OR_CONNECTED = 4;
+ // NO exceptions expected
+ final static Collection<Class<?>> NONE = Collections.emptySet();
+
+ // make a set of expected exception.
+ static Collection<Class<?>> expectedExceptions(Class<?>... expected) {
+ final Collection<Class<?>> exceptions;
+ if (expected.length == 0) {
+ exceptions = NONE;
+ } else if (expected.length == 1) {
+ assert expected[0] != null;
+ exceptions = Collections.<Class<?>>singleton(expected[0]);
+ } else {
+ exceptions = new HashSet<>(Arrays.asList(expected));
+ }
+ return exceptions;
+ }
static abstract class Test {
@@ -76,37 +95,65 @@
check(!sc.isConnectionPending(), "!isConnectionPending");
check(sc.isOpen(), "isOpen");
break;
+ case ST_PENDING_OR_CONNECTED:
+ check(sc.isConnected() || sc.isConnectionPending(),
+ "isConnected || isConnectionPending");
+ check(sc.isOpen(), "isOpen");
+ break;
}
}
- Test(String name, Class exception, int state) throws Exception {
+ Test(String name, Class<?> exception, int state) throws Exception {
+ this(name, expectedExceptions(exception), state);
+ }
+
+ // On some architecture we may need to accept several exceptions.
+ // For instance on Solaris, when using a server colocated on the
+ // machine we cannot guarantee that we will get a
+ // ConnectionPendingException when connecting twice on the same
+ // non-blocking socket. We may instead get a an
+ // AlreadyConnectedException, which is also valid: it simply means
+ // that the first connection has been immediately accepted.
+ Test(String name, Collection<Class<?>> exceptions, int state)
+ throws Exception {
SocketChannel sc = SocketChannel.open();
- String note = null;
+ String note;
try {
try {
note = go(sc);
} catch (Exception x) {
- if (exception != null) {
+ Class<?> expectedExceptionClass = null;
+ for (Class<?> exception : exceptions) {
if (exception.isInstance(x)) {
log.println(name + ": As expected: "
+ x);
+ expectedExceptionClass = exception;
check(sc, state);
- return;
- } else {
- throw new Exception(name
+ break;
+ }
+ }
+ if (expectedExceptionClass == null
+ && !exceptions.isEmpty()) {
+ // we had an exception, but it's not of the set of
+ // exceptions we expected.
+ throw new Exception(name
+ ": Incorrect exception",
x);
- }
- } else {
+ } else if (exceptions.isEmpty()) {
+ // we didn't expect any exception
throw new Exception(name
+ ": Unexpected exception",
x);
}
+ // if we reach here, we have our expected exception
+ assert expectedExceptionClass != null;
+ return;
}
- if (exception != null)
+ if (!exceptions.isEmpty()) {
throw new Exception(name
+ ": Expected exception not thrown: "
- + exception);
+ + exceptions.iterator().next());
+ }
check(sc, state);
log.println(name + ": Returned normally"
+ ((note != null) ? ": " + note : ""));
@@ -123,6 +170,7 @@
new Test("Read unconnected", NotYetConnectedException.class,
ST_UNCONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
ByteBuffer b = ByteBuffer.allocateDirect(1024);
sc.read(b);
@@ -131,19 +179,22 @@
new Test("Write unconnected", NotYetConnectedException.class,
ST_UNCONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
ByteBuffer b = ByteBuffer.allocateDirect(1024);
sc.write(b);
return null;
}};
- new Test("Simple connect", null, ST_CONNECTED) {
+ new Test("Simple connect", NONE, ST_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.connect(remote);
return null;
}};
- new Test("Simple connect & finish", null, ST_CONNECTED) {
+ new Test("Simple connect & finish", NONE, ST_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.connect(remote);
if (!sc.finishConnect())
@@ -153,6 +204,7 @@
new Test("Double connect",
AlreadyConnectedException.class, ST_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.connect(remote);
sc.connect(remote);
@@ -161,12 +213,16 @@
new Test("Finish w/o start",
NoConnectionPendingException.class, ST_UNCONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.finishConnect();
return null;
}};
- new Test("NB simple connect", null, ST_CONNECTED) {
+ // Note: using our local EchoServer rather than echo on a distant
+ // host - we see that Tries to finish = 0 (instead of ~ 18).
+ new Test("NB simple connect", NONE, ST_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.configureBlocking(false);
sc.connect(remote);
@@ -179,8 +235,15 @@
return ("Tries to finish = " + n);
}};
+ // Note: using our local EchoServer rather than echo on a distant
+ // host - we cannot guarantee that this test will get a
+ // a ConnectionPendingException: it may get an
+ // AlreadyConnectedException, so we should allow for both.
new Test("NB double connect",
- ConnectionPendingException.class, ST_PENDING) {
+ expectedExceptions(ConnectionPendingException.class,
+ AlreadyConnectedException.class),
+ ST_PENDING_OR_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.configureBlocking(false);
sc.connect(remote);
@@ -190,13 +253,15 @@
new Test("NB finish w/o start",
NoConnectionPendingException.class, ST_UNCONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.configureBlocking(false);
sc.finishConnect();
return null;
}};
- new Test("NB connect, B finish", null, ST_CONNECTED) {
+ new Test("NB connect, B finish", NONE, ST_CONNECTED) {
+ @Override
String go(SocketChannel sc) throws Exception {
sc.configureBlocking(false);
sc.connect(remote);
@@ -208,9 +273,12 @@
}
public static void main(String[] args) throws Exception {
- remote = new InetSocketAddress(InetAddress.getByName(REMOTE_HOST),
- REMOTE_PORT);
- tests();
+ try (TestServers.EchoServer echoServer
+ = TestServers.EchoServer.startNewServer(500)) {
+ remote = new InetSocketAddress(echoServer.getAddress(),
+ echoServer.getPort());
+ tests();
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/FinishConnect.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/FinishConnect.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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
@@ -36,21 +36,25 @@
public class FinishConnect {
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
public static void main(String[] args) throws Exception {
- test1(true, true);
- test1(true, false);
- test1(false, true);
- test1(false, false);
- test2();
+ try (TestServers.DayTimeServer dayTimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ test1(dayTimeServer, true, true);
+ test1(dayTimeServer, true, false);
+ test1(dayTimeServer, false, true);
+ test1(dayTimeServer, false, false);
+ test2(dayTimeServer);
+ }
}
- static void test1(boolean select, boolean setBlocking) throws Exception {
+ static void test1(TestServers.DayTimeServer daytimeServer,
+ boolean select,
+ boolean setBlocking)
+ throws Exception
+ {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
boolean connected = sc.connect(isa);
@@ -109,15 +113,27 @@
sc.close();
}
- static void test2() throws Exception {
+ static void test2(TestServers.DayTimeServer daytimeServer) throws Exception {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
boolean done = false;
int globalAttempts = 0;
+ int connectSuccess = 0;
while (!done) {
- if (globalAttempts++ > 50)
+ // When using a local daytime server it is not always possible
+ // to get a pending connection, as sc.connect(isa) may always
+ // return true.
+ // So we're going to throw the exception only if there was
+ // at least 1 case where we did not manage to connect.
+ if (globalAttempts++ > 50) {
+ if (globalAttempts == connectSuccess + 1) {
+ System.out.println("Can't fully test on "
+ + System.getProperty("os.name"));
+ break;
+ }
throw new RuntimeException("Failed to connect");
+ }
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
boolean connected = sc.connect(isa);
@@ -132,6 +148,9 @@
}
Thread.sleep(10);
}
+ if (connected) {
+ connectSuccess++;
+ }
sc.close();
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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
@@ -28,24 +28,19 @@
*/
import java.net.*;
-import java.io.*;
-import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.SelectorProvider;
import java.util.*;
public class IsConnectable {
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
- static void test() throws Exception {
+ static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
- sc.connect(isa);
+ final boolean immediatelyConnected = sc.connect(isa);
Selector selector = SelectorProvider.provider().openSelector();
try {
@@ -67,7 +62,12 @@
throw new Exception("Test failed: 4737146 detected");
}
} else {
- throw new Exception("Select failed");
+ if (!immediatelyConnected) {
+ throw new Exception("Select failed");
+ } else {
+ System.out.println("IsConnectable couldn't be fully tested for "
+ + System.getProperty("os.name"));
+ }
}
} finally {
sc.close();
@@ -76,7 +76,10 @@
}
public static void main(String[] args) throws Exception {
- test();
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ test(daytimeServer);
+ }
}
}
--- a/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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
@@ -28,18 +28,20 @@
*/
import java.net.*;
-import java.nio.*;
import java.nio.channels.*;
public class LocalAddress {
public static void main(String[] args) throws Exception {
- test1();
+ try (TestServers.EchoServer echoServer
+ = TestServers.EchoServer.startNewServer()) {
+ test1(echoServer);
+ }
}
- static void test1() throws Exception {
+ static void test1(TestServers.AbstractServer server) throws Exception {
InetAddress bogus = InetAddress.getByName("0.0.0.0");
InetSocketAddress saddr = new InetSocketAddress(
- InetAddress.getByName(TestUtil.HOST), 23);
+ server.getAddress(), server.getPort());
//Test1: connect only
SocketChannel sc = SocketChannel.open();
--- a/jdk/test/java/nio/channels/SocketChannel/Stream.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/Stream.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,22 +27,17 @@
* @library ..
*/
+import java.io.*;
import java.net.*;
-import java.io.*;
-import java.nio.*;
import java.nio.channels.*;
-import java.nio.charset.*;
public class Stream {
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
-
- static void test() throws Exception {
+ static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
InetSocketAddress isa
- = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
SocketChannel sc = SocketChannel.open();
sc.connect(isa);
sc.configureBlocking(false);
@@ -58,7 +53,9 @@
}
public static void main(String[] args) throws Exception {
- test();
+ try (TestServers.DayTimeServer dayTimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ test(dayTimeServer);
+ }
}
-
}
--- a/jdk/test/java/nio/channels/SocketChannel/VectorParams.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/SocketChannel/VectorParams.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,31 +27,31 @@
* @library ..
*/
+import java.io.*;
import java.net.*;
-import java.io.*;
import java.nio.*;
import java.nio.channels.*;
-import java.nio.charset.*;
public class VectorParams {
static java.io.PrintStream out = System.out;
- static final int DAYTIME_PORT = 13;
- static final String DAYTIME_HOST = TestUtil.HOST;
static final int testSize = 10;
static ByteBuffer[] bufs = null;
static InetSocketAddress isa = null;
public static void main(String[] args) throws Exception {
- initBufs();
- testSocketChannelVectorParams();
- testDatagramChannelVectorParams();
- testPipeVectorParams();
- testFileVectorParams();
+ try (TestServers.DayTimeServer daytimeServer
+ = TestServers.DayTimeServer.startNewServer(100)) {
+ initBufs(daytimeServer);
+ testSocketChannelVectorParams();
+ testDatagramChannelVectorParams();
+ testPipeVectorParams();
+ testFileVectorParams();
+ }
}
- static void initBufs() throws Exception {
+ static void initBufs(TestServers.DayTimeServer daytimeServer) throws Exception {
bufs = new ByteBuffer[testSize];
for(int i=0; i<testSize; i++) {
String source = "buffer" + i;
@@ -59,8 +59,8 @@
bufs[i].put(source.getBytes("8859_1"));
bufs[i].flip();
}
- isa = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST),
- DAYTIME_PORT);
+ isa = new InetSocketAddress(daytimeServer.getAddress(),
+ daytimeServer.getPort());
}
static void testSocketChannelVectorParams() throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/TestServers.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Test utility classes
+ *
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+
+public class TestServers {
+
+ private TestServers() { }
+
+ /**
+ * An abstract server identifies a server which listens on a port on on a
+ * given machine.
+ */
+ static abstract class AbstractServer {
+
+ private AbstractServer() {
+ }
+
+ public abstract int getPort();
+
+ public abstract InetAddress getAddress();
+ }
+
+ /**
+ * A downgraded type of AbstractServer which will refuse connections. Note:
+ * use it once and throw it away - this implementation opens an anonymous
+ * socket and closes it, returning the address of the closed socket. If
+ * other servers are started afterwards, the address/port might get reused
+ * and become connectable again - so it's not a good idea to assume that
+ * connections using this address/port will always be refused. Connections
+ * will be refused as long as the address/port of the refusing server has
+ * not been reused.
+ */
+ static class RefusingServer extends AbstractServer {
+
+ final InetAddress address;
+ final int port;
+
+ private RefusingServer(InetAddress address, int port) {
+ this.address = address;
+ this.port = port;
+ }
+
+ @Override
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public InetAddress getAddress() {
+ return address;
+ }
+
+ public static RefusingServer startNewServer() throws IOException {
+ ServerSocket socket = new ServerSocket(0, 100,
+ InetAddress.getLocalHost());
+ RefusingServer server = new RefusingServer(socket.getInetAddress(),
+ socket.getLocalPort());
+ socket.close();
+ return server;
+ }
+ }
+
+ /**
+ * An abstract class for implementing small TCP servers for the nio tests
+ * purposes. Disclaimer: This is a naive implementation that uses the old
+ * networking APIs (not those from {@code java.nio.*}) and shamelessly
+ * extends/creates Threads instead of using an executor service.
+ */
+ static abstract class AbstractTcpServer extends AbstractServer
+ implements Runnable, Closeable {
+
+ protected final long linger; // #of ms to wait before responding
+ private Thread acceptThread; // thread waiting for accept
+ // list of opened connections that should be closed on close.
+ private List<TcpConnectionThread> connections = new ArrayList<>();
+ private ServerSocket serverSocket; // the server socket
+ private boolean started = false; // whether the server is started
+ Throwable error = null;
+
+ /**
+ * Creates a new abstract TCP server.
+ *
+ * @param linger the amount of time the server should wait before
+ * responding to requests.
+ */
+ protected AbstractTcpServer(long linger) {
+ this.linger = linger;
+ }
+
+ /**
+ * The local port to which the server is bound.
+ *
+ * @return The local port to which the server is bound.
+ * @exception IllegalStateException is thrown if the server is not
+ * started.
+ */
+ @Override
+ public final synchronized int getPort() {
+ if (!started) {
+ throw new IllegalStateException("Not started");
+ }
+ return serverSocket.getLocalPort();
+ }
+
+ /**
+ * The local address to which the server is bound.
+ *
+ * @return The local address to which the server is bound.
+ * @exception IllegalStateException is thrown if the server is not
+ * started.
+ */
+ @Override
+ public final synchronized InetAddress getAddress() {
+ if (!started) {
+ throw new IllegalStateException("Not started");
+ }
+ return serverSocket.getInetAddress();
+ }
+
+ /**
+ * Tells whether the server is started.
+ *
+ * @return true if the server is started.
+ */
+ public final synchronized boolean isStarted() {
+ return started;
+ }
+
+ /**
+ * Creates a new server socket.
+ *
+ * @param port local port to bind to.
+ * @param backlog requested maximum length of the queue of incoming
+ * connections.
+ * @param address local address to bind to.
+ * @return a new bound server socket ready to accept connections.
+ * @throws IOException if the socket cannot be created or bound.
+ */
+ protected ServerSocket newServerSocket(int port, int backlog,
+ InetAddress address)
+ throws IOException {
+ return new ServerSocket(port, backlog, address);
+ }
+
+ /**
+ * Starts listening for connections.
+ *
+ * @throws IOException if the server socket cannot be created or bound.
+ */
+ public final synchronized void start() throws IOException {
+ if (started) {
+ return;
+ }
+ final ServerSocket socket =
+ newServerSocket(0, 100, InetAddress.getLocalHost());
+ serverSocket = socket;
+ acceptThread = new Thread(this);
+ acceptThread.setDaemon(true);
+ acceptThread.start();
+ started = true;
+ }
+
+ /**
+ * Calls {@code Thread.sleep(linger);}
+ */
+ protected final void lingerIfRequired() {
+ if (linger > 0) {
+ try {
+ Thread.sleep(linger);
+ } catch (InterruptedException x) {
+ Thread.interrupted();
+ final ServerSocket socket = serverSocket();
+ if (socket != null && !socket.isClosed()) {
+ System.err.println("Thread interrupted...");
+ }
+ }
+ }
+ }
+
+ final synchronized ServerSocket serverSocket() {
+ return this.serverSocket;
+ }
+
+ /**
+ * The main accept loop.
+ */
+ @Override
+ public final void run() {
+ final ServerSocket sSocket = serverSocket();
+ try {
+ Socket s;
+ while (isStarted() && !Thread.interrupted()
+ && (s = sSocket.accept()) != null) {
+ lingerIfRequired();
+ listen(s);
+ }
+ } catch (Exception x) {
+ error = x;
+ } finally {
+ synchronized (this) {
+ if (!sSocket.isClosed()) {
+ try {
+ sSocket.close();
+ } catch (IOException x) {
+ System.err.println("Failed to close server socket");
+ }
+ }
+ if (started && this.serverSocket == sSocket) {
+ started = false;
+ this.serverSocket = null;
+ this.acceptThread = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Represents a connection accepted by the server.
+ */
+ protected abstract class TcpConnectionThread extends Thread {
+
+ protected final Socket socket;
+
+ protected TcpConnectionThread(Socket socket) {
+ this.socket = socket;
+ this.setDaemon(true);
+ }
+
+ public void close() throws IOException {
+ socket.close();
+ interrupt();
+ }
+ }
+
+ /**
+ * Creates a new TcpConnnectionThread to handle the connection through
+ * an accepted socket.
+ *
+ * @param s the socket returned by {@code serverSocket.accept()}.
+ * @return a new TcpConnnectionThread to handle the connection through
+ * an accepted socket.
+ */
+ protected abstract TcpConnectionThread createConnection(Socket s);
+
+ /**
+ * Creates and starts a new TcpConnectionThread to handle the accepted
+ * socket.
+ *
+ * @param s the socket returned by {@code serverSocket.accept()}.
+ */
+ private synchronized void listen(Socket s) {
+ TcpConnectionThread c = createConnection(s);
+ c.start();
+ addConnection(c);
+ }
+
+ /**
+ * Add the connection to the list of accepted connections.
+ *
+ * @param connection an accepted connection.
+ */
+ protected synchronized void addConnection(
+ TcpConnectionThread connection) {
+ connections.add(connection);
+ }
+
+ /**
+ * Remove the connection from the list of accepted connections.
+ *
+ * @param connection an accepted connection.
+ */
+ protected synchronized void removeConnection(
+ TcpConnectionThread connection) {
+ connections.remove(connection);
+ }
+
+ /**
+ * Close the server socket and all the connections present in the list
+ * of accepted connections.
+ *
+ * @throws IOException
+ */
+ @Override
+ public synchronized void close() throws IOException {
+ if (serverSocket != null && !serverSocket.isClosed()) {
+ serverSocket.close();
+ }
+ if (acceptThread != null) {
+ acceptThread.interrupt();
+ }
+ int failed = 0;
+ for (TcpConnectionThread c : connections) {
+ try {
+ c.close();
+ } catch (IOException x) {
+ // no matter - we're closing.
+ failed++;
+ }
+ }
+ connections.clear();
+ if (failed > 0) {
+ throw new IOException("Failed to close some connections");
+ }
+ }
+ }
+
+ /**
+ * A small TCP Server that emulates the echo service for tests purposes. See
+ * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
+ * port - NOT the standard port 7. We don't guarantee that its behavior
+ * exactly matches the RFC - the only purpose of this server is to have
+ * something that responds to nio tests...
+ */
+ static final class EchoServer extends AbstractTcpServer {
+
+ public EchoServer() {
+ this(0L);
+ }
+
+ public EchoServer(long linger) {
+ super(linger);
+ }
+
+ @Override
+ protected TcpConnectionThread createConnection(Socket s) {
+ return new EchoConnection(s);
+ }
+
+ private final class EchoConnection extends TcpConnectionThread {
+
+ public EchoConnection(Socket socket) {
+ super(socket);
+ }
+
+ @Override
+ public void run() {
+ try {
+ final InputStream is = socket.getInputStream();
+ final OutputStream out = socket.getOutputStream();
+ byte[] b = new byte[255];
+ int n;
+ while ((n = is.read(b)) > 0) {
+ lingerIfRequired();
+ out.write(b, 0, n);
+ }
+ } catch (IOException io) {
+ // fall through to finally
+ } finally {
+ if (!socket.isClosed()) {
+ try {
+ socket.close();
+ } catch (IOException x) {
+ System.err.println(
+ "Failed to close echo connection socket");
+ }
+ }
+ removeConnection(this);
+ }
+ }
+ }
+
+ public static EchoServer startNewServer() throws IOException {
+ return startNewServer(0);
+ }
+
+ public static EchoServer startNewServer(long linger) throws IOException {
+ final EchoServer echoServer = new EchoServer(linger);
+ echoServer.start();
+ return echoServer;
+ }
+ }
+
+ /**
+ * A small TCP server that emulates the Day & Time service for tests
+ * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
+ * uses an anonymous port - NOT the standard port 13. We don't guarantee
+ * that its behavior exactly matches the RFC - the only purpose of this
+ * server is to have something that responds to nio tests...
+ */
+ static final class DayTimeServer extends AbstractTcpServer {
+
+ public DayTimeServer() {
+ this(0L);
+ }
+
+ public DayTimeServer(long linger) {
+ super(linger);
+ }
+
+ @Override
+ protected TcpConnectionThread createConnection(Socket s) {
+ return new DayTimeServerConnection(s);
+ }
+
+ @Override
+ protected void addConnection(TcpConnectionThread connection) {
+ // do nothing - the connection just write the date and terminates.
+ }
+
+ @Override
+ protected void removeConnection(TcpConnectionThread connection) {
+ // do nothing - we're not adding connections to the list...
+ }
+
+ private final class DayTimeServerConnection extends TcpConnectionThread {
+
+ public DayTimeServerConnection(Socket socket) {
+ super(socket);
+ }
+
+ @Override
+ public void run() {
+ try {
+ final OutputStream out = socket.getOutputStream();
+ lingerIfRequired();
+ out.write(new Date(System.currentTimeMillis())
+ .toString().getBytes("US-ASCII"));
+ out.flush();
+ } catch (IOException io) {
+ // fall through to finally
+ } finally {
+ if (!socket.isClosed()) {
+ try {
+ socket.close();
+ } catch (IOException x) {
+ System.err.println(
+ "Failed to close echo connection socket");
+ }
+ }
+ }
+ }
+ }
+
+ public static DayTimeServer startNewServer()
+ throws IOException {
+ return startNewServer(0);
+ }
+
+ public static DayTimeServer startNewServer(long linger)
+ throws IOException {
+ final DayTimeServer daytimeServer = new DayTimeServer(linger);
+ daytimeServer.start();
+ return daytimeServer;
+ }
+ }
+
+ /**
+ * An abstract class for implementing small UDP Servers for the nio tests
+ * purposes. Disclaimer: This is a naive implementation that uses the old
+ * networking APIs (not those from {@code java.nio.*}) and shamelessly
+ * extends/creates Threads instead of using an executor service.
+ */
+ static abstract class AbstractUdpServer extends AbstractServer
+ implements Runnable, Closeable {
+
+ protected final long linger; // #of ms to wait before responding
+ private Thread acceptThread; // thread waiting for packets
+ private DatagramSocket serverSocket; // the server socket
+ private boolean started = false; // whether the server is started
+ Throwable error = null;
+
+ /**
+ * Creates a new abstract UDP server.
+ *
+ * @param linger the amount of time the server should wait before
+ * responding to requests.
+ */
+ protected AbstractUdpServer(long linger) {
+ this.linger = linger;
+ }
+
+ /**
+ * The local port to which the server is bound.
+ *
+ * @return The local port to which the server is bound.
+ * @exception IllegalStateException is thrown if the server is not
+ * started.
+ */
+ @Override
+ public final synchronized int getPort() {
+ if (!started) {
+ throw new IllegalStateException("Not started");
+ }
+ return serverSocket.getLocalPort();
+ }
+
+ /**
+ * The local address to which the server is bound.
+ *
+ * @return The local address to which the server is bound.
+ * @exception IllegalStateException is thrown if the server is not
+ * started.
+ */
+ @Override
+ public final synchronized InetAddress getAddress() {
+ if (!started) {
+ throw new IllegalStateException("Not started");
+ }
+ return serverSocket.getLocalAddress();
+ }
+
+ /**
+ * Tells whether the server is started.
+ *
+ * @return true if the server is started.
+ */
+ public final synchronized boolean isStarted() {
+ return started;
+ }
+
+ /**
+ * Creates a new datagram socket.
+ *
+ * @param port local port to bind to.
+ * @param address local address to bind to.
+ * @return a new bound server socket ready to listen for packets.
+ * @throws IOException if the socket cannot be created or bound.
+ */
+ protected DatagramSocket newDatagramSocket(int port,
+ InetAddress address)
+ throws IOException {
+ return new DatagramSocket(port, address);
+ }
+
+ /**
+ * Starts listening for connections.
+ *
+ * @throws IOException if the server socket cannot be created or bound.
+ */
+ public final synchronized void start() throws IOException {
+ if (started) {
+ return;
+ }
+ final DatagramSocket socket =
+ newDatagramSocket(0, InetAddress.getLocalHost());
+ serverSocket = socket;
+ acceptThread = new Thread(this);
+ acceptThread.setDaemon(true);
+ acceptThread.start();
+ started = true;
+ }
+
+ /**
+ * Calls {@code Thread.sleep(linger);}
+ */
+ protected final void lingerIfRequired() {
+ if (linger > 0) {
+ try {
+ Thread.sleep(linger);
+ } catch (InterruptedException x) {
+ Thread.interrupted();
+ final DatagramSocket socket = serverSocket();
+ if (socket != null && !socket.isClosed()) {
+ System.err.println("Thread interrupted...");
+ }
+ }
+ }
+ }
+
+ final synchronized DatagramSocket serverSocket() {
+ return this.serverSocket;
+ }
+
+ final synchronized boolean send(DatagramSocket socket,
+ DatagramPacket response) throws IOException {
+ if (!socket.isClosed()) {
+ socket.send(response);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * The main receive loop.
+ */
+ @Override
+ public final void run() {
+ final DatagramSocket sSocket = serverSocket();
+ try {
+ final int size = Math.max(1024, sSocket.getReceiveBufferSize());
+ if (size > sSocket.getReceiveBufferSize()) {
+ sSocket.setReceiveBufferSize(size);
+ }
+ while (isStarted() && !Thread.interrupted() && !sSocket.isClosed()) {
+ final byte[] buf = new byte[size];
+ final DatagramPacket packet =
+ new DatagramPacket(buf, buf.length);
+ lingerIfRequired();
+ sSocket.receive(packet);
+ //System.out.println("Received packet from: "
+ // + packet.getAddress()+":"+packet.getPort());
+ handle(sSocket, packet);
+ }
+ } catch (Exception x) {
+ error = x;
+ } finally {
+ synchronized (this) {
+ if (!sSocket.isClosed()) {
+ sSocket.close();
+ }
+ if (started && this.serverSocket == sSocket) {
+ started = false;
+ this.serverSocket = null;
+ this.acceptThread = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Represents an UDP request received by the server.
+ */
+ protected abstract class UdpRequestThread extends Thread {
+
+ protected final DatagramPacket request;
+ protected final DatagramSocket socket;
+
+ protected UdpRequestThread(DatagramSocket socket, DatagramPacket request) {
+ this.socket = socket;
+ this.request = request;
+ this.setDaemon(true);
+ }
+ }
+
+ /**
+ * Creates a new UdpRequestThread to handle a DatagramPacket received
+ * through a DatagramSocket.
+ *
+ * @param socket the socket through which the request was received.
+ * @param request the datagram packet received through the socket.
+ * @return a new UdpRequestThread to handle the request received through
+ * a DatagramSocket.
+ */
+ protected abstract UdpRequestThread createConnection(DatagramSocket socket,
+ DatagramPacket request);
+
+ /**
+ * Creates and starts a new UdpRequestThread to handle the received
+ * datagram packet.
+ *
+ * @param socket the socket through which the request was received.
+ * @param request the datagram packet received through the socket.
+ */
+ private synchronized void handle(DatagramSocket socket,
+ DatagramPacket request) {
+ UdpRequestThread c = createConnection(socket, request);
+ // c can be null if the request requires no response.
+ if (c != null) {
+ c.start();
+ }
+ }
+
+ /**
+ * Close the server socket.
+ *
+ * @throws IOException
+ */
+ @Override
+ public synchronized void close() throws IOException {
+ if (serverSocket != null && !serverSocket.isClosed()) {
+ serverSocket.close();
+ }
+ if (acceptThread != null) {
+ acceptThread.interrupt();
+ }
+ }
+ }
+
+ /**
+ * A small UDP Server that emulates the discard service for tests purposes.
+ * See http://en.wikipedia.org/wiki/Discard_Protocol This server uses an
+ * anonymous port - NOT the standard port 9. We don't guarantee that its
+ * behavior exactly matches the RFC - the only purpose of this server is to
+ * have something that responds to nio tests...
+ */
+ static final class UdpDiscardServer extends AbstractUdpServer {
+
+ public UdpDiscardServer() {
+ this(0L);
+ }
+
+ public UdpDiscardServer(long linger) {
+ super(linger);
+ }
+
+ @Override
+ protected UdpRequestThread createConnection(DatagramSocket socket,
+ DatagramPacket request) {
+ // no response required
+ return null;
+ }
+
+ public static UdpDiscardServer startNewServer() throws IOException {
+ return startNewServer(0);
+ }
+
+ public static UdpDiscardServer startNewServer(long linger) throws IOException {
+ final UdpDiscardServer discardServer = new UdpDiscardServer(linger);
+ discardServer.start();
+ return discardServer;
+ }
+ }
+
+ /**
+ * A small UDP Server that emulates the echo service for tests purposes. See
+ * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
+ * port - NOT the standard port 7. We don't guarantee that its behavior
+ * exactly matches the RFC - the only purpose of this server is to have
+ * something that responds to nio tests...
+ */
+ static final class UdpEchoServer extends AbstractUdpServer {
+
+ public UdpEchoServer() {
+ this(0L);
+ }
+
+ public UdpEchoServer(long linger) {
+ super(linger);
+ }
+
+ @Override
+ protected UdpEchoRequest createConnection(DatagramSocket socket,
+ DatagramPacket request) {
+ return new UdpEchoRequest(socket, request);
+ }
+
+ private final class UdpEchoRequest extends UdpRequestThread {
+
+ public UdpEchoRequest(DatagramSocket socket, DatagramPacket request) {
+ super(socket, request);
+ }
+
+ @Override
+ public void run() {
+ try {
+ lingerIfRequired();
+ final DatagramPacket response =
+ new DatagramPacket(request.getData(),
+ request.getOffset(), request.getLength(),
+ request.getAddress(), request.getPort());
+ send(socket, response);
+ } catch (IOException io) {
+ System.err.println("Failed to send response: " + io);
+ io.printStackTrace(System.err);
+ }
+ }
+ }
+
+ public static UdpEchoServer startNewServer() throws IOException {
+ return startNewServer(0);
+ }
+
+ public static UdpEchoServer startNewServer(long linger) throws IOException {
+ final UdpEchoServer echoServer = new UdpEchoServer(linger);
+ echoServer.start();
+ return echoServer;
+ }
+ }
+
+ /**
+ * A small UDP server that emulates the Day & Time service for tests
+ * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
+ * uses an anonymous port - NOT the standard port 13. We don't guarantee
+ * that its behavior exactly matches the RFC - the only purpose of this
+ * server is to have something that responds to nio tests...
+ */
+ static final class UdpDayTimeServer extends AbstractUdpServer {
+
+ public UdpDayTimeServer() {
+ this(0L);
+ }
+
+ public UdpDayTimeServer(long linger) {
+ super(linger);
+ }
+
+ @Override
+ protected UdpDayTimeRequestThread createConnection(DatagramSocket socket,
+ DatagramPacket request) {
+ return new UdpDayTimeRequestThread(socket, request);
+ }
+
+ private final class UdpDayTimeRequestThread extends UdpRequestThread {
+
+ public UdpDayTimeRequestThread(DatagramSocket socket,
+ DatagramPacket request) {
+ super(socket, request);
+ }
+
+ @Override
+ public void run() {
+ try {
+ lingerIfRequired();
+ final byte[] data = new Date(System.currentTimeMillis())
+ .toString().getBytes("US-ASCII");
+ final DatagramPacket response =
+ new DatagramPacket(data, 0, data.length,
+ request.getAddress(), request.getPort());
+ send(socket, response);
+ } catch (IOException io) {
+ System.err.println("Failed to send response: " + io);
+ io.printStackTrace(System.err);
+ }
+ }
+ }
+
+ public static UdpDayTimeServer startNewServer() throws IOException {
+ return startNewServer(0);
+ }
+
+ public static UdpDayTimeServer startNewServer(long linger)
+ throws IOException {
+ final UdpDayTimeServer echoServer = new UdpDayTimeServer(linger);
+ echoServer.start();
+ return echoServer;
+ }
+ }
+}
--- a/jdk/test/java/nio/channels/TestUtil.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/nio/channels/TestUtil.java Thu Nov 15 00:54:54 2012 +0000
@@ -27,7 +27,6 @@
import java.io.*;
import java.net.*;
-import java.nio.*;
import java.nio.channels.*;
import java.util.Random;
@@ -36,9 +35,6 @@
// Test hosts used by the channels tests - change these when
// executing in a different network.
- public static final String HOST = "javaweb.sfbay.sun.com";
- public static final String REFUSING_HOST = "jano1.sfbay.sun.com";
- public static final String FAR_HOST = "irejano.ireland.sun.com";
public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah";
private TestUtil() { }
--- a/jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6854712
+ * @bug 6854712 7171570
* @summary Basic unit test for PKIXRevocationChecker
*/
@@ -33,6 +33,7 @@
import java.io.OutputStream;
import java.net.URI;
import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathChecker;
import java.security.cert.CertPathValidator;
import java.security.cert.Extension;
@@ -58,8 +59,7 @@
requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
- requireEmpty(prc.getOCSPStapledResponses(),
- "getOCSPStapledResponses()");
+ requireEmpty(prc.getOCSPResponses(), "getOCSPResponses()");
requireEmpty(prc.getOptions(), "getOptions()");
System.out.println("Testing that get methods return same parameters " +
@@ -94,11 +94,24 @@
requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
prc.setOCSPExtensions(null);
requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
- prc.setOCSPStapledResponses(null);
- requireEmpty(prc.getOCSPStapledResponses(),
- "getOCSPStapledResponses()");
+ prc.setOCSPResponses(null);
+ requireEmpty(prc.getOCSPResponses(), "getOCSPResponses()");
prc.setOptions(null);
requireEmpty(prc.getOptions(), "getOptions()");
+
+ System.out.println("Testing that getRevocationChecker returns new " +
+ "instance each time");
+ CertPathChecker first = cpv.getRevocationChecker();
+ CertPathChecker second = cpv.getRevocationChecker();
+ if (first == second) {
+ throw new Exception("FAILED: CertPathCheckers not new instances");
+ }
+ CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+ first = cpb.getRevocationChecker();
+ second = cpb.getRevocationChecker();
+ if (first == second) {
+ throw new Exception("FAILED: CertPathCheckers not new instances");
+ }
}
static void requireNull(Object o, String msg) throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Locale/Bug8001562.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8001562
+ * @summary Verify that getAvailableLocales() in locale sensitive services
+ * classes return compatible set of locales as in JDK7.
+ * @run main Bug8001562
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug8001562 {
+
+ static final String[] jdk7availTags = {
+ "ar", "ar-AE", "ar-BH", "ar-DZ", "ar-EG", "ar-IQ", "ar-JO", "ar-KW",
+ "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", "ar-SD", "ar-SY",
+ "ar-TN", "ar-YE", "be", "be-BY", "bg", "bg-BG", "ca", "ca-ES", "cs",
+ "cs-CZ", "da", "da-DK", "de", "de-AT", "de-CH", "de-DE", "de-LU", "el",
+ "el-CY", "el-GR", "en", "en-AU", "en-CA", "en-GB", "en-IE", "en-IN",
+ "en-MT", "en-NZ", "en-PH", "en-SG", "en-US", "en-ZA", "es", "es-AR",
+ "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-GT",
+ "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV",
+ "es-US", "es-UY", "es-VE", "et", "et-EE", "fi", "fi-FI", "fr", "fr-BE",
+ "fr-CA", "fr-CH", "fr-FR", "fr-LU", "ga", "ga-IE", "he", "he-IL",
+ "hi-IN", "hr", "hr-HR", "hu", "hu-HU", "id", "id-ID", "is", "is-IS",
+ "it", "it-CH", "it-IT", "ja", "ja-JP",
+ "ja-JP-u-ca-japanese-x-lvariant-JP", "ko", "ko-KR", "lt", "lt-LT", "lv",
+ "lv-LV", "mk", "mk-MK", "ms", "ms-MY", "mt", "mt-MT", "nl", "nl-BE",
+ "nl-NL", "no", "no-NO", "no-NO-x-lvariant-NY", "pl", "pl-PL", "pt",
+ "pt-BR", "pt-PT", "ro", "ro-RO", "ru", "ru-RU", "sk", "sk-SK", "sl",
+ "sl-SI", "sq", "sq-AL", "sr", "sr-BA", "sr-CS", "sr-Latn", "sr-Latn-BA",
+ "sr-Latn-ME", "sr-Latn-RS", "sr-ME", "sr-RS", "sv", "sv-SE", "th",
+ "th-TH", "th-TH-u-nu-thai-x-lvariant-TH", "tr", "tr-TR", "uk", "uk-UA",
+ "vi", "vi-VN", "zh", "zh-CN", "zh-HK", "zh-SG", "zh-TW", };
+ static List<Locale> jdk7availLocs = new ArrayList<>();
+ static {
+ for (String locStr : jdk7availTags) {
+ jdk7availLocs.add(Locale.forLanguageTag(locStr));
+ }
+ }
+
+ public static void main(String[] args) {
+ List<Locale> avail = Arrays.asList(BreakIterator.getAvailableLocales());
+ diffLocale(BreakIterator.class, avail);
+
+ avail = Arrays.asList(Collator.getAvailableLocales());
+ diffLocale(Collator.class, avail);
+
+ avail = Arrays.asList(DateFormat.getAvailableLocales());
+ diffLocale(DateFormat.class, avail);
+
+ avail = Arrays.asList(DateFormatSymbols.getAvailableLocales());
+ diffLocale(DateFormatSymbols.class, avail);
+
+ avail = Arrays.asList(DecimalFormatSymbols.getAvailableLocales());
+ diffLocale(DecimalFormatSymbols.class, avail);
+
+ avail = Arrays.asList(NumberFormat.getAvailableLocales());
+ diffLocale(NumberFormat.class, avail);
+
+ avail = Arrays.asList(Locale.getAvailableLocales());
+ diffLocale(Locale.class, avail);
+ }
+
+ static void diffLocale(Class c, List<Locale> locs) {
+ String diff = "";
+
+ System.out.printf("Only in target locales (%s.getAvailableLocales()): ", c.getSimpleName());
+ for (Locale l : locs) {
+ if (!jdk7availLocs.contains(l)) {
+ diff += "\""+l.toLanguageTag()+"\", ";
+ }
+ }
+ System.out.println(diff);
+ diff = "";
+
+ System.out.printf("Only in JDK7 (%s.getAvailableLocales()): ", c.getSimpleName());
+ for (Locale l : jdk7availLocs) {
+ if (!locs.contains(l)) {
+ diff += "\""+l.toLanguageTag()+"\", ";
+ }
+ }
+ System.out.println(diff);
+
+ if (diff.length() > 0) {
+ throw new RuntimeException("Above locale(s) were not included in the target available locales");
+ }
+ }
+}
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -53,9 +53,8 @@
}
void availableLocalesTest() {
- Set<Locale> localesFromAPI = new HashSet<Locale>(availloc);
- Set<Locale> localesExpected = new HashSet<Locale>(jreimplloc);
- localesExpected.remove(Locale.ROOT);
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
localesExpected.addAll(providerloc);
if (localesFromAPI.equals(localesExpected)) {
System.out.println("availableLocalesTest passed.");
--- a/jdk/test/java/util/PluggableLocale/CollatorProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/CollatorProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -47,9 +47,8 @@
}
void availableLocalesTest() {
- Set<Locale> localesFromAPI = new HashSet<Locale>(availloc);
- Set<Locale> localesExpected = new HashSet<Locale>(jreimplloc);
- localesExpected.remove(Locale.ROOT);
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
localesExpected.addAll(providerloc);
if (localesFromAPI.equals(localesExpected)) {
System.out.println("availableLocalesTest passed.");
--- a/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -34,6 +34,7 @@
com.foo.DateFormatProviderImpl dfp = new com.foo.DateFormatProviderImpl();
List<Locale> availloc = Arrays.asList(DateFormat.getAvailableLocales());
List<Locale> providerloc = Arrays.asList(dfp.getAvailableLocales());
+ List<Locale> jreloc = Arrays.asList(LocaleProviderAdapter.forJRE().getAvailableLocales());
List<Locale> jreimplloc = Arrays.asList(LocaleProviderAdapter.forJRE().getDateFormatProvider().getAvailableLocales());
public static void main(String[] s) {
@@ -41,11 +42,23 @@
}
DateFormatProviderTest() {
+ availableLocalesTest();
objectValidityTest();
extendedVariantTest();
messageFormatTest();
}
+ void availableLocalesTest() {
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
+ localesExpected.addAll(providerloc);
+ if (localesFromAPI.equals(localesExpected)) {
+ System.out.println("availableLocalesTest passed.");
+ } else {
+ throw new RuntimeException("availableLocalesTest failed");
+ }
+ }
+
void objectValidityTest() {
for (Locale target: availloc) {
--- a/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -48,9 +48,8 @@
}
void availableLocalesTest() {
- Set<Locale> localesFromAPI = new HashSet<Locale>(availloc);
- Set<Locale> localesExpected = new HashSet<Locale>(jreimplloc);
- localesExpected.remove(Locale.ROOT);
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
localesExpected.addAll(providerloc);
if (localesFromAPI.equals(localesExpected)) {
System.out.println("availableLocalesTest passed.");
--- a/jdk/test/java/util/PluggableLocale/DecimalFormatSymbolsProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/DecimalFormatSymbolsProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -47,9 +47,8 @@
}
void availableLocalesTest() {
- Set<Locale> localesFromAPI = new HashSet<Locale>(availloc);
- Set<Locale> localesExpected = new HashSet<Locale>(jreimplloc);
- localesExpected.remove(Locale.ROOT);
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
localesExpected.addAll(providerloc);
if (localesFromAPI.equals(localesExpected)) {
System.out.println("availableLocalesTest passed.");
--- a/jdk/test/java/util/PluggableLocale/GenericTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/GenericTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -73,7 +73,6 @@
expected.addAll(Arrays.asList(localeNP.getAvailableLocales()));
expected.addAll(Arrays.asList(tzNP.getAvailableLocales()));
expected.addAll(Arrays.asList(calDataP.getAvailableLocales()));
- expected.remove(Locale.ROOT);
if (!result.equals(expected)) {
throw new RuntimeException("Locale.getAvailableLocales() does not return the union of locales: diff="
+ getDiff(result, expected));
--- a/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -50,9 +50,8 @@
}
void availableLocalesTest() {
- Set<Locale> localesFromAPI = new HashSet<Locale>(availloc);
- Set<Locale> localesExpected = new HashSet<Locale>(jreimplloc);
- localesExpected.remove(Locale.ROOT);
+ Set<Locale> localesFromAPI = new HashSet<>(availloc);
+ Set<Locale> localesExpected = new HashSet<>(jreloc);
localesExpected.addAll(providerloc);
if (localesFromAPI.equals(localesExpected)) {
System.out.println("availableLocalesTest passed.");
--- a/jdk/test/sun/net/www/protocol/http/StackTraceTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/net/www/protocol/http/StackTraceTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -32,26 +32,28 @@
import java.io.IOException;
public class StackTraceTest {
- public static void main(String[] args) {
- try {
- URL url = new URL("http://localhost:8080/");
- URLConnection uc = url.openConnection();
- System.out.println("key = "+uc.getHeaderFieldKey(20));
- uc.getInputStream();
- } catch (IOException ioe) {
- ioe.printStackTrace();
+ public static void main(String[] args) throws Exception {
+ URL url;
+ try (ServerSocket ss = new ServerSocket(0)) { // refusing socket
+ url = new URL("http://localhost:" + ss.getLocalPort() + "/");
+ }
+ URLConnection uc = url.openConnection();
+
+ // Trigger implicit connection by trying to retrieve bogus
+ // response header, and force remembered exception
+ uc.getHeaderFieldKey(20);
- if (!(ioe instanceof ConnectException)) {
- throw new RuntimeException("Expect ConnectException, got "+ioe);
- }
- if (ioe.getMessage() == null) {
+ try {
+ uc.getInputStream(); // expect to throw
+ throw new RuntimeException("Expected getInputStream to throw");
+ } catch (IOException ioe) {
+ if (!(ioe instanceof ConnectException))
+ throw new RuntimeException("Expect ConnectException, got " + ioe);
+ if (ioe.getMessage() == null)
throw new RuntimeException("Exception message is null");
- }
-
- // this exception should be a chained exception
- if (ioe.getCause() == null) {
- throw new RuntimeException("Excepting a chained exception, but got: ", ioe);
- }
+ if (ioe.getCause() == null)
+ throw new RuntimeException("Excepting a chained exception, but got: ",
+ ioe);
}
}
}
--- a/jdk/test/sun/security/krb5/auto/Basic.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/krb5/auto/Basic.java Thu Nov 15 00:54:54 2012 +0000
@@ -38,11 +38,13 @@
new OneKDC(null).writeJAASConf();
- Context c, s;
+ Context c, s, s2, b;
c = Context.fromJAAS("client");
s = Context.fromJAAS("server");
+ b = Context.fromJAAS("backend");
c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ c.x().requestCredDeleg(true);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
Context.handshake(c, s);
@@ -50,7 +52,13 @@
Context.transmit("i say high --", c, s);
Context.transmit(" you say low", s, c);
+ s2 = s.delegated();
s.dispose();
c.dispose();
+
+ s2.startAsClient(OneKDC.BACKEND, GSSUtil.GSS_KRB5_MECH_OID);
+ b.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(s2, b);
}
}
--- a/jdk/test/sun/security/krb5/auto/Context.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/krb5/auto/Context.java Thu Nov 15 00:54:54 2012 +0000
@@ -42,9 +42,10 @@
import com.sun.security.jgss.ExtendedGSSContext;
import com.sun.security.jgss.InquireType;
import com.sun.security.jgss.AuthorizationDataEntry;
+import com.sun.security.jgss.ExtendedGSSCredential;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import javax.security.auth.kerberos.KeyTab;
+import java.security.Principal;
/**
* Context of a JGSS subject, encapsulating Subject and GSSContext.
@@ -90,7 +91,21 @@
public Context delegated() throws Exception {
Context out = new Context();
out.s = s;
- out.cred = x.getDelegCred();
+ try {
+ out.cred = Subject.doAs(s, new PrivilegedExceptionAction<GSSCredential>() {
+ @Override
+ public GSSCredential run() throws Exception {
+ GSSCredential cred = x.getDelegCred();
+ if (cred == null && x.getCredDelegState() ||
+ cred != null && !x.getCredDelegState()) {
+ throw new Exception("getCredDelegState not match");
+ }
+ return cred;
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ throw pae.getException();
+ }
out.name = name + " as " + out.cred.getName().toString();
return out;
}
@@ -212,28 +227,34 @@
* @throws java.lang.Exception
*/
public void startAsServer(final Oid mech) throws Exception {
- startAsServer(null, mech);
+ startAsServer(null, mech, false);
}
+ public void startAsServer(final String name, final Oid mech) throws Exception {
+ startAsServer(name, mech, false);
+ }
/**
* Starts as a server with the specified service name
* @param name the service name
* @param mech GSS mech
* @throws java.lang.Exception
*/
- public void startAsServer(final String name, final Oid mech) throws Exception {
+ public void startAsServer(final String name, final Oid mech, final boolean asInitiator) throws Exception {
doAs(new Action() {
@Override
public byte[] run(Context me, byte[] dummy) throws Exception {
GSSManager m = GSSManager.getInstance();
- me.x = (ExtendedGSSContext)m.createContext(m.createCredential(
+ me.cred = m.createCredential(
name == null ? null :
(name.indexOf('@') < 0 ?
m.createName(name, null) :
m.createName(name, GSSName.NT_HOSTBASED_SERVICE)),
GSSCredential.INDEFINITE_LIFETIME,
mech,
- GSSCredential.ACCEPT_ONLY));
+ asInitiator?
+ GSSCredential.INITIATE_AND_ACCEPT:
+ GSSCredential.ACCEPT_ONLY);
+ me.x = (ExtendedGSSContext)m.createContext(me.cred);
return null;
}
}, null);
@@ -331,27 +352,38 @@
} catch (Exception e) {
;// Don't care
}
- System.out.println("====== Private Credentials Set ======");
- for (Object o : s.getPrivateCredentials()) {
- System.out.println(" " + o.getClass());
- if (o instanceof KerberosTicket) {
- KerberosTicket kt = (KerberosTicket) o;
- System.out.println(" " + kt.getServer() + " for " + kt.getClient());
- } else if (o instanceof KerberosKey) {
- KerberosKey kk = (KerberosKey) o;
- System.out.print(" " + kk.getKeyType() + " " + kk.getVersionNumber() + " " + kk.getAlgorithm() + " ");
- for (byte b : kk.getEncoded()) {
- System.out.printf("%02X", b & 0xff);
- }
- System.out.println();
- } else if (o instanceof Map) {
- Map map = (Map) o;
- for (Object k : map.keySet()) {
- System.out.println(" " + k + ": " + map.get(k));
- }
- } else {
+ if (s != null) {
+ System.out.println("====== START SUBJECT CONTENT =====");
+ for (Principal p: s.getPrincipals()) {
+ System.out.println(" Principal: " + p);
+ }
+ for (Object o : s.getPublicCredentials()) {
+ System.out.println(" " + o.getClass());
System.out.println(" " + o);
}
+ System.out.println("====== Private Credentials Set ======");
+ for (Object o : s.getPrivateCredentials()) {
+ System.out.println(" " + o.getClass());
+ if (o instanceof KerberosTicket) {
+ KerberosTicket kt = (KerberosTicket) o;
+ System.out.println(" " + kt.getServer() + " for " + kt.getClient());
+ } else if (o instanceof KerberosKey) {
+ KerberosKey kk = (KerberosKey) o;
+ System.out.print(" " + kk.getKeyType() + " " + kk.getVersionNumber() + " " + kk.getAlgorithm() + " ");
+ for (byte b : kk.getEncoded()) {
+ System.out.printf("%02X", b & 0xff);
+ }
+ System.out.println();
+ } else if (o instanceof Map) {
+ Map map = (Map) o;
+ for (Object k : map.keySet()) {
+ System.out.println(" " + k + ": " + map.get(k));
+ }
+ } else {
+ System.out.println(" " + o);
+ }
+ }
+ System.out.println("====== END SUBJECT CONTENT =====");
}
if (x != null && x instanceof ExtendedGSSContext) {
if (x.isEstablished()) {
@@ -510,6 +542,29 @@
return sb.toString();
}
+ public Context impersonate(final String someone) throws Exception {
+ try {
+ GSSCredential creds = Subject.doAs(s, new PrivilegedExceptionAction<GSSCredential>() {
+ @Override
+ public GSSCredential run() throws Exception {
+ GSSManager m = GSSManager.getInstance();
+ GSSName other = m.createName(someone, GSSName.NT_USER_NAME);
+ if (Context.this.cred == null) {
+ Context.this.cred = m.createCredential(GSSCredential.INITIATE_ONLY);
+ }
+ return ((ExtendedGSSCredential)Context.this.cred).impersonate(other);
+ }
+ });
+ Context out = new Context();
+ out.s = s;
+ out.cred = creds;
+ out.name = name + " as " + out.cred.getName().toString();
+ return out;
+ } catch (PrivilegedActionException pae) {
+ throw pae.getException();
+ }
+ }
+
public byte[] take(final byte[] in) throws Exception {
return doAs(new Action() {
@Override
@@ -522,10 +577,11 @@
}
return null;
} else {
- System.out.println(name + " call initSecContext");
if (me.x.isInitiator()) {
+ System.out.println(name + " call initSecContext");
return me.x.initSecContext(input, 0, input.length);
} else {
+ System.out.println(name + " call acceptSecContext");
return me.x.acceptSecContext(input, 0, input.length);
}
}
--- a/jdk/test/sun/security/krb5/auto/CrossRealm.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/krb5/auto/CrossRealm.java Thu Nov 15 00:54:54 2012 +0000
@@ -24,6 +24,7 @@
/*
* @test
* @bug 6706974
+ * @compile -XDignore.symbol.file CrossRealm.java
* @run main/othervm CrossRealm
* @summary Add krb5 test infrastructure
*/
--- a/jdk/test/sun/security/krb5/auto/KDC.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java Thu Nov 15 00:54:54 2012 +0000
@@ -178,6 +178,20 @@
* What backend server can be delegated to
*/
OK_AS_DELEGATE,
+ /**
+ * Allow S4U2self, List<String> of middle servers.
+ * If not set, means KDC does not understand S4U2self at all, therefore
+ * would ignore any PA-FOR-USER request and send a ticket using the
+ * cname of teh requestor. If set, it returns FORWARDABLE tickets to
+ * a server with its name in the list
+ */
+ ALLOW_S4U2SELF,
+ /**
+ * Allow S4U2proxy, Map<String,List<String>> of middle servers to
+ * backends. If not set or a backend not in a server's list,
+ * Krb5.KDC_ERR_POLICY will be send for S4U2proxy request.
+ */
+ ALLOW_S4U2PROXY,
};
static {
@@ -618,13 +632,18 @@
int e2 = eTypes[0]; // etype for outgoing session key
int e3 = eTypes[0]; // etype for outgoing ticket
- PAData[] pas = kDCReqDotPAData(tgsReq);
+ PAData[] pas = KDCReqDotPAData(tgsReq);
Ticket tkt = null;
EncTicketPart etp = null;
+
+ PrincipalName cname = null;
+ boolean allowForwardable = true;
+
if (pas == null || pas.length == 0) {
throw new KrbException(Krb5.KDC_ERR_PADATA_TYPE_NOSUPP);
} else {
+ PrincipalName forUserCName = null;
for (PAData pa: pas) {
if (pa.getType() == Krb5.PA_TGS_REQ) {
APReq apReq = new APReq(pa.getValue());
@@ -636,8 +655,31 @@
DerInputStream derIn = new DerInputStream(bb);
DerValue der = derIn.getDerValue();
etp = new EncTicketPart(der.toByteArray());
+ // Finally, cname will be overwritten by PA-FOR-USER
+ // if it exists.
+ cname = etp.cname;
+ System.out.println(realm + "> presenting a ticket of "
+ + etp.cname + " to " + tkt.sname);
+ } else if (pa.getType() == Krb5.PA_FOR_USER) {
+ if (options.containsKey(Option.ALLOW_S4U2SELF)) {
+ PAForUserEnc p4u = new PAForUserEnc(
+ new DerValue(pa.getValue()), null);
+ forUserCName = p4u.name;
+ System.out.println(realm + "> presenting a PA_FOR_USER "
+ + " in the name of " + p4u.name);
+ }
}
}
+ if (forUserCName != null) {
+ List<String> names = (List<String>)options.get(Option.ALLOW_S4U2SELF);
+ if (!names.contains(cname.toString())) {
+ // Mimic the normal KDC behavior. When a server is not
+ // allowed to send S4U2self, do not send an error.
+ // Instead, send a ticket which is useless later.
+ allowForwardable = false;
+ }
+ cname = forUserCName;
+ }
if (tkt == null) {
throw new KrbException(Krb5.KDC_ERR_PADATA_TYPE_NOSUPP);
}
@@ -658,7 +700,8 @@
}
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
- if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
+ if (body.kdcOptions.get(KDCOptions.FORWARDABLE)
+ && allowForwardable) {
bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
}
if (body.kdcOptions.get(KDCOptions.FORWARDED) ||
@@ -678,6 +721,37 @@
if (body.kdcOptions.get(KDCOptions.ALLOW_POSTDATE)) {
bFlags[Krb5.TKT_OPTS_MAY_POSTDATE] = true;
}
+ if (body.kdcOptions.get(KDCOptions.CNAME_IN_ADDL_TKT)) {
+ if (!options.containsKey(Option.ALLOW_S4U2PROXY)) {
+ // Don't understand CNAME_IN_ADDL_TKT
+ throw new KrbException(Krb5.KDC_ERR_BADOPTION);
+ } else {
+ Map<String,List<String>> map = (Map<String,List<String>>)
+ options.get(Option.ALLOW_S4U2PROXY);
+ Ticket second = KDCReqBodyDotFirstAdditionalTicket(body);
+ EncryptionKey key2 = keyForUser(second.sname, second.encPart.getEType(), true);
+ byte[] bb = second.encPart.decrypt(key2, KeyUsage.KU_TICKET);
+ DerInputStream derIn = new DerInputStream(bb);
+ DerValue der = derIn.getDerValue();
+ EncTicketPart tktEncPart = new EncTicketPart(der.toByteArray());
+ if (!tktEncPart.flags.get(Krb5.TKT_OPTS_FORWARDABLE)) {
+ //throw new KrbException(Krb5.KDC_ERR_BADOPTION);
+ }
+ PrincipalName client = tktEncPart.cname;
+ System.out.println(realm + "> and an additional ticket of "
+ + client + " to " + second.sname);
+ if (map.containsKey(cname.toString())) {
+ if (map.get(cname.toString()).contains(service.toString())) {
+ System.out.println(realm + "> S4U2proxy OK");
+ } else {
+ throw new KrbException(Krb5.KDC_ERR_BADOPTION);
+ }
+ } else {
+ throw new KrbException(Krb5.KDC_ERR_BADOPTION);
+ }
+ cname = client;
+ }
+ }
String okAsDelegate = (String)options.get(Option.OK_AS_DELEGATE);
if (okAsDelegate != null && (
@@ -691,7 +765,7 @@
EncTicketPart enc = new EncTicketPart(
tFlags,
key,
- etp.cname,
+ cname,
new TransitedEncoding(1, new byte[0]), // TODO
new KerberosTime(new Date()),
body.from,
@@ -729,7 +803,7 @@
);
EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
TGSRep tgsRep = new TGSRep(null,
- etp.cname,
+ cname,
t,
edata);
System.out.println(" Return " + tgsRep.cname
@@ -942,7 +1016,7 @@
outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
}
- PAData[] inPAs = kDCReqDotPAData(asReq);
+ PAData[] inPAs = KDCReqDotPAData(asReq);
if (inPAs == null || inPAs.length == 0) {
Object preauth = options.get(Option.PREAUTH_REQUIRED);
if (preauth == null || preauth.equals(Boolean.TRUE)) {
@@ -1252,6 +1326,7 @@
private static final Field getEType;
private static final Constructor<EncryptedData> ctorEncryptedData;
private static final Method stringToKey;
+ private static final Field getAddlTkt;
static {
try {
@@ -1265,6 +1340,8 @@
"stringToKey",
char[].class, String.class, byte[].class, Integer.TYPE);
stringToKey.setAccessible(true);
+ getAddlTkt = KDCReqBody.class.getDeclaredField("additionalTickets");
+ getAddlTkt.setAccessible(true);
} catch (NoSuchFieldException nsfe) {
throw new AssertionError(nsfe);
} catch (NoSuchMethodException nsme) {
@@ -1278,7 +1355,7 @@
throw new AssertionError(e);
}
}
- private static PAData[] kDCReqDotPAData(KDCReq req) {
+ private static PAData[] KDCReqDotPAData(KDCReq req) {
try {
return (PAData[])getPADataField.get(req);
} catch (Exception e) {
@@ -1303,4 +1380,11 @@
throw new AssertionError(e);
}
}
+ private static Ticket KDCReqBodyDotFirstAdditionalTicket(KDCReqBody body) {
+ try {
+ return ((Ticket[])getAddlTkt.get(body))[0];
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
}
--- a/jdk/test/sun/security/krb5/auto/OkAsDelegate.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/krb5/auto/OkAsDelegate.java Thu Nov 15 00:54:54 2012 +0000
@@ -91,7 +91,7 @@
Context c, s;
c = Context.fromJAAS("client");
- s = Context.fromJAAS("server");
+ s = Context.fromJAAS("com.sun.security.jgss.krb5.accept");
Oid mech = GSSUtil.GSS_KRB5_MECH_OID;
if (System.getProperty("test.spnego") != null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2proxy.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2proxy.java
+ * @run main/othervm S4U2proxy krb5
+ * @run main/othervm S4U2proxy spnego
+ */
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2proxy {
+
+ public static void main(String[] args) throws Exception {
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+ kdc.setOption(KDC.Option.PREAUTH_REQUIRED, false);
+ Map<String,List<String>> map = new HashMap<>();
+ map.put(OneKDC.SERVER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.BACKEND + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+
+ Context c, s, b;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+ b = Context.fromJAAS("backend");
+
+ c.startAsClient(OneKDC.SERVER, mech);
+ s.startAsServer(null, mech, false);
+
+ Context.handshake(c, s);
+ Context p = s.delegated();
+
+ p.startAsClient(OneKDC.BACKEND, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+
+ p.startAsClient(OneKDC.BACKEND, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2proxyGSS.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2proxyGSS.java
+ * @run main/othervm -Djavax.security.auth.useSubjectCredsOnly=false S4U2proxyGSS krb5
+ * @run main/othervm -Djavax.security.auth.useSubjectCredsOnly=false S4U2proxyGSS spnego
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2proxyGSS {
+
+ public static void main(String[] args) throws Exception {
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+ kdc.setOption(KDC.Option.PREAUTH_REQUIRED, false);
+ Map<String,List<String>> map = new HashMap<>();
+ map.put(OneKDC.SERVER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+
+ Context c, s, b;
+ System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+ System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+ File f = new File(OneKDC.JAAS_CONF);
+ FileOutputStream fos = new FileOutputStream(f);
+ fos.write((
+ "com.sun.security.jgss.krb5.initiate {\n" +
+ " com.sun.security.auth.module.Krb5LoginModule required;\n};\n" +
+ "com.sun.security.jgss.krb5.accept {\n" +
+ " com.sun.security.auth.module.Krb5LoginModule required\n" +
+ " principal=\"" + OneKDC.SERVER + "\"\n" +
+ " useKeyTab=true\n" +
+ " storeKey=true;\n};\n"
+ ).getBytes());
+ fos.close();
+ Security.setProperty("auth.login.defaultCallbackHandler", "OneKDC$CallbackForClient");
+ c = Context.fromThinAir();
+ s = Context.fromThinAir();
+ b = Context.fromThinAir();
+ c.startAsClient(OneKDC.SERVER, mech);
+ c.x().requestCredDeleg(false);
+ s.startAsServer(mech);
+
+ Context.handshake(c, s);
+ Context p = s.delegated();
+ p.startAsClient(OneKDC.SERVER, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+
+ String n1 = p.x().getSrcName().toString().split("@")[0];
+ String n2 = b.x().getSrcName().toString().split("@")[0];
+ if (!n1.equals(OneKDC.USER) || !n2.equals(OneKDC.USER)) {
+ throw new Exception("Delegation failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2self.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2self.java
+ * @run main/othervm -Dsun.security.krb5.debug=false S4U2self krb5 0
+ * @run main/othervm/fail -Dsun.security.krb5.debug=false S4U2self krb5 1
+ * @run main/othervm/fail -Dsun.security.krb5.debug=false S4U2self krb5 2
+ * @run main/othervm/fail -Dsun.security.krb5.debug=false S4U2self krb5 3
+ * @run main/othervm/fail -Dsun.security.krb5.debug=false S4U2self krb5 4
+ * @run main/othervm/fail -Dsun.security.krb5.debug=false S4U2self krb5 5
+ * @run main/othervm -Dsun.security.krb5.debug=false S4U2self spnego
+ */
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2self {
+
+ public static void main(String[] args) throws Exception {
+ // Test case, different policy settings in KDC:
+ // | ALLOW_S4U2SELF on
+ // | USER USER2 none
+ // ALLOW_S4U2PORXY |-------------------------
+ // USER to BACKEND | 0 1 2
+ // USER2 to BACKEND | 3
+ // USER to SERVER | 4
+ // none | 5
+ //
+ // 0 should succeed, all other fail
+ int test = 0;
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ test = Integer.parseInt(args[1]);
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+
+ switch (test) {
+ case 1:
+ kdc.setOption(KDC.Option.ALLOW_S4U2SELF, Arrays.asList(
+ new String[]{OneKDC.USER2 + "@" + OneKDC.REALM}));
+ break;
+ case 2:
+ // No S4U2self
+ break;
+ default:
+ kdc.setOption(KDC.Option.ALLOW_S4U2SELF, Arrays.asList(
+ new String[]{OneKDC.USER + "@" + OneKDC.REALM}));
+ break;
+ }
+
+ Map<String,List<String>> map = new HashMap<>();
+ switch (test) {
+ case 3:
+ map.put(OneKDC.USER2 + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.BACKEND + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+ break;
+ case 4:
+ map.put(OneKDC.USER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+ break;
+ case 5:
+ // No S4U2proxy set
+ break;
+ default:
+ map.put(OneKDC.USER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.BACKEND + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+ break;
+ }
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+
+ c = c.impersonate(OneKDC.USER2);
+ c.status();
+
+ c.startAsClient(OneKDC.BACKEND, mech);
+
+ s = Context.fromJAAS("backend");
+ s.startAsServer(mech);
+
+ Context.handshake(c, s);
+
+ Context.transmit("i say high --", c, s);
+ Context.transmit(" you say low", s, c);
+
+ c.status();
+ s.status();
+
+ String n1 = c.x().getSrcName().toString().split("@")[0];
+ String n2 = s.x().getSrcName().toString().split("@")[0];
+ if (!n1.equals(OneKDC.USER2) || !n2.equals(OneKDC.USER2)) {
+ throw new Exception("Impersonate failed");
+ }
+
+ s.dispose();
+ c.dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2selfAsServer.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2selfAsServer.java
+ * @run main/othervm S4U2selfAsServer krb5
+ * @run main/othervm S4U2selfAsServer spnego
+ */
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2selfAsServer {
+
+ public static void main(String[] args) throws Exception {
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+ kdc.setOption(KDC.Option.PREAUTH_REQUIRED, false);
+ Map<String,List<String>> map = new HashMap<>();
+ map.put(OneKDC.SERVER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.BACKEND + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+ kdc.setOption(KDC.Option.ALLOW_S4U2SELF, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+
+ Context s, b;
+ s = Context.fromJAAS("server");
+ b = Context.fromJAAS("backend");
+
+ s.startAsServer(null, mech, false);
+
+ Context p = s.impersonate(OneKDC.USER);
+
+ p.startAsClient(OneKDC.BACKEND, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+
+ p.startAsClient(OneKDC.BACKEND, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2selfAsServerGSS.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2selfAsServerGSS.java
+ * @run main/othervm -Djavax.security.auth.useSubjectCredsOnly=false S4U2selfAsServerGSS krb5
+ * @run main/othervm -Djavax.security.auth.useSubjectCredsOnly=false S4U2selfAsServerGSS spnego
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2selfAsServerGSS {
+
+ public static void main(String[] args) throws Exception {
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+ kdc.setOption(KDC.Option.PREAUTH_REQUIRED, false);
+ Map<String,List<String>> map = new HashMap<>();
+ map.put(OneKDC.SERVER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+ kdc.setOption(KDC.Option.ALLOW_S4U2SELF, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+
+ Context s, b;
+ System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+ System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+ File f = new File(OneKDC.JAAS_CONF);
+ FileOutputStream fos = new FileOutputStream(f);
+ fos.write((
+ "com.sun.security.jgss.krb5.accept {\n" +
+ " com.sun.security.auth.module.Krb5LoginModule required\n" +
+ " principal=\"" + OneKDC.SERVER + "\"\n" +
+ " useKeyTab=true\n" +
+ " storeKey=true;\n};\n"
+ ).getBytes());
+ fos.close();
+ Security.setProperty("auth.login.defaultCallbackHandler", "OneKDC$CallbackForClient");
+ s = Context.fromThinAir();
+ b = Context.fromThinAir();
+ s.startAsServer(mech);
+
+ Context p = s.impersonate(OneKDC.USER);
+
+ p.startAsClient(OneKDC.SERVER, mech);
+ b.startAsServer(mech);
+ Context.handshake(p, b);
+
+ String n1 = p.x().getSrcName().toString().split("@")[0];
+ String n2 = b.x().getSrcName().toString().split("@")[0];
+ if (!n1.equals(OneKDC.USER) || !n2.equals(OneKDC.USER)) {
+ throw new Exception("Delegation failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/S4U2selfGSS.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355584
+ * @summary Introduce constrained Kerberos delegation
+ * @compile -XDignore.symbol.file S4U2selfGSS.java
+ * @run main/othervm -Dsun.security.krb5.debug=false S4U2selfGSS krb5
+ * @run main/othervm -Dsun.security.krb5.debug=false S4U2selfGSS spnego
+ */
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class S4U2selfGSS {
+
+ public static void main(String[] args) throws Exception {
+ Oid mech;
+ if (args[0].equals("spnego")) {
+ mech = GSSUtil.GSS_SPNEGO_MECH_OID;
+ } else if (args[0].contains("krb5")) {
+ mech = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ throw new Exception("Unknown mech");
+ }
+
+ OneKDC kdc = new OneKDC(null);
+ kdc.writeJAASConf();
+ kdc.setOption(KDC.Option.ALLOW_S4U2SELF, Arrays.asList(
+ new String[]{OneKDC.USER + "@" + OneKDC.REALM}));
+ Map<String,List<String>> map = new HashMap<>();
+ map.put(OneKDC.USER + "@" + OneKDC.REALM, Arrays.asList(
+ new String[]{OneKDC.SERVER + "@" + OneKDC.REALM}));
+ kdc.setOption(KDC.Option.ALLOW_S4U2PROXY, map);
+
+ Context c, s;
+ System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+ c = Context.fromThinAir();
+ s = Context.fromThinAir();
+
+ c = c.impersonate(OneKDC.USER2);
+
+ c.startAsClient(OneKDC.SERVER, mech);
+ s.startAsServer(mech);
+
+ Context.handshake(c, s);
+
+ String n1 = c.x().getSrcName().toString().split("@")[0];
+ String n2 = s.x().getSrcName().toString().split("@")[0];
+ if (!n1.equals(OneKDC.USER2) || !n2.equals(OneKDC.USER2)) {
+ throw new Exception("Impersonate failed");
+ }
+
+ s.dispose();
+ c.dispose();
+ }
+}
--- a/jdk/test/sun/security/pkcs11/rsa/GenKeyStore.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/pkcs11/rsa/GenKeyStore.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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
@@ -54,8 +54,8 @@
certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V1));
certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(1));
certInfo.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algID));
- certInfo.set(X509CertInfo.SUBJECT, new CertificateSubjectName(name));
- certInfo.set(X509CertInfo.ISSUER, new CertificateIssuerName(name));
+ certInfo.set(X509CertInfo.SUBJECT, name);
+ certInfo.set(X509CertInfo.ISSUER, name);
certInfo.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
certInfo.set(X509CertInfo.VALIDITY, new CertificateValidity(date, date));
--- a/jdk/test/sun/security/provider/X509Factory/BigCRL.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/provider/X509Factory/BigCRL.java Thu Nov 15 00:54:54 2012 +0000
@@ -57,7 +57,7 @@
X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
X509CertImpl.NAME + "." + X509CertImpl.INFO);
X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "."
- + CertificateSubjectName.DN_NAME);
+ + X509CertInfo.DN_NAME);
Date date = new Date();
PrivateKey privateKey = (PrivateKey)
--- a/jdk/test/sun/security/rsa/GenKeyStore.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/rsa/GenKeyStore.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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
@@ -54,8 +54,8 @@
certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V1));
certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(1));
certInfo.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algID));
- certInfo.set(X509CertInfo.SUBJECT, new CertificateSubjectName(name));
- certInfo.set(X509CertInfo.ISSUER, new CertificateIssuerName(name));
+ certInfo.set(X509CertInfo.SUBJECT, name);
+ certInfo.set(X509CertInfo.ISSUER, name);
certInfo.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
certInfo.set(X509CertInfo.VALIDITY, new CertificateValidity(date, date));
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHost.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHost.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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,13 +21,15 @@
* questions.
*/
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
/**
* @test
* @bug 4302026
* @run main/othervm GetPeerHost
- *
- * SunJSSE does not support dynamic system properties, no way to re-use
- * system properties in samevm/agentvm mode.
* @summary make sure the server side doesn't do DNS lookup.
*/
import javax.net.*;
@@ -41,7 +43,8 @@
+ "/../../../../../../../etc/truststore");
GetPeerHostServer server = new GetPeerHostServer();
server.start();
- GetPeerHostClient client = new GetPeerHostClient();
+ GetPeerHostClient client =
+ new GetPeerHostClient(server.getServerPort());
client.start();
server.join ();
if (!server.getPassStatus ()) {
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostClient.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostClient.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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
@@ -38,13 +38,13 @@
SSLSocket s;
String server;
- public GetPeerHostClient ()
+ public GetPeerHostClient (int serverPort)
{
try {
SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory
.getDefault();
server = InetAddress.getLocalHost().getHostName();
- s = (SSLSocket) factory.createSocket(server, 9999);
+ s = (SSLSocket) factory.createSocket(server, serverPort);
System.out.println("CLIENT: connected to the server- " + server);
} catch (Exception e) {
System.err.println("Unexpected exceptions: " + e);
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostServer.java Wed Nov 14 10:20:25 2012 -0800
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostServer.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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
@@ -42,6 +42,7 @@
private String host;
ServerSocket ss;
boolean isHostIPAddr = false;
+ int serverPort = 0;
public GetPeerHostServer ()
{
@@ -57,7 +58,8 @@
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf = ctx.getServerSocketFactory();
- ss = ssf.createServerSocket(9999);
+ ss = ssf.createServerSocket(serverPort);
+ serverPort = ss.getLocalPort();
}catch (Exception e) {
System.err.println("Unexpected exceptions: " + e);
e.printStackTrace();
@@ -90,4 +92,8 @@
boolean getPassStatus () {
return isHostIPAddr;
}
+
+ int getServerPort() {
+ return serverPort;
+ }
}
--- a/langtools/.hgtags Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/.hgtags Thu Nov 15 00:54:54 2012 +0000
@@ -185,3 +185,4 @@
26020b247ad3806dbca33e029ee12e1b191f59f9 jdk8-b61
b47bb81ba962ef80bb6f0b863c33a0afcfb0b49e jdk8-b62
92e6f2190ca0567c857f85c3fb7a2be5adf079d0 jdk8-b63
+e6ee43b3e2473798b17a556e9f11eebe25ab81d4 jdk8-b64
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Thu Nov 15 00:54:54 2012 +0000
@@ -41,32 +41,21 @@
doclet.Help=Help
doclet.Skip_navigation_links=Skip navigation links
doclet.New_Page=NewPage
-doclet.None=None
-doclet.Factory_Method_Detail=Static Factory Method Detail
doclet.navDeprecated=Deprecated
-doclet.Deprecated_List=Deprecated List
doclet.Window_Deprecated_List=Deprecated List
-doclet.Note_0_is_deprecated=Note: {0} is deprecated.
doclet.Overrides=Overrides:
doclet.in_class=in class
-doclet.0_Fields_and_Methods="{0}" Fields and Methods
-doclet.Index_of_Fields_and_Methods=Index of Fields and Methods
doclet.Static_variable_in=Static variable in {0}
doclet.Variable_in=Variable in {0}
doclet.Constructor_for=Constructor for {0}
doclet.Static_method_in=Static method in {0}
doclet.Method_in=Method in {0}
-doclet.throws=throws
doclet.package=package
doclet.MalformedURL=Malformed URL: {0}
doclet.File_error=Error reading file: {0}
doclet.URL_error=Error fetching URL: {0}
-doclet.No_Package_Comment_File=For Package {0} Package.Comment file not found
-doclet.No_Source_For_Class=Source information for class {0} not available.
doclet.see.class_or_package_not_found=Tag {0}: reference not found: {1}
doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1}
-doclet.see.malformed_tag=Tag {0}: Malformed: {1}
-doclet.Inherited_API_Summary=Inherited API Summary
doclet.Deprecated_API=Deprecated API
doclet.Deprecated_Packages=Deprecated Packages
doclet.Deprecated_Classes=Deprecated Classes
@@ -92,10 +81,7 @@
doclet.deprecated_methods=deprecated methods
doclet.deprecated_enum_constants=deprecated enum constants
doclet.deprecated_annotation_type_members=deprecated annotation type elements
-doclet.Frame_Output=Frame Output
-doclet.Docs_generated_by_Javadoc=Documentation generated by Javadoc.
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)
-doclet.Blank=Blank
doclet.Other_Packages=Other Packages
doclet.Package_Description=Package {0} Description
doclet.Description=Description
@@ -105,32 +91,22 @@
doclet.Subinterfaces=All Known Subinterfaces:
doclet.Implementing_Classes=All Known Implementing Classes:
doclet.also=also
-doclet.Option=Option
-doclet.Or=Or
doclet.Frames=Frames
doclet.No_Frames=No Frames
doclet.Package_Hierarchies=Package Hierarchies:
doclet.Hierarchy_For_Package=Hierarchy For Package {0}
-doclet.Source_Code=Source Code:
doclet.Hierarchy_For_All_Packages=Hierarchy For All Packages
-doclet.Cannot_handle_no_packages=Cannot handle no packages.
doclet.Frame_Alert=Frame Alert
-doclet.Overview-Member-Frame=Overview Member Frame
doclet.Frame_Warning_Message=This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to {0}.
doclet.No_Script_Message=JavaScript is disabled on your browser.
doclet.Non_Frame_Version=Non-frame version
-doclet.Frame_Version=Frame version
-doclet.Following_From_Class=Following copied from class: {0}
-doclet.Following_From_Interface=Following copied from interface: {0}
doclet.Description_From_Interface=Description copied from interface:
doclet.Description_From_Class=Description copied from class:
-doclet.Standard_doclet_invoked=Standard doclet invoked...
doclet.No_Non_Deprecated_Classes_To_Document=No non-deprecated classes found to document.
doclet.Interfaces_Italic=Interfaces (italic)
doclet.Enclosing_Class=Enclosing class:
doclet.Enclosing_Interface=Enclosing interface:
doclet.Window_Source_title=Source code
-doclet.Help_title=API Help
doclet.Window_Help_title=API Help
doclet.Help_line_1=How This API Document Is Organized
doclet.Help_line_2=This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
@@ -168,19 +144,6 @@
doclet.Help_annotation_type_line_1=Each annotation type has its own separate page with the following sections:
doclet.Help_annotation_type_line_2=Annotation Type declaration
doclet.Help_annotation_type_line_3=Annotation Type description
-doclet.Style_line_1=Javadoc style sheet
-doclet.Style_line_2=Define colors, fonts and other style attributes here to override the defaults
-doclet.Style_line_3=Page background color
-doclet.Style_Headings=Headings
-doclet.Style_line_4=Table colors
-doclet.Style_line_5=Dark mauve
-doclet.Style_line_6=Light mauve
-doclet.Style_line_7=White
-doclet.Style_line_8=Font used in left-hand frame lists
-doclet.Style_line_9=Example of smaller, sans-serif font in frames
-doclet.Style_line_10=Navigation bar fonts and colors
-doclet.Style_line_11=Dark Blue
-doclet.Style_line_12=Table caption style
doclet.ClassUse_Packages.that.use.0=Packages that use {0}
doclet.ClassUse_Uses.of.0.in.1=Uses of {0} in {1}
doclet.ClassUse_Classes.in.0.used.by.1=Classes in {0} used by {1}
@@ -210,12 +173,9 @@
doclet.Window_ClassUse_Header=Uses of {0} {1}
doclet.ClassUse_Title=Uses of {0}<br>{1}
doclet.navClassUse=Use
-doclet.link_option_twice=Extern URL link option (link or linkoffline) used twice.
doclet.Error_in_packagelist=Error in using -group option: {0} {1}
doclet.Groupname_already_used=In -group option, groupname already used: {0}
doclet.Same_package_name_used=Package name format used twice: {0}
-doclet.Serialization.Excluded_Class=Non-transient field {1} uses excluded class {0}.
-doclet.Serialization.Nonexcluded_Class=Non-transient field {1} uses hidden, non-included class {0}.
doclet.exception_encountered=Exception encountered while processing {1}\n{0}
doclet.usage=Provided by Standard doclet:\n\
-d <directory> Destination directory for output files\n\
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Thu Nov 15 00:54:54 2012 +0000
@@ -21,10 +21,8 @@
doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}...
doclet.No_Public_Classes_To_Document=No public or protected classes found to document.
doclet.Unable_to_create_directory_0=Unable to create directory {0}
-doclet.destination_directory_not_found_0=Destination directory not found {0}
doclet.destination_directory_not_directory_0=Destination directory is not a directory {0}
doclet.destination_directory_not_writable_0=Destination directory not writable {0}
-doclet.Error_creating_tmp_file=Error creating temporary file, using default platform encoding.
doclet.Encoding_not_supported=Encoding not supported: {0}
doclet.Building_Tree=Building tree for all the packages and classes...
doclet.Building_Index=Building index for all the packages and classes...
@@ -74,7 +72,6 @@
doclet.Enum_Constant_Summary=Enum Constant Summary
doclet.Constructor_Summary=Constructor Summary
doclet.Method_Summary=Method Summary
-doclet.Factory_Method_Summary=Static Factory Method Summary
doclet.Interfaces=Interfaces
doclet.Enums=Enums
doclet.AnnotationTypes=Annotation Types
@@ -88,7 +85,6 @@
doclet.All_Implemented_Interfaces=All Implemented Interfaces:
doclet.All_classes_and_interfaces=All classes and interfaces (except non-static nested types)
doclet.Package_class_and_interface_descriptions=Package, class and interface descriptions
-doclet.Members=Members
doclet.Interface=Interface
doclet.Class=Class
doclet.AnnotationType=Annotation Type
@@ -107,18 +103,13 @@
doclet.Exception=Exception
doclet.exception=exception
doclet.exceptions=exceptions
-doclet.extended_by=extended by
-doclet.extends=extends
doclet.Package_private=(package private)
-doclet.implements=implementsdoclet.Same_package_name_used=Package name format used twice: {0}
doclet.Nested_Classes_Interfaces_Inherited_From_Class=Nested classes/interfaces inherited from class
doclet.Nested_Classes_Interface_Inherited_From_Interface=Nested classes/interfaces inherited from interface
doclet.Methods_Inherited_From_Class=Methods inherited from class
doclet.Methods_Inherited_From_Interface=Methods inherited from interface
doclet.Fields_Inherited_From_Class=Fields inherited from class
doclet.Fields_Inherited_From_Interface=Fields inherited from interface
-doclet.Serializable=Serializable
-doclet.Externalizable=Externalizable
doclet.Annotation_Type_Member_Detail=Element Detail
doclet.Enum_Constant_Detail=Enum Constant Detail
doclet.Constants_Summary=Constant Field Values
@@ -126,7 +117,6 @@
doclet.Method_Detail=Method Detail
doclet.Constructor_Detail=Constructor Detail
doclet.Deprecated=Deprecated.
-doclet.Deprecated_class=This class is deprecated.
doclet.Groupname_already_used=In -group option, groupname already used: {0}
doclet.value_tag_invalid_reference={0} (referenced by @value tag) is an unknown reference.
doclet.value_tag_invalid_constant=@value tag (which references {0}) can only be used in constants.
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Thu Nov 15 00:54:54 2012 +0000
@@ -555,7 +555,7 @@
*
* @param cd the ClassDoc to check.
* @param lowerCaseOnly true if you want the name returned in lower case.
- * If false, the first letter of the name is capatilized.
+ * If false, the first letter of the name is capitalized.
* @return
*/
public static String getTypeName(Configuration config,
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Thu Nov 15 00:54:54 2012 +0000
@@ -67,7 +67,6 @@
if ((mask&NATIVE) != 0) flags.add(Flag.NATIVE);
if ((mask&INTERFACE) != 0) flags.add(Flag.INTERFACE);
if ((mask&ABSTRACT) != 0) flags.add(Flag.ABSTRACT);
- if ((mask&DEFAULT) != 0) flags.add(Flag.DEFAULT);
if ((mask&STRICTFP) != 0) flags.add(Flag.STRICTFP);
if ((mask&BRIDGE) != 0) flags.add(Flag.BRIDGE);
if ((mask&SYNTHETIC) != 0) flags.add(Flag.SYNTHETIC);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Thu Nov 15 00:54:54 2012 +0000
@@ -206,6 +206,9 @@
public boolean allowDefaultMethods() {
return compareTo(JDK1_8) >= 0;
}
+ public boolean allowStrictMethodClashCheck() {
+ return compareTo(JDK1_8) >= 0;
+ }
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Nov 15 00:54:54 2012 +0000
@@ -1192,9 +1192,9 @@
// check for an inherited implementation
if ((flags() & ABSTRACT) != 0 ||
- (other.flags() & ABSTRACT) == 0 ||
- !other.isOverridableIn(origin) ||
- !this.isMemberOf(origin, types))
+ (other.flags() & ABSTRACT) == 0 ||
+ !other.isOverridableIn(origin) ||
+ !this.isMemberOf(origin, types))
return false;
// assert types.asSuper(origin.type, other.owner) != null;
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Thu Nov 15 00:54:54 2012 +0000
@@ -75,6 +75,7 @@
final boolean allowBoxing;
final boolean allowCovariantReturns;
final boolean allowObjectToPrimitiveCast;
+ final boolean allowDefaultMethods;
final ClassReader reader;
final Check chk;
JCDiagnostic.Factory diags;
@@ -98,6 +99,7 @@
allowBoxing = source.allowBoxing();
allowCovariantReturns = source.allowCovariantReturns();
allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
+ allowDefaultMethods = source.allowDefaultMethods();
reader = ClassReader.instance(context);
chk = Check.instance(context);
capturedName = names.fromString("<captured wildcard>");
@@ -2146,6 +2148,13 @@
return List.nil();
}
};
+
+ public boolean isDirectSuperInterface(Type t, TypeSymbol tsym) {
+ for (Type t2 : interfaces(tsym.type)) {
+ if (isSameType(t, t2)) return true;
+ }
+ return false;
+ }
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
@@ -2310,6 +2319,10 @@
return false;
}
+ public boolean overridesObjectMethod(Symbol msym) {
+ return ((MethodSymbol)msym).implementation(syms.objectType.tsym, this, true) != null;
+ }
+
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
class ImplementationCache {
@@ -2455,6 +2468,70 @@
}
// </editor-fold>
+
+ //where
+ public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
+ return interfaceCandidates(site, ms, false);
+ }
+
+ public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms, boolean intfOnly) {
+ Filter<Symbol> filter = new MethodFilter(ms, site, intfOnly);
+ List<MethodSymbol> candidates = List.nil();
+ for (Symbol s : membersClosure(site, false).getElements(filter)) {
+ if (!site.tsym.isInterface() && !s.owner.isInterface()) {
+ return List.of((MethodSymbol)s);
+ } else if (!candidates.contains(s)) {
+ candidates = candidates.prepend((MethodSymbol)s);
+ }
+ }
+ return prune(candidates, ownerComparator);
+ }
+
+ public List<MethodSymbol> prune(List<MethodSymbol> methods, Comparator<MethodSymbol> cmp) {
+ ListBuffer<MethodSymbol> methodsMin = ListBuffer.lb();
+ for (MethodSymbol m1 : methods) {
+ boolean isMin_m1 = true;
+ for (MethodSymbol m2 : methods) {
+ if (m1 == m2) continue;
+ if (cmp.compare(m2, m1) < 0) {
+ isMin_m1 = false;
+ break;
+ }
+ }
+ if (isMin_m1)
+ methodsMin.append(m1);
+ }
+ return methodsMin.toList();
+ }
+
+ Comparator<MethodSymbol> ownerComparator = new Comparator<MethodSymbol>() {
+ public int compare(MethodSymbol s1, MethodSymbol s2) {
+ return s1.owner.isSubClass(s2.owner, Types.this) ? -1 : 1;
+ }
+ };
+ // where
+ private class MethodFilter implements Filter<Symbol> {
+
+ Symbol msym;
+ Type site;
+ boolean intfOnly;
+
+ MethodFilter(Symbol msym, Type site, boolean intfOnly) {
+ this.msym = msym;
+ this.site = site;
+ this.intfOnly = intfOnly;
+ }
+
+ public boolean accepts(Symbol s) {
+ return s.kind == Kinds.MTH &&
+ (!intfOnly || s.owner.isInterface()) &&
+ s.name == msym.name &&
+ s.isInheritedIn(site.tsym, Types.this) &&
+ overrideEquivalent(memberType(site, s), memberType(site, msym));
+ }
+ };
+ // </editor-fold>
+
/**
* Does t have the same arguments as s? It is assumed that both
* types are (possibly polymorphic) method types. Monomorphic
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Nov 15 00:54:54 2012 +0000
@@ -135,6 +135,7 @@
allowStringsInSwitch = source.allowStringsInSwitch();
allowPoly = source.allowPoly() && options.isSet("allowPoly");
allowLambda = source.allowLambda();
+ allowDefaultMethods = source.allowDefaultMethods();
sourceName = source.name;
relax = (options.isSet("-retrofit") ||
options.isSet("-relax"));
@@ -178,6 +179,10 @@
*/
boolean allowCovariantReturns;
+ /** Switch: support default methods ?
+ */
+ boolean allowDefaultMethods;
+
/** Switch: support lambda expressions ?
*/
boolean allowLambda;
@@ -898,6 +903,10 @@
localEnv.info.lint = lint;
+ if (isDefaultMethod && types.overridesObjectMethod(m)) {
+ log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location());
+ }
+
// Enter all type parameters into the local method scope.
for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
localEnv.info.scope.enterIfAbsent(l.head.type.tsym);
@@ -961,10 +970,12 @@
log.error(tree.pos(),
"default.allowed.in.intf.annotation.member");
}
- } else if ((owner.flags() & INTERFACE) != 0 && !isDefaultMethod) {
- log.error(tree.body.pos(), "intf.meth.cant.have.body");
- } else if ((tree.mods.flags & ABSTRACT) != 0) {
- log.error(tree.pos(), "abstract.meth.cant.have.body");
+ } else if ((tree.sym.flags() & ABSTRACT) != 0 && !isDefaultMethod) {
+ if ((owner.flags() & INTERFACE) != 0) {
+ log.error(tree.body.pos(), "intf.meth.cant.have.body");
+ } else {
+ log.error(tree.pos(), "abstract.meth.cant.have.body");
+ }
} else if ((tree.mods.flags & NATIVE) != 0) {
log.error(tree.pos(), "native.meth.cant.have.body");
} else {
@@ -3281,6 +3292,23 @@
}
}
+ if (env.info.defaultSuperCallSite != null &&
+ !types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true).contains(sym)) {
+ Symbol ovSym = null;
+ for (MethodSymbol msym : types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true)) {
+ if (msym.overrides(sym, msym.enclClass(), types, true)) {
+ for (Type i : types.interfaces(env.enclClass.type)) {
+ if (i.tsym.isSubClass(msym.owner, types)) {
+ ovSym = i.tsym;
+ break;
+ }
+ }
+ }
+ }
+ log.error(env.tree.pos(), "illegal.default.super.call", env.info.defaultSuperCallSite,
+ diags.fragment("overridden.default", sym, ovSym));
+ }
+
// Compute the identifier's instantiated type.
// For methods, we need to compute the instance type by
// Resolve.instantiate from the symbol's type as well as
@@ -3700,6 +3728,9 @@
// are compatible (i.e. no two define methods with same arguments
// yet different return types). (JLS 8.4.6.3)
chk.checkCompatibleSupertypes(tree.pos(), c.type);
+ if (allowDefaultMethods) {
+ chk.checkDefaultMethodClashes(tree.pos(), c.type);
+ }
}
// Check that class does not import the same parameterized interface
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Thu Nov 15 00:54:54 2012 +0000
@@ -72,6 +72,10 @@
*/
Attr.ResultInfo returnResult = null;
+ /** Symbol corresponding to the site of a qualified default super call
+ */
+ Type defaultSuperCallSite = null;
+
/** Duplicate this context, replacing scope field and copying all others.
*/
AttrContext dup(Scope scope) {
@@ -84,6 +88,7 @@
info.lint = lint;
info.enclVar = enclVar;
info.returnResult = returnResult;
+ info.defaultSuperCallSite = defaultSuperCallSite;
return info;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Nov 15 00:54:54 2012 +0000
@@ -119,6 +119,9 @@
allowAnnotations = source.allowAnnotations();
allowCovariantReturns = source.allowCovariantReturns();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
+ allowDefaultMethods = source.allowDefaultMethods();
+ allowStrictMethodClashCheck = source.allowStrictMethodClashCheck() &&
+ options.isSet("strictMethodClashCheck"); //pre-lambda guard
complexInference = options.isSet("complexinference");
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
@@ -162,6 +165,14 @@
*/
boolean allowSimplifiedVarargs;
+ /** Switch: default methods enabled?
+ */
+ boolean allowDefaultMethods;
+
+ /** Switch: should unrelated return types trigger a method clash?
+ */
+ boolean allowStrictMethodClashCheck;
+
/** Switch: -complexinference option set?
*/
boolean complexInference;
@@ -1114,7 +1125,7 @@
} else if ((sym.owner.flags_field & INTERFACE) != 0) {
if ((flags & DEFAULT) != 0) {
mask = InterfaceDefaultMethodMask;
- implicit = PUBLIC;
+ implicit = PUBLIC | ABSTRACT;
} else {
mask = implicit = InterfaceMethodFlags;
}
@@ -2047,11 +2058,21 @@
undef == null && e != null;
e = e.sibling) {
if (e.sym.kind == MTH &&
- (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) {
+ (e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
MethodSymbol absmeth = (MethodSymbol)e.sym;
MethodSymbol implmeth = absmeth.implementation(impl, types, true);
- if (implmeth == null || implmeth == absmeth)
+ if (implmeth == null || implmeth == absmeth) {
+ //look for default implementations
+ if (allowDefaultMethods) {
+ MethodSymbol prov = types.interfaceCandidates(impl.type, absmeth).head;
+ if (prov != null && prov.overrides(absmeth, impl, types, true)) {
+ implmeth = prov;
+ }
+ }
+ }
+ if (implmeth == null || implmeth == absmeth) {
undef = absmeth;
+ }
}
}
if (undef == null) {
@@ -2354,7 +2375,7 @@
if (m2 == m1) continue;
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
//a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
- if (!types.isSubSignature(sym.type, types.memberType(site, m2), false) &&
+ if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
sym.flags_field |= CLASH;
String key = m1 == sym ?
@@ -2386,7 +2407,7 @@
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
- if (!types.isSubSignature(sym.type, types.memberType(site, s), false) &&
+ if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
log.error(pos,
"name.clash.same.erasure.no.hide",
@@ -2420,6 +2441,62 @@
}
}
+ void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
+ DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
+ for (Symbol m : types.membersClosure(site, false).getElements(dcf)) {
+ Assert.check(m.kind == MTH);
+ List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
+ if (prov.size() > 1) {
+ ListBuffer<Symbol> abstracts = ListBuffer.lb();
+ ListBuffer<Symbol> defaults = ListBuffer.lb();
+ for (MethodSymbol provSym : prov) {
+ if ((provSym.flags() & DEFAULT) != 0) {
+ defaults = defaults.append(provSym);
+ } else if ((provSym.flags() & ABSTRACT) != 0) {
+ abstracts = abstracts.append(provSym);
+ }
+ if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
+ //strong semantics - issue an error if two sibling interfaces
+ //have two override-equivalent defaults - or if one is abstract
+ //and the other is default
+ String errKey;
+ Symbol s1 = defaults.first();
+ Symbol s2;
+ if (defaults.size() > 1) {
+ errKey = "types.incompatible.unrelated.defaults";
+ s2 = defaults.toList().tail.head;
+ } else {
+ errKey = "types.incompatible.abstract.default";
+ s2 = abstracts.first();
+ }
+ log.error(pos, errKey,
+ Kinds.kindName(site.tsym), site,
+ m.name, types.memberType(site, m).getParameterTypes(),
+ s1.location(), s2.location());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //where
+ private class DefaultMethodClashFilter implements Filter<Symbol> {
+
+ Type site;
+
+ DefaultMethodClashFilter(Type site) {
+ this.site = site;
+ }
+
+ public boolean accepts(Symbol s) {
+ return s.kind == MTH &&
+ (s.flags() & DEFAULT) != 0 &&
+ s.isInheritedIn(site.tsym, types) &&
+ !s.isConstructor();
+ }
+ }
+
/** Report a conflict between a user symbol and a synthetic symbol.
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Nov 15 00:54:54 2012 +0000
@@ -502,7 +502,7 @@
JCNewClass tree = make.NewClass(null,
null, make.QualIdent(ctype.tsym), args, null);
tree.constructor = rs.resolveConstructor(
- make_pos, attrEnv, ctype, TreeInfo.types(args), null, false, false);
+ make_pos, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil());
tree.type = ctype;
return tree;
}
@@ -3631,15 +3631,26 @@
public void visitSelect(JCFieldAccess tree) {
// need to special case-access of the form C.super.x
- // these will always need an access method.
+ // these will always need an access method, unless C
+ // is a default interface subclassed by the current class.
boolean qualifiedSuperAccess =
tree.selected.hasTag(SELECT) &&
- TreeInfo.name(tree.selected) == names._super;
+ TreeInfo.name(tree.selected) == names._super &&
+ !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type, currentClass);
tree.selected = translate(tree.selected);
- if (tree.name == names._class)
+ if (tree.name == names._class) {
result = classOf(tree.selected);
- else if (tree.name == names._this || tree.name == names._super)
+ }
+ else if (tree.name == names._super &&
+ types.isDirectSuperInterface(tree.selected.type, currentClass)) {
+ //default super call!! Not a classic qualified super call
+ TypeSymbol supSym = tree.selected.type.tsym;
+ Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
+ result = tree;
+ }
+ else if (tree.name == names._this || tree.name == names._super) {
result = makeThis(tree.pos(), tree.selected.type.tsym);
+ }
else
result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Nov 15 00:54:54 2012 +0000
@@ -560,6 +560,12 @@
MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner);
m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree);
tree.sym = m;
+
+ //if this is a default method, add the DEFAULT flag to the enclosing interface
+ if ((tree.mods.flags & DEFAULT) != 0) {
+ m.enclClass().flags_field |= DEFAULT;
+ }
+
Env<AttrContext> localEnv = methodEnv(tree, env);
DeferredLintHandler prevLintHandler =
@@ -677,7 +683,7 @@
localEnv.info.scope.owner = tree.sym;
}
if ((tree.mods.flags & STATIC) != 0 ||
- (env.enclClass.sym.flags() & INTERFACE) != 0)
+ ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null))
localEnv.info.staticLevel++;
return localEnv;
}
@@ -1001,20 +1007,19 @@
}
}
- // If this is a class, enter symbols for this and super into
- // current scope.
- if ((c.flags_field & INTERFACE) == 0) {
- VarSymbol thisSym =
- new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
- thisSym.pos = Position.FIRSTPOS;
- env.info.scope.enter(thisSym);
- if (ct.supertype_field.hasTag(CLASS)) {
- VarSymbol superSym =
- new VarSymbol(FINAL | HASINIT, names._super,
- ct.supertype_field, c);
- superSym.pos = Position.FIRSTPOS;
- env.info.scope.enter(superSym);
- }
+ // enter symbols for 'this' into current scope.
+ VarSymbol thisSym =
+ new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
+ thisSym.pos = Position.FIRSTPOS;
+ env.info.scope.enter(thisSym);
+ // if this is a class, enter symbol for 'super' into current scope.
+ if ((c.flags_field & INTERFACE) == 0 &&
+ ct.supertype_field.hasTag(CLASS)) {
+ VarSymbol superSym =
+ new VarSymbol(FINAL | HASINIT, names._super,
+ ct.supertype_field, c);
+ superSym.pos = Position.FIRSTPOS;
+ env.info.scope.enter(superSym);
}
// check that no package exists with same fully qualified name,
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Nov 15 00:54:54 2012 +0000
@@ -51,7 +51,10 @@
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Set;
import javax.lang.model.element.ElementVisitor;
@@ -88,6 +91,7 @@
public final boolean boxingEnabled; // = source.allowBoxing();
public final boolean varargsEnabled; // = source.allowVarargs();
public final boolean allowMethodHandles;
+ public final boolean allowDefaultMethods;
private final boolean debugResolve;
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
@@ -122,6 +126,7 @@
verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
Target target = Target.instance(context);
allowMethodHandles = target.hasMethodHandles();
+ allowDefaultMethods = source.allowDefaultMethods();
polymorphicSignatureScope = new Scope(syms.noSymbol);
inapplicableMethodException = new InapplicableMethodException(diags);
@@ -447,22 +452,9 @@
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
- Warner warn)
- throws Infer.InferenceException {
- if (useVarargs && (m.flags() & VARARGS) == 0) {
- //better error recovery - if we stumbled upon a non-varargs method
- //during varargs applicability phase, the method should be treated as
- //not applicable; the reason for inapplicability can be found in the
- //candidate for 'm' that was created during the BOX phase.
- Candidate prevCandidate = currentResolutionContext.getCandidate(m, BOX);
- JCDiagnostic details = null;
- if (prevCandidate != null && !prevCandidate.isApplicable()) {
- details = prevCandidate.details;
- }
- throw inapplicableMethodException.setMessage(details);
- }
+ Warner warn) throws Infer.InferenceException {
+
Type mt = types.memberType(site, m);
-
// tvars is the list of formal type variables for which type arguments
// need to inferred.
List<Type> tvars = List.nil();
@@ -1020,8 +1012,11 @@
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
- if (sym.kind == ERR) return bestSoFar;
- if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
+ if (sym.kind == ERR ||
+ !sym.isInheritedIn(site.tsym, types) ||
+ (useVarargs && (sym.flags() & VARARGS) == 0)) {
+ return bestSoFar;
+ }
Assert.check(sym.kind < AMBIGUOUS);
try {
Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
@@ -1032,13 +1027,13 @@
if (!operator)
currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
switch (bestSoFar.kind) {
- case ABSENT_MTH:
- return new InapplicableSymbolError(currentResolutionContext);
- case WRONG_MTH:
- if (operator) return bestSoFar;
- bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
- default:
- return bestSoFar;
+ case ABSENT_MTH:
+ return new InapplicableSymbolError(currentResolutionContext);
+ case WRONG_MTH:
+ if (operator) return bestSoFar;
+ bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
+ default:
+ return bestSoFar;
}
}
if (!isAccessible(env, site, sym)) {
@@ -1327,6 +1322,42 @@
}
}
+ Symbol findMethodInScope(Env<AttrContext> env,
+ Type site,
+ Name name,
+ List<Type> argtypes,
+ List<Type> typeargtypes,
+ Scope sc,
+ Symbol bestSoFar,
+ boolean allowBoxing,
+ boolean useVarargs,
+ boolean operator,
+ boolean abstractok) {
+ for (Symbol s : sc.getElementsByName(name, new LookupFilter(abstractok))) {
+ bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
+ bestSoFar, allowBoxing, useVarargs, operator);
+ }
+ return bestSoFar;
+ }
+ //where
+ class LookupFilter implements Filter<Symbol> {
+
+ boolean abstractOk;
+
+ LookupFilter(boolean abstractOk) {
+ this.abstractOk = abstractOk;
+ }
+
+ public boolean accepts(Symbol s) {
+ long flags = s.flags();
+ return s.kind == MTH &&
+ (flags & SYNTHETIC) == 0 &&
+ (abstractOk ||
+ (flags & DEFAULT) != 0 ||
+ (flags & ABSTRACT) == 0);
+ }
+ };
+
/** Find best qualified method matching given name, type and value
* arguments.
* @param env The current environment.
@@ -1371,49 +1402,76 @@
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
- boolean abstractOk = true;
- List<Type> itypes = List.nil();
+ @SuppressWarnings({"unchecked","rawtypes"})
+ List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
+ InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
for (TypeSymbol s : superclasses(intype)) {
- bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
+ bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
- //We should not look for abstract methods if receiver is a concrete class
- //(as concrete classes are expected to implement all abstracts coming
- //from superinterfaces)
- abstractOk &= (s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0;
- if (abstractOk) {
+ if (name == names.init) return bestSoFar;
+ iphase = (iphase == null) ? null : iphase.update(s, this);
+ if (iphase != null) {
for (Type itype : types.interfaces(s.type)) {
- itypes = types.union(types.closure(itype), itypes);
+ itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]);
}
}
- if (name == names.init) break;
}
Symbol concrete = bestSoFar.kind < ERR &&
(bestSoFar.flags() & ABSTRACT) == 0 ?
bestSoFar : methodNotFound;
- if (name != names.init) {
+ for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) {
+ if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && !allowDefaultMethods) break;
//keep searching for abstract methods
- for (Type itype : itypes) {
+ for (Type itype : itypes[iphase2.ordinal()]) {
if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
- bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
- itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
- if (concrete != bestSoFar &&
- concrete.kind < ERR && bestSoFar.kind < ERR &&
- types.isSubSignature(concrete.type, bestSoFar.type)) {
- //this is an hack - as javac does not do full membership checks
- //most specific ends up comparing abstract methods that might have
- //been implemented by some concrete method in a subclass and,
- //because of raw override, it is possible for an abstract method
- //to be more specific than the concrete method - so we need
- //to explicitly call that out (see CR 6178365)
- bestSoFar = concrete;
- }
+ if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
+ (itype.tsym.flags() & DEFAULT) == 0) continue;
+ bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
+ itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
+ if (concrete != bestSoFar &&
+ concrete.kind < ERR && bestSoFar.kind < ERR &&
+ types.isSubSignature(concrete.type, bestSoFar.type)) {
+ //this is an hack - as javac does not do full membership checks
+ //most specific ends up comparing abstract methods that might have
+ //been implemented by some concrete method in a subclass and,
+ //because of raw override, it is possible for an abstract method
+ //to be more specific than the concrete method - so we need
+ //to explicitly call that out (see CR 6178365)
+ bestSoFar = concrete;
+ }
}
}
return bestSoFar;
}
+ enum InterfaceLookupPhase {
+ ABSTRACT_OK() {
+ @Override
+ InterfaceLookupPhase update(Symbol s, Resolve rs) {
+ //We should not look for abstract methods if receiver is a concrete class
+ //(as concrete classes are expected to implement all abstracts coming
+ //from superinterfaces)
+ if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) {
+ return this;
+ } else if (rs.allowDefaultMethods) {
+ return DEFAULT_OK;
+ } else {
+ return null;
+ }
+ }
+ },
+ DEFAULT_OK() {
+ @Override
+ InterfaceLookupPhase update(Symbol s, Resolve rs) {
+ return this;
+ }
+ };
+
+ abstract InterfaceLookupPhase update(Symbol s, Resolve rs);
+ }
+
/**
* Return an Iterable object to scan the superclasses of a given type.
* It's crucial that the scan is done lazily, as we don't want to accidentally
@@ -1467,34 +1525,6 @@
};
}
- /**
- * Lookup a method with given name and argument types in a given scope
- */
- Symbol lookupMethod(Env<AttrContext> env,
- Type site,
- Name name,
- List<Type> argtypes,
- List<Type> typeargtypes,
- Scope sc,
- Symbol bestSoFar,
- boolean allowBoxing,
- boolean useVarargs,
- boolean operator,
- boolean abstractok) {
- for (Symbol s : sc.getElementsByName(name, lookupFilter)) {
- bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
- bestSoFar, allowBoxing, useVarargs, operator);
- }
- return bestSoFar;
- }
- //where
- Filter<Symbol> lookupFilter = new Filter<Symbol>() {
- public boolean accepts(Symbol s) {
- return s.kind == MTH &&
- (s.flags() & SYNTHETIC) == 0;
- }
- };
-
/** Find unqualified method matching given name, type and value arguments.
* @param env The current environment.
* @param name The method's name.
@@ -1898,7 +1928,7 @@
((InapplicableSymbolError)errSym).errCandidate().sym : accessedSym;
List<Type> argtypes2 = Type.map(argtypes,
- deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, msym, currentResolutionContext.firstErroneousResolutionPhase()));
+ deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, msym, currentResolutionContext.step));
if (msym != accessedSym) {
//fixup deferred type caches - this 'hack' is required because the symbol
@@ -1920,7 +1950,7 @@
/** Check that sym is not an abstract method.
*/
void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
- if ((sym.flags() & ABSTRACT) != 0)
+ if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0)
log.error(pos, "abstract.cant.be.accessed.directly",
kindName(sym), sym, sym.location());
}
@@ -1992,33 +2022,14 @@
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = new MethodResolutionContext();
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
- sym = findFun(env, name, argtypes, typeargtypes,
- steps.head.isBoxingRequired,
- steps.head.isVarargsRequired);
- currentResolutionContext.resolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ return lookupMethod(env, pos, env.enclClass.sym, new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) {
+ @Override
+ Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return findFun(env, name, argtypes, typeargtypes,
+ phase.isBoxingRequired(),
+ phase.isVarargsRequired());
}
- if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
- MethodResolutionPhase errPhase =
- currentResolutionContext.firstErroneousResolutionPhase();
- sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
- pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
- env.info.pendingResolutionPhase = errPhase;
- }
- return sym;
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
+ });
}
/** Resolve a qualified method identifier
@@ -2044,40 +2055,27 @@
DiagnosticPosition pos, Env<AttrContext> env,
Symbol location, Type site, Name name, List<Type> argtypes,
List<Type> typeargtypes) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = resolveContext;
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
- sym = findMethod(env, site, name, argtypes, typeargtypes,
- steps.head.isBoxingRequired(),
- steps.head.isVarargsRequired(), false);
- currentResolutionContext.resolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) {
+ @Override
+ Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return findMethod(env, site, name, argtypes, typeargtypes,
+ phase.isBoxingRequired(),
+ phase.isVarargsRequired(), false);
}
- if (sym.kind >= AMBIGUOUS) {
- //if nothing is found return the 'first' error
- MethodResolutionPhase errPhase =
- currentResolutionContext.firstErroneousResolutionPhase();
- sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
- pos, location, site, name, true, argtypes, typeargtypes);
- env.info.pendingResolutionPhase = errPhase;
- } else if (allowMethodHandles) {
- MethodSymbol msym = (MethodSymbol)sym;
- if (msym.isSignaturePolymorphic(types)) {
- env.info.pendingResolutionPhase = BASIC;
- return findPolymorphicSignatureInstance(env, sym, argtypes);
+ @Override
+ Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+ if (sym.kind >= AMBIGUOUS) {
+ sym = super.access(env, pos, location, sym);
+ } else if (allowMethodHandles) {
+ MethodSymbol msym = (MethodSymbol)sym;
+ if (msym.isSignaturePolymorphic(types)) {
+ env.info.pendingResolutionPhase = BASIC;
+ return findPolymorphicSignatureInstance(env, sym, argtypes);
+ }
}
+ return sym;
}
- return sym;
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
+ });
}
/** Find or create an implicit method of exactly the given type (after erasure).
@@ -2145,38 +2143,53 @@
List<Type> typeargtypes) {
return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes);
}
+
private Symbol resolveConstructor(MethodResolutionContext resolveContext,
- DiagnosticPosition pos,
+ final DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = resolveContext;
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
- sym = findConstructor(pos, env, site, argtypes, typeargtypes,
- steps.head.isBoxingRequired(),
- steps.head.isVarargsRequired());
- currentResolutionContext.resolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
+ @Override
+ Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return findConstructor(pos, env, site, argtypes, typeargtypes,
+ phase.isBoxingRequired(),
+ phase.isVarargsRequired());
}
- if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
- MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
- sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
- pos, site, names.init, true, argtypes, typeargtypes);
- env.info.pendingResolutionPhase = errPhase;
- }
- return sym;
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
+ });
+ }
+
+ /** Resolve a constructor, throw a fatal error if not found.
+ * @param pos The position to use for error reporting.
+ * @param env The environment current at the method invocation.
+ * @param site The type to be constructed.
+ * @param argtypes The types of the invocation's value arguments.
+ * @param typeargtypes The types of the invocation's type arguments.
+ */
+ public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env,
+ Type site,
+ List<Type> argtypes,
+ List<Type> typeargtypes) {
+ MethodResolutionContext resolveContext = new MethodResolutionContext();
+ resolveContext.internalResolution = true;
+ Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes);
+ if (sym.kind == MTH) return (MethodSymbol)sym;
+ else throw new FatalError(
+ diags.fragment("fatal.err.cant.locate.ctor", site));
+ }
+
+ Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
+ Type site, List<Type> argtypes,
+ List<Type> typeargtypes,
+ boolean allowBoxing,
+ boolean useVarargs) {
+ Symbol sym = findMethod(env, site,
+ names.init, argtypes,
+ typeargtypes, allowBoxing,
+ useVarargs, false);
+ chk.checkDeprecated(pos, env.info.scope.owner, sym);
+ return sym;
}
/** Resolve constructor using diamond inference.
@@ -2194,47 +2207,36 @@
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = new MethodResolutionContext();
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
- sym = findDiamond(env, site, argtypes, typeargtypes,
- steps.head.isBoxingRequired(),
- steps.head.isVarargsRequired());
- currentResolutionContext.resolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ return lookupMethod(env, pos, site.tsym, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
+ @Override
+ Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return findDiamond(env, site, argtypes, typeargtypes,
+ phase.isBoxingRequired(),
+ phase.isVarargsRequired());
}
- if (sym.kind >= AMBIGUOUS) {
- Symbol errSym =
- currentResolutionContext.resolutionCache.get(currentResolutionContext.firstErroneousResolutionPhase());
- final JCDiagnostic details = errSym.kind == WRONG_MTH ?
- ((InapplicableSymbolError)errSym).errCandidate().details :
- null;
- errSym = new InapplicableSymbolError(errSym.kind, "diamondError", currentResolutionContext) {
- @Override
- JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
- Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
- String key = details == null ?
- "cant.apply.diamond" :
- "cant.apply.diamond.1";
- return diags.create(dkind, log.currentSource(), pos, key,
- diags.fragment("diamond", site.tsym), details);
- }
- };
- MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
- sym = accessMethod(errSym, pos, site, names.init, true, argtypes, typeargtypes);
- env.info.pendingResolutionPhase = errPhase;
+ @Override
+ Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+ if (sym.kind >= AMBIGUOUS) {
+ final JCDiagnostic details = sym.kind == WRONG_MTH ?
+ ((InapplicableSymbolError)sym).errCandidate().details :
+ null;
+ sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
+ @Override
+ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
+ Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+ String key = details == null ?
+ "cant.apply.diamond" :
+ "cant.apply.diamond.1";
+ return diags.create(dkind, log.currentSource(), pos, key,
+ diags.fragment("diamond", site.tsym), details);
+ }
+ };
+ sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
+ env.info.pendingResolutionPhase = currentResolutionContext.step;
+ }
+ return sym;
}
- return sym;
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
+ });
}
/** This method scans all the constructor symbol in a given class scope -
@@ -2281,392 +2283,7 @@
return bestSoFar;
}
- /**
- * Resolution of member references is typically done as a single
- * overload resolution step, where the argument types A are inferred from
- * the target functional descriptor.
- *
- * If the member reference is a method reference with a type qualifier,
- * a two-step lookup process is performed. The first step uses the
- * expected argument list A, while the second step discards the first
- * type from A (which is treated as a receiver type).
- *
- * There are two cases in which inference is performed: (i) if the member
- * reference is a constructor reference and the qualifier type is raw - in
- * which case diamond inference is used to infer a parameterization for the
- * type qualifier; (ii) if the member reference is an unbound reference
- * where the type qualifier is raw - in that case, during the unbound lookup
- * the receiver argument type is used to infer an instantiation for the raw
- * qualifier type.
- *
- * When a multi-step resolution process is exploited, it is an error
- * if two candidates are found (ambiguity).
- *
- * This routine returns a pair (T,S), where S is the member reference symbol,
- * and T is the type of the class in which S is defined. This is necessary as
- * the type T might be dynamically inferred (i.e. if constructor reference
- * has a raw qualifier).
- */
- Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
- Env<AttrContext> env,
- JCMemberReference referenceTree,
- Type site,
- Name name, List<Type> argtypes,
- List<Type> typeargtypes,
- boolean boxingAllowed) {
- //step 1 - bound lookup
- ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
- new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, boxingAllowed) :
- new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
- Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
- Symbol boundSym = findMemberReference(boundEnv, boundLookupHelper);
-
- //step 2 - unbound lookup
- ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
- Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
- Symbol unboundSym = findMemberReference(unboundEnv, unboundLookupHelper);
-
- //merge results
- Pair<Symbol, ReferenceLookupHelper> res;
- if (unboundSym.kind != MTH) {
- res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
- env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
- } else if (boundSym.kind == MTH) {
- res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
- env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
- } else {
- res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
- env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
- }
-
- return res;
- }
-
- /**
- * Helper for defining custom method-like lookup logic; a lookup helper
- * provides hooks for (i) the actual lookup logic and (ii) accessing the
- * lookup result (this step might result in compiler diagnostics to be generated)
- */
- abstract class LookupHelper {
-
- /** name of the symbol to lookup */
- Name name;
-
- /** location in which the lookup takes place */
- Type site;
-
- /** actual types used during the lookup */
- List<Type> argtypes;
-
- /** type arguments used during the lookup */
- List<Type> typeargtypes;
-
- LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
- this.name = name;
- this.site = site;
- this.argtypes = argtypes;
- this.typeargtypes = typeargtypes;
- }
-
- /**
- * Search for a symbol under a given overload resolution phase - this method
- * is usually called several times, once per each overload resolution phase
- */
- abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
-
- /**
- * Validate the result of the lookup
- */
- abstract Symbol access(Env<AttrContext> env, Symbol symbol);
- }
-
- /**
- * Helper class for member reference lookup. A reference lookup helper
- * defines the basic logic for member reference lookup; a method gives
- * access to an 'unbound' helper used to perform an unbound member
- * reference lookup.
- */
- abstract class ReferenceLookupHelper extends LookupHelper {
-
- /** The member reference tree */
- JCMemberReference referenceTree;
-
- /** Max overload resolution phase handled by this helper */
- MethodResolutionPhase maxPhase;
-
- ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
- List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
- super(name, site, argtypes, typeargtypes);
- this.referenceTree = referenceTree;
- this.maxPhase = boxingAllowed ? VARARITY : BASIC;
- }
-
- /**
- * Returns an unbound version of this lookup helper. By default, this
- * method returns an dummy lookup helper.
- */
- ReferenceLookupHelper unboundLookup() {
- //dummy loopkup helper that always return 'methodNotFound'
- return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase.isBoxingRequired()) {
- @Override
- ReferenceLookupHelper unboundLookup() {
- return this;
- }
- @Override
- Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
- return methodNotFound;
- }
- @Override
- ReferenceKind referenceKind(Symbol sym) {
- Assert.error();
- return null;
- }
- };
- }
-
- /**
- * Get the kind of the member reference
- */
- abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
-
- @Override
- Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
- return (env.info.pendingResolutionPhase.ordinal() > maxPhase.ordinal()) ?
- methodNotFound : lookupReference(env, phase);
- }
-
- abstract Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase);
-
- Symbol access(Env<AttrContext> env, Symbol sym) {
- if (sym.kind >= AMBIGUOUS) {
- MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
- if (errPhase.ordinal() > maxPhase.ordinal()) {
- errPhase = maxPhase;
- }
- env.info.pendingResolutionPhase = errPhase;
- sym = currentResolutionContext.resolutionCache.get(errPhase);
- }
- return sym;
- }
- }
-
- /**
- * Helper class for method reference lookup. The lookup logic is based
- * upon Resolve.findMethod; in certain cases, this helper class has a
- * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
- * In such cases, non-static lookup results are thrown away.
- */
- class MethodReferenceLookupHelper extends ReferenceLookupHelper {
-
- MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
- List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
- super(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
- }
-
- protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
- return findMethod(env, site, name, argtypes, typeargtypes,
- phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
- }
-
- protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
- return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
- sym.kind != MTH ||
- sym.isStatic() ? sym : new StaticError(sym);
- }
-
- @Override
- final Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
- return adjustLookupResult(env, lookupReferenceInternal(env, phase));
- }
-
- @Override
- ReferenceLookupHelper unboundLookup() {
- if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
- argtypes.nonEmpty() &&
- types.isSubtypeUnchecked(argtypes.head, site)) {
- return new UnboundMethodReferenceLookupHelper(referenceTree, name,
- site, argtypes, typeargtypes, maxPhase.isBoxingRequired());
- } else {
- return super.unboundLookup();
- }
- }
-
- @Override
- ReferenceKind referenceKind(Symbol sym) {
- if (sym.isStatic()) {
- return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
- ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
- } else {
- Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
- return selName != null && selName == names._super ?
- ReferenceKind.SUPER :
- ReferenceKind.BOUND;
- }
- }
- }
-
- /**
- * Helper class for unbound method reference lookup. Essentially the same
- * as the basic method reference lookup helper; main difference is that static
- * lookup results are thrown away. If qualifier type is raw, an attempt to
- * infer a parameterized type is made using the first actual argument (that
- * would otherwise be ignored during the lookup).
- */
- class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
-
- UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
- List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
- super(referenceTree, name,
- site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site,
- argtypes.tail, typeargtypes, boxingAllowed);
- }
-
- @Override
- protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
- return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
- }
-
- @Override
- ReferenceLookupHelper unboundLookup() {
- return this;
- }
-
- @Override
- ReferenceKind referenceKind(Symbol sym) {
- return ReferenceKind.UNBOUND;
- }
- }
-
- /**
- * Helper class for constructor reference lookup. The lookup logic is based
- * upon either Resolve.findMethod or Resolve.findDiamond - depending on
- * whether the constructor reference needs diamond inference (this is the case
- * if the qualifier type is raw). A special erroneous symbol is returned
- * if the lookup returns the constructor of an inner class and there's no
- * enclosing instance in scope.
- */
- class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
-
- boolean needsInference;
-
- ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
- List<Type> typeargtypes, boolean boxingAllowed) {
- super(referenceTree, names.init, site, argtypes, typeargtypes, boxingAllowed);
- if (site.isRaw()) {
- this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym);
- needsInference = true;
- }
- }
-
- @Override
- protected Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
- Symbol sym = needsInference ?
- findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
- findMethod(env, site, name, argtypes, typeargtypes,
- phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
- return sym.kind != MTH ||
- site.getEnclosingType().hasTag(NONE) ||
- hasEnclosingInstance(env, site) ?
- sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
- @Override
- JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
- return diags.create(dkind, log.currentSource(), pos,
- "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
- }
- };
- }
-
- @Override
- ReferenceKind referenceKind(Symbol sym) {
- return site.getEnclosingType().hasTag(NONE) ?
- ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
- }
- }
-
- /**
- * Resolution step for member reference. This generalizes a standard
- * method/constructor lookup - on each overload resolution step, a
- * lookup helper class is used to perform the reference lookup; at the end
- * of the lookup, the helper is used to validate the results.
- */
- Symbol findMemberReference(Env<AttrContext> env, LookupHelper lookupHelper) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = new MethodResolutionContext();
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
- sym = lookupHelper.lookup(env, steps.head);
- currentResolutionContext.resolutionCache.put(steps.head, sym);
- steps = steps.tail;
- }
- return lookupHelper.access(env, sym);
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
- }
-
- /** Resolve constructor.
- * @param pos The position to use for error reporting.
- * @param env The environment current at the constructor invocation.
- * @param site The type of class for which a constructor is searched.
- * @param argtypes The types of the constructor invocation's value
- * arguments.
- * @param typeargtypes The types of the constructor invocation's type
- * arguments.
- * @param allowBoxing Allow boxing and varargs conversions.
- * @param useVarargs Box trailing arguments into an array for varargs.
- */
- Symbol resolveConstructor(DiagnosticPosition pos, Env<AttrContext> env,
- Type site, List<Type> argtypes,
- List<Type> typeargtypes,
- boolean allowBoxing,
- boolean useVarargs) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = new MethodResolutionContext();
- return findConstructor(pos, env, site, argtypes, typeargtypes, allowBoxing, useVarargs);
- }
- finally {
- currentResolutionContext = prevResolutionContext;
- }
- }
-
- Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
- Type site, List<Type> argtypes,
- List<Type> typeargtypes,
- boolean allowBoxing,
- boolean useVarargs) {
- Symbol sym = findMethod(env, site,
- names.init, argtypes,
- typeargtypes, allowBoxing,
- useVarargs, false);
- chk.checkDeprecated(pos, env.info.scope.owner, sym);
- return sym;
- }
-
- /** Resolve a constructor, throw a fatal error if not found.
- * @param pos The position to use for error reporting.
- * @param env The environment current at the method invocation.
- * @param site The type to be constructed.
- * @param argtypes The types of the invocation's value arguments.
- * @param typeargtypes The types of the invocation's type arguments.
- */
- public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env,
- Type site,
- List<Type> argtypes,
- List<Type> typeargtypes) {
- MethodResolutionContext resolveContext = new MethodResolutionContext();
- resolveContext.internalResolution = true;
- Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes);
- if (sym.kind == MTH) return (MethodSymbol)sym;
- else throw new FatalError(
- diags.fragment("fatal.err.cant.locate.ctor", site));
- }
+
/** Resolve operator.
* @param pos The position to use for error reporting.
@@ -2719,6 +2336,350 @@
}
/**
+ * Resolution of member references is typically done as a single
+ * overload resolution step, where the argument types A are inferred from
+ * the target functional descriptor.
+ *
+ * If the member reference is a method reference with a type qualifier,
+ * a two-step lookup process is performed. The first step uses the
+ * expected argument list A, while the second step discards the first
+ * type from A (which is treated as a receiver type).
+ *
+ * There are two cases in which inference is performed: (i) if the member
+ * reference is a constructor reference and the qualifier type is raw - in
+ * which case diamond inference is used to infer a parameterization for the
+ * type qualifier; (ii) if the member reference is an unbound reference
+ * where the type qualifier is raw - in that case, during the unbound lookup
+ * the receiver argument type is used to infer an instantiation for the raw
+ * qualifier type.
+ *
+ * When a multi-step resolution process is exploited, it is an error
+ * if two candidates are found (ambiguity).
+ *
+ * This routine returns a pair (T,S), where S is the member reference symbol,
+ * and T is the type of the class in which S is defined. This is necessary as
+ * the type T might be dynamically inferred (i.e. if constructor reference
+ * has a raw qualifier).
+ */
+ Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
+ Env<AttrContext> env,
+ JCMemberReference referenceTree,
+ Type site,
+ Name name, List<Type> argtypes,
+ List<Type> typeargtypes,
+ boolean boxingAllowed) {
+ MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
+ //step 1 - bound lookup
+ ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
+ new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) :
+ new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
+ Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
+ Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper);
+
+ //step 2 - unbound lookup
+ ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
+ Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
+ Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, unboundLookupHelper);
+
+ //merge results
+ Pair<Symbol, ReferenceLookupHelper> res;
+ if (unboundSym.kind != MTH) {
+ res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
+ env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+ } else if (boundSym.kind == MTH) {
+ res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
+ env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+ } else {
+ res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
+ env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
+ }
+
+ return res;
+ }
+
+ /**
+ * Helper for defining custom method-like lookup logic; a lookup helper
+ * provides hooks for (i) the actual lookup logic and (ii) accessing the
+ * lookup result (this step might result in compiler diagnostics to be generated)
+ */
+ abstract class LookupHelper {
+
+ /** name of the symbol to lookup */
+ Name name;
+
+ /** location in which the lookup takes place */
+ Type site;
+
+ /** actual types used during the lookup */
+ List<Type> argtypes;
+
+ /** type arguments used during the lookup */
+ List<Type> typeargtypes;
+
+ /** Max overload resolution phase handled by this helper */
+ MethodResolutionPhase maxPhase;
+
+ LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ this.name = name;
+ this.site = site;
+ this.argtypes = argtypes;
+ this.typeargtypes = typeargtypes;
+ this.maxPhase = maxPhase;
+ }
+
+ /**
+ * Should lookup stop at given phase with given result
+ */
+ protected boolean shouldStop(Symbol sym, MethodResolutionPhase phase) {
+ return phase.ordinal() > maxPhase.ordinal() ||
+ sym.kind < ERRONEOUS || sym.kind == AMBIGUOUS;
+ }
+
+ /**
+ * Search for a symbol under a given overload resolution phase - this method
+ * is usually called several times, once per each overload resolution phase
+ */
+ abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
+
+ /**
+ * Validate the result of the lookup
+ */
+ abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym);
+ }
+
+ abstract class BasicLookupHelper extends LookupHelper {
+
+ BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
+ super(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY);
+ }
+
+ @Override
+ Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+ if (sym.kind >= AMBIGUOUS) {
+ //if nothing is found return the 'first' error
+ sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
+ }
+ return sym;
+ }
+ }
+
+ /**
+ * Helper class for member reference lookup. A reference lookup helper
+ * defines the basic logic for member reference lookup; a method gives
+ * access to an 'unbound' helper used to perform an unbound member
+ * reference lookup.
+ */
+ abstract class ReferenceLookupHelper extends LookupHelper {
+
+ /** The member reference tree */
+ JCMemberReference referenceTree;
+
+ ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+ List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ super(name, site, argtypes, typeargtypes, maxPhase);
+ this.referenceTree = referenceTree;
+
+ }
+
+ /**
+ * Returns an unbound version of this lookup helper. By default, this
+ * method returns an dummy lookup helper.
+ */
+ ReferenceLookupHelper unboundLookup() {
+ //dummy loopkup helper that always return 'methodNotFound'
+ return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) {
+ @Override
+ ReferenceLookupHelper unboundLookup() {
+ return this;
+ }
+ @Override
+ Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return methodNotFound;
+ }
+ @Override
+ ReferenceKind referenceKind(Symbol sym) {
+ Assert.error();
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Get the kind of the member reference
+ */
+ abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
+
+ Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+ //skip error reporting
+ return sym;
+ }
+ }
+
+ /**
+ * Helper class for method reference lookup. The lookup logic is based
+ * upon Resolve.findMethod; in certain cases, this helper class has a
+ * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
+ * In such cases, non-static lookup results are thrown away.
+ */
+ class MethodReferenceLookupHelper extends ReferenceLookupHelper {
+
+ MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+ List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ super(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
+ }
+
+ protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return findMethod(env, site, name, argtypes, typeargtypes,
+ phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+ }
+
+ protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+ return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
+ sym.kind != MTH ||
+ sym.isStatic() ? sym : new StaticError(sym);
+ }
+
+ @Override
+ final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ return adjustLookupResult(env, lookupReferenceInternal(env, phase));
+ }
+
+ @Override
+ ReferenceLookupHelper unboundLookup() {
+ if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
+ argtypes.nonEmpty() &&
+ types.isSubtypeUnchecked(argtypes.head, site)) {
+ return new UnboundMethodReferenceLookupHelper(referenceTree, name,
+ site, argtypes, typeargtypes, maxPhase);
+ } else {
+ return super.unboundLookup();
+ }
+ }
+
+ @Override
+ ReferenceKind referenceKind(Symbol sym) {
+ if (sym.isStatic()) {
+ return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
+ ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
+ } else {
+ Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
+ return selName != null && selName == names._super ?
+ ReferenceKind.SUPER :
+ ReferenceKind.BOUND;
+ }
+ }
+ }
+
+ /**
+ * Helper class for unbound method reference lookup. Essentially the same
+ * as the basic method reference lookup helper; main difference is that static
+ * lookup results are thrown away. If qualifier type is raw, an attempt to
+ * infer a parameterized type is made using the first actual argument (that
+ * would otherwise be ignored during the lookup).
+ */
+ class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
+
+ UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+ List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ super(referenceTree, name,
+ site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site,
+ argtypes.tail, typeargtypes, maxPhase);
+ }
+
+ @Override
+ protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+ return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
+ }
+
+ @Override
+ ReferenceLookupHelper unboundLookup() {
+ return this;
+ }
+
+ @Override
+ ReferenceKind referenceKind(Symbol sym) {
+ return ReferenceKind.UNBOUND;
+ }
+ }
+
+ /**
+ * Helper class for constructor reference lookup. The lookup logic is based
+ * upon either Resolve.findMethod or Resolve.findDiamond - depending on
+ * whether the constructor reference needs diamond inference (this is the case
+ * if the qualifier type is raw). A special erroneous symbol is returned
+ * if the lookup returns the constructor of an inner class and there's no
+ * enclosing instance in scope.
+ */
+ class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
+
+ boolean needsInference;
+
+ ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
+ List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
+ if (site.isRaw()) {
+ this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym);
+ needsInference = true;
+ }
+ }
+
+ @Override
+ protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ Symbol sym = needsInference ?
+ findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
+ findMethod(env, site, name, argtypes, typeargtypes,
+ phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+ return sym.kind != MTH ||
+ site.getEnclosingType().hasTag(NONE) ||
+ hasEnclosingInstance(env, site) ?
+ sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
+ @Override
+ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+ return diags.create(dkind, log.currentSource(), pos,
+ "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
+ }
+ };
+ }
+
+ @Override
+ ReferenceKind referenceKind(Symbol sym) {
+ return site.getEnclosingType().hasTag(NONE) ?
+ ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
+ }
+ }
+
+ /**
+ * Main overload resolution routine. On each overload resolution step, a
+ * lookup helper class is used to perform the method/constructor lookup;
+ * at the end of the lookup, the helper is used to validate the results
+ * (this last step might trigger overload resolution diagnostics).
+ */
+ Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, LookupHelper lookupHelper) {
+ return lookupMethod(env, pos, location, new MethodResolutionContext(), lookupHelper);
+ }
+
+ Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location,
+ MethodResolutionContext resolveContext, LookupHelper lookupHelper) {
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ Symbol bestSoFar = methodNotFound;
+ currentResolutionContext = resolveContext;
+ for (MethodResolutionPhase phase : methodResolutionSteps) {
+ if (!phase.isApplicable(boxingEnabled, varargsEnabled) ||
+ lookupHelper.shouldStop(bestSoFar, phase)) break;
+ MethodResolutionPhase prevPhase = currentResolutionContext.step;
+ Symbol prevBest = bestSoFar;
+ currentResolutionContext.step = phase;
+ bestSoFar = phase.mergeResults(bestSoFar, lookupHelper.lookup(env, phase));
+ env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase;
+ }
+ return lookupHelper.access(env, pos, location, bestSoFar);
+ } finally {
+ currentResolutionContext = prevResolutionContext;
+ }
+ }
+
+ /**
* Resolve `c.name' where name == this or name == super.
* @param pos The position to use for error reporting.
* @param env The environment current at the expression.
@@ -2744,9 +2705,47 @@
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
env1 = env1.outer;
}
+ if (allowDefaultMethods && c.isInterface() &&
+ name == names._super && !isStatic(env) &&
+ types.isDirectSuperInterface(c.type, env.enclClass.sym)) {
+ //this might be a default super call if one of the superinterfaces is 'c'
+ for (Type t : pruneInterfaces(env.enclClass.type)) {
+ if (t.tsym == c) {
+ env.info.defaultSuperCallSite = t;
+ return new VarSymbol(0, names._super,
+ types.asSuper(env.enclClass.type, c), env.enclClass.sym);
+ }
+ }
+ //find a direct superinterface that is a subtype of 'c'
+ for (Type i : types.interfaces(env.enclClass.type)) {
+ if (i.tsym.isSubClass(c, types) && i.tsym != c) {
+ log.error(pos, "illegal.default.super.call", c,
+ diags.fragment("redundant.supertype", c, i));
+ return syms.errSymbol;
+ }
+ }
+ Assert.error();
+ }
log.error(pos, "not.encl.class", c);
return syms.errSymbol;
}
+ //where
+ private List<Type> pruneInterfaces(Type t) {
+ ListBuffer<Type> result = ListBuffer.lb();
+ for (Type t1 : types.interfaces(t)) {
+ boolean shouldAdd = true;
+ for (Type t2 : types.interfaces(t)) {
+ if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) {
+ shouldAdd = false;
+ }
+ }
+ if (shouldAdd) {
+ result.append(t1);
+ }
+ }
+ return result.toList();
+ }
+
/**
* Resolve `c.this' for an enclosing class c that contains the
@@ -3114,20 +3113,14 @@
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
}
- protected boolean shouldReport(Candidate c) {
- MethodResolutionPhase errPhase = resolveContext.firstErroneousResolutionPhase();
- return !c.isApplicable() &&
- c.step == errPhase;
- }
-
private Candidate errCandidate() {
+ Candidate bestSoFar = null;
for (Candidate c : resolveContext.candidates) {
- if (shouldReport(c)) {
- return c;
- }
+ if (c.isApplicable()) continue;
+ bestSoFar = c;
}
- Assert.error();
- return null;
+ Assert.checkNonNull(bestSoFar);
+ return bestSoFar;
}
}
@@ -3156,7 +3149,7 @@
pos,
"cant.apply.symbols",
name == names.init ? KindName.CONSTRUCTOR : absentKind(kind),
- getName(),
+ name == names.init ? site.tsym.name : name,
argtypes);
return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(site));
} else {
@@ -3167,24 +3160,17 @@
//where
List<JCDiagnostic> candidateDetails(Type site) {
- List<JCDiagnostic> details = List.nil();
+ Map<Symbol, JCDiagnostic> details = new LinkedHashMap<Symbol, JCDiagnostic>();
for (Candidate c : resolveContext.candidates) {
- if (!shouldReport(c)) continue;
+ if (c.isApplicable()) continue;
JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
Kinds.kindName(c.sym),
c.sym.location(site, types),
c.sym.asMemberOf(site, types),
c.details);
- details = details.prepend(detailDiag);
+ details.put(c.sym, detailDiag);
}
- return details.reverse();
- }
-
- private Name getName() {
- Symbol sym = resolveContext.candidates.head.sym;
- return sym.name == names.init ?
- sym.owner.name :
- sym.name;
+ return List.from(details.values());
}
}
@@ -3322,7 +3308,21 @@
enum MethodResolutionPhase {
BASIC(false, false),
BOX(true, false),
- VARARITY(true, true);
+ VARARITY(true, true) {
+ @Override
+ public Symbol mergeResults(Symbol bestSoFar, Symbol sym) {
+ switch (sym.kind) {
+ case WRONG_MTH:
+ return (bestSoFar.kind == WRONG_MTH || bestSoFar.kind == WRONG_MTHS) ?
+ bestSoFar :
+ sym;
+ case ABSENT_MTH:
+ return bestSoFar;
+ default:
+ return sym;
+ }
+ }
+ };
boolean isBoxingRequired;
boolean isVarargsRequired;
@@ -3344,6 +3344,10 @@
return (varargsEnabled || !isVarargsRequired) &&
(boxingEnabled || !isBoxingRequired);
}
+
+ public Symbol mergeResults(Symbol prev, Symbol sym) {
+ return sym;
+ }
}
final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
@@ -3359,29 +3363,11 @@
private List<Candidate> candidates = List.nil();
- private Map<MethodResolutionPhase, Symbol> resolutionCache =
- new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class);
-
MethodResolutionPhase step = null;
private boolean internalResolution = false;
private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
- private MethodResolutionPhase firstErroneousResolutionPhase() {
- MethodResolutionPhase bestSoFar = BASIC;
- Symbol sym = methodNotFound;
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= WRONG_MTHS) {
- sym = resolutionCache.get(steps.head);
- if (sym.kind == ABSENT_MTH) break; //ignore spurious empty entries
- bestSoFar = steps.head;
- steps = steps.tail;
- }
- return bestSoFar;
- }
-
void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
candidates = candidates.append(c);
@@ -3392,16 +3378,6 @@
candidates = candidates.append(c);
}
- Candidate getCandidate(Symbol sym, MethodResolutionPhase phase) {
- for (Candidate c : currentResolutionContext.candidates) {
- if (c.step == phase &&
- c.sym.baseSymbol() == sym.baseSymbol()) {
- return c;
- }
- }
- return null;
- }
-
/**
* This class represents an overload resolution candidate. There are two
* kinds of candidates: applicable methods and inapplicable methods;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Thu Nov 15 00:54:54 2012 +0000
@@ -503,6 +503,14 @@
result = sr;
}
+ @Override
+ public void visitLetExpr(LetExpr tree) {
+ SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
+ sr.mergeWith(csp(tree.defs));
+ sr.mergeWith(csp(tree.expr));
+ result = sr;
+ }
+
public void visitTypeParameter(JCTypeParameter tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
sr.mergeWith(csp(tree.bounds));
@@ -525,7 +533,7 @@
*/
public int startPos(JCTree tree) {
if (tree == null) return Position.NOPOS;
- return tree.pos;
+ return TreeInfo.getStartPos(tree);
}
/** The end position of given tree, if it has
@@ -533,9 +541,7 @@
*/
public int endPos(JCTree tree) {
if (tree == null) return Position.NOPOS;
- if (tree.hasTag(JCTree.Tag.BLOCK))
- return ((JCBlock) tree).endpos;
- return endPosTable.getEndPos(tree);
+ return TreeInfo.getEndPos(tree, endPosTable);
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Nov 15 00:54:54 2012 +0000
@@ -115,6 +115,9 @@
*/
boolean lintClassfile;
+ /** Switch: allow default methods
+ */
+ boolean allowDefaultMethods;
/** Switch: preserve parameter names from the variable table.
*/
@@ -279,6 +282,7 @@
allowVarargs = source.allowVarargs();
allowAnnotations = source.allowAnnotations();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
+ allowDefaultMethods = source.allowDefaultMethods();
saveParameterNames = options.isSet("save-parameter-names");
cacheCompletionFailure = options.isUnset("dev");
preferSource = "source".equals(options.get("-Xprefer"));
@@ -937,6 +941,18 @@
new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
+ if (currentOwner.isInterface() &&
+ (sym.flags_field & ABSTRACT) == 0 && !name.equals(names.clinit)) {
+ if (majorVersion > Target.JDK1_8.majorVersion ||
+ //todo replace with Target.Version when available
+ (majorVersion == Target.JDK1_8.majorVersion && minorVersion >= Target.JDK1_8.minorVersion)) {
+ currentOwner.flags_field |= DEFAULT;
+ sym.flags_field |= DEFAULT | ABSTRACT;
+ } else {
+ //protect against ill-formed classfiles
+ throw new CompletionFailure(currentOwner, "default method found in pre JDK 8 classfile");
+ }
+ }
if (readAllOfClassFile || saveParameterNames)
((MethodSymbol)sym).code = readCode(sym);
else
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Nov 15 00:54:54 2012 +0000
@@ -1540,7 +1540,7 @@
List<Type> interfaces = types.interfaces(c.type);
List<Type> typarams = c.type.getTypeArguments();
- int flags = adjustFlags(c.flags());
+ int flags = adjustFlags(c.flags() & ~DEFAULT);
if ((flags & PROTECTED) != 0) flags |= PUBLIC;
flags = flags & ClassFlags & ~STRICTFP;
if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
@@ -1676,6 +1676,8 @@
result |= ACC_BRIDGE;
if ((flags & VARARGS) != 0 && target.useVarargsFlag())
result |= ACC_VARARGS;
+ if ((flags & DEFAULT) != 0)
+ result &= ~ABSTRACT;
return result;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java Thu Nov 15 00:54:54 2012 +0000
@@ -523,7 +523,7 @@
Item invoke() {
MethodType mtype = (MethodType)member.externalType(types);
int rescode = Code.typecode(mtype.restype);
- if ((member.owner.flags() & Flags.INTERFACE) != 0) {
+ if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
code.emitInvokeinterface(pool.put(member), mtype);
} else if (nonvirtual) {
code.emitInvokespecial(pool.put(member), mtype);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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
@@ -68,8 +68,8 @@
/** JDK 7. */
JDK1_7("1.7", 51, 0),
- /** JDK 8. */ // For now, a clone of 7
- JDK1_8("1.8", 51, 0);
+ /** JDK 8. */
+ JDK1_8("1.8", 52, 0);
private static final Context.Key<Target> targetKey =
new Context.Key<Target>();
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Thu Nov 15 00:54:54 2012 +0000
@@ -533,7 +533,7 @@
* annotation processor.
*/
void apMessage(AnnotationProcessingError ex) {
- log.printLines("msg.proc.annotation.uncaught.exception");
+ log.printLines(PrefixKind.JAVAC, "msg.proc.annotation.uncaught.exception");
ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE));
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Nov 15 00:54:54 2012 +0000
@@ -88,6 +88,15 @@
/** End position mappings container */
private final AbstractEndPosTable endPosTable;
+ interface ErrorRecoveryAction {
+ JCTree doRecover(JavacParser parser);
+ }
+
+ enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
+ BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
+ CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
+ }
+
/** Construct a parser from a given scanner, tree factory and log.
*/
protected JavacParser(ParserFactory fac,
@@ -2102,11 +2111,15 @@
nextToken();
return toP(F.at(pos).Skip());
case ELSE:
- return toP(F.Exec(syntaxError("else.without.if")));
+ int elsePos = token.pos;
+ nextToken();
+ return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
case FINALLY:
- return toP(F.Exec(syntaxError("finally.without.try")));
+ int finallyPos = token.pos;
+ nextToken();
+ return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
case CATCH:
- return toP(F.Exec(syntaxError("catch.without.try")));
+ return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
case ASSERT: {
if (allowAsserts && token.kind == ASSERT) {
nextToken();
@@ -2139,6 +2152,13 @@
}
}
+ private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
+ int errPos = S.errPos();
+ JCTree stm = action.doRecover(this);
+ S.errPos(errPos);
+ return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
+ }
+
/** CatchClause = CATCH "(" FormalParameter ")" Block
*/
protected JCCatch catchClause() {
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Nov 15 00:54:54 2012 +0000
@@ -574,7 +574,7 @@
interface expected here
compiler.err.intf.meth.cant.have.body=\
- interface methods cannot have body
+ interface abstract methods cannot have body
compiler.err.invalid.annotation.member.type=\
invalid type for annotation member
@@ -941,6 +941,31 @@
compiler.err.types.incompatible.diff.ret=\
types {0} and {1} are incompatible; both define {2}, but with unrelated return types
+# 0: kind, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol
+compiler.err.types.incompatible.unrelated.defaults=\
+ {0} {1} inherits unrelated defaults for {2}({3}) from types {4} and {5}
+
+# 0: kind, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol
+compiler.err.types.incompatible.abstract.default=\
+ {0} {1} inherits abstract and default for {2}({3}) from types {4} and {5}
+
+# 0: name, 1: kind, 2: symbol
+compiler.err.default.overrides.object.member=\
+ default method {0} in {1} {2} overrides a member of java.lang.Object
+
+# 0: type, 1: message segment
+compiler.err.illegal.default.super.call=\
+ bad type qualifier {0} in default super call\n\
+ {1}
+
+# 0: symbol, 1: type
+compiler.misc.overridden.default=\
+ method {0} is overridden in {2}
+
+# 0: symbol, 1: symbol
+compiler.misc.redundant.supertype=\
+ redundant interface {0} is extended by {1}
+
compiler.err.unclosed.char.lit=\
unclosed character literal
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Thu Nov 15 00:54:54 2012 +0000
@@ -81,6 +81,9 @@
docenv.makeAnnotationTypeElementDoc(meth, docComment, tree, lineMap);
else
docenv.makeMethodDoc(meth, docComment, tree, lineMap);
+
+ // release resources
+ tree.body = null;
}
@Override
--- a/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Thu Nov 15 00:54:54 2012 +0000
@@ -267,8 +267,6 @@
}
if (referencedClass == null) { /* may just not be in this run */
-// docenv().warning(holder, "tag.see.class_not_found",
-// where, text);
// check if it's a package name
referencedPackage = docenv().lookupPackage(where);
return;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Start.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Start.java Thu Nov 15 00:54:54 2012 +0000
@@ -54,6 +54,8 @@
* @author Neal Gafter (rewrite)
*/
class Start {
+ /** Context for this invocation. */
+ private final Context context;
private final String defaultDocletClassName;
private final ClassLoader docletParentClassLoader;
@@ -69,7 +71,7 @@
private long defaultFilter = PUBLIC | PROTECTED;
- private Messager messager;
+ private final Messager messager;
String docLocale = "";
@@ -96,8 +98,8 @@
PrintWriter noticeWriter,
String defaultDocletClassName,
ClassLoader docletParentClassLoader) {
- Context tempContext = new Context(); // interim context until option decoding completed
- messager = new Messager(tempContext, programName, errWriter, warnWriter, noticeWriter);
+ context = new Context();
+ messager = new Messager(context, programName, errWriter, warnWriter, noticeWriter);
this.defaultDocletClassName = defaultDocletClassName;
this.docletParentClassLoader = docletParentClassLoader;
}
@@ -108,8 +110,8 @@
Start(String programName, String defaultDocletClassName,
ClassLoader docletParentClassLoader) {
- Context tempContext = new Context(); // interim context until option decoding completed
- messager = new Messager(tempContext, programName);
+ context = new Context();
+ messager = new Messager(context, programName);
this.defaultDocletClassName = defaultDocletClassName;
this.docletParentClassLoader = docletParentClassLoader;
}
@@ -219,16 +221,6 @@
ListBuffer<String> subPackages = new ListBuffer<String>();
ListBuffer<String> excludedPackages = new ListBuffer<String>();
- Context context = new Context();
- // Setup a new Messager, using the same initial parameters as the
- // existing Messager, except that this one will be able to use any
- // options that may be set up below.
- Messager.preRegister(context,
- messager.programName,
- messager.getWriter(Log.WriterKind.ERROR),
- messager.getWriter(Log.WriterKind.WARNING),
- messager.getWriter(Log.WriterKind.NOTICE));
-
Options compOpts = Options.instance(context);
boolean docClasses = false;
@@ -368,6 +360,7 @@
javaNames.append(arg);
}
}
+ compOpts.notifyListeners();
if (javaNames.isEmpty() && subPackages.isEmpty()) {
usageError("main.No_packages_or_classes_specified");
@@ -394,14 +387,13 @@
// legacy?
languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1, quiet);
+ // release resources
+ comp = null;
+
// pass off control to the doclet
boolean ok = root != null;
if (ok) ok = docletInvoker.start(root);
- Messager docletMessager = Messager.instance0(context);
- messager.nwarnings += docletMessager.nwarnings;
- messager.nerrors += docletMessager.nerrors;
-
// We're done.
if (compOpts.get("-verbose") != null) {
tm = System.currentTimeMillis() - tm;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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
@@ -64,7 +64,6 @@
main.incompatible.access.flags=More than one of -public, -private, -package, or -protected specified.
main.cant.read=cannot read {0}
main.Loading_source_files_for_package=Loading source files for package {0}...
-main.Loading_source_file_for_class=Loading source file for class {0}...
main.Loading_source_file=Loading source file {0}...
main.Building_tree=Constructing Javadoc information...
main.no_source_files_for_package=No source files for package {0}
@@ -96,13 +95,12 @@
tag.see.can_not_find_member=Tag {0}: can''t find {1} in {2}
tag.see.no_close_bracket_on_url=Tag {0}: missing final ''>'': "{1}"
tag.see.no_close_quote=Tag {0}: no final close quote: "{1}"
-tag.see.class_not_found=class {0} not found for @see tag: "{1}"
tag.see.class_not_specified=Tag {0}: class not specified: "{1}"
tag.see.illegal_character=Tag {0}:illegal character: "{1}" in "{2}"
tag.see.malformed_see_tag=Tag {0}: malformed: "{1}"
-tag.throws.exception_not_found={0} tag, class {1} not found.
tag.End_delimiter_missing_for_possible_SeeTag=End Delimiter } missing for possible See Tag in comment string: "{0}"
tag.Improper_Use_Of_Link_Tag=Missing closing ''}'' character for inline tag: "{0}"
+tag.serialField.illegal_character=illegal character {0} in @serialField tag: {1}.
javadoc.File_Read_Error=Error while reading file {0}
javadoc.Body_missing_from_html_file=Body tag missing from HTML file
javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file
@@ -110,4 +108,3 @@
javadoc.class_not_found=Class {0} not found.
javadoc.error=error
javadoc.warning=warning
-tag.serialField.illegal_character=illegal character {0} in @serialField tag: {1}.
--- a/langtools/test/tools/javac/7132880/T7132880.out Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/7132880/T7132880.out Thu Nov 15 00:54:54 2012 +0000
@@ -1,4 +1,4 @@
T7132880.java:23:12: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
-T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Double))),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)))}
+T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Double)))}
T7132880.java:43:12: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.lang.Object,int), Outer.Inner3, kindname.method, m2(int,java.lang.Object), Outer.Inner3
3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8002286/T8002286.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8002286
+ * @summary Resolve should support nested resolution contexts
+ * @compile/fail/ref=T8002286.out -XDrawDiagnostics T8002286.java
+ */
+class T8002286 {
+ @Anno(nonExistent())
+ static class Test { }
+
+ @interface Anno { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8002286/T8002286.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,3 @@
+T8002286.java:8:22: compiler.err.cant.resolve.location.args: kindname.method, value, , , (compiler.misc.location: kindname.annotation, T8002286.Anno, null)
+T8002286.java:8:11: compiler.err.cant.resolve.location.args: kindname.method, nonExistent, , , (compiler.misc.location: kindname.class, T8002286, null)
+2 errors
--- a/langtools/test/tools/javac/Diagnostics/6799605/T6799605.out Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/Diagnostics/6799605/T6799605.out Thu Nov 15 00:54:54 2012 +0000
@@ -1,4 +1,4 @@
-T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.type.captureof: 1, ?, T6799605<compiler.misc.type.captureof: 1, ?>))}
-T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ?, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
-T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 3, ?, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
+T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.type.captureof: 1, ?, T6799605<compiler.misc.type.captureof: 1, ?>)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
+T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ?, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
+T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 3, ?, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?))}
3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8002157
+ * @author sogoel
+ * @summary Basic Syntax test for repeating annotations on all elements
+ * @build Helper
+ * @compile BasicSyntaxCombo.java
+ * @run main BasicSyntaxCombo
+ */
+
+
+import java.util.Arrays;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+import javax.tools.Diagnostic;
+
+/*
+ * Generate test src for element kinds with repeating annotations.
+ * The test uses Helper.java to get the template to create test src and
+ * compile the test src.
+ * The test passes if valid test src compile as expected and
+ * and invalid test src fail as expected.
+ */
+
+public class BasicSyntaxCombo extends Helper{
+ static int errors = 0;
+ static boolean exitMode = false;
+ static String TESTPKG = "testpkg";
+ static String srcContent = "";
+ static String pkgInfoContent = "";
+
+ static {
+ // If EXIT_ON_FAIL is set, the combo test will exit at the first error
+ String exitOnFail = System.getenv("EXIT_ON_FAIL");
+ if (exitOnFail == null || exitOnFail == "" ) {
+ exitMode = false;
+ }
+ else {
+ if (exitOnFail.equalsIgnoreCase("YES") ||
+ exitOnFail.equalsIgnoreCase("Y") ||
+ exitOnFail.equalsIgnoreCase("TRUE") ||
+ exitOnFail.equalsIgnoreCase("T")) {
+ exitMode = true;
+ }
+ }
+ }
+
+ enum TestElem {
+ ANNOTATION_TYPE(true),
+ PACKAGE(true),
+ CONSTRUCTOR(true),
+ FIELD(true),
+ LOCAL_VARIABLE(true),
+ METHOD(true),
+ TYPE(true),
+ PARAMETER(true),
+ INNER_CLASS(true),
+ STATIC_INI(false),
+ INSTANCE_INI(false);
+
+ TestElem(boolean compile) {
+ this.compile = compile;
+ }
+
+ boolean compile;
+ boolean shouldCompile() {
+ return compile;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ new BasicSyntaxCombo().runTest();
+ }
+
+ public void runTest() throws Exception {
+ boolean result = false;
+ Iterable<? extends JavaFileObject> files = null;
+ int testCtr = 0;
+ for (TestElem type : TestElem.values()) {
+ testCtr++;
+ String className = "BasicCombo_"+type;
+ files = getFileList(className, type);
+
+ boolean shouldCompile = type.shouldCompile();
+ result = getCompileResult(className, shouldCompile,files);
+
+ if (shouldCompile && !result) {
+ error(className + " did not compile as expected", srcContent);
+ if(!pkgInfoContent.isEmpty()) {
+ System.out.println("package-info.java contents: " + pkgInfoContent);
+ }
+ }
+
+ if (!shouldCompile && !result) {
+ error(className + " compiled unexpectedly", srcContent);
+ if(!pkgInfoContent.isEmpty()) {
+ System.out.println("package-info.java contents: " + pkgInfoContent);
+ }
+ }
+ }
+
+ System.out.println("Total number of tests run: " + testCtr);
+ System.out.println("Total number of errors: " + errors);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ private boolean getCompileResult(String className, boolean shouldCompile,
+ Iterable<? extends JavaFileObject> files) throws Exception {
+
+ DiagnosticCollector<JavaFileObject> diagnostics =
+ new DiagnosticCollector<JavaFileObject>();
+ boolean ok = Helper.compileCode(diagnostics,files);
+ if (!shouldCompile && !ok) {
+ checkErrorKeys(className, diagnostics);
+ }
+ return (shouldCompile == ok);
+ }
+
+ private void checkErrorKeys (
+ String className, DiagnosticCollector<JavaFileObject> diagnostics) throws Exception {
+ String expectedErrKey = "compiler.err.illegal.start.of.type";
+ for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
+ if ((d.getKind() == Diagnostic.Kind.ERROR) &&
+ d.getCode().contains(expectedErrKey)) {
+ break; // Found the expected error
+ } else {
+ error("Incorrect error key, expected = "
+ + expectedErrKey + ", Actual = " + d.getCode()
+ + " for className = " + className, srcContent);
+ }
+ }
+ }
+
+ private Iterable<? extends JavaFileObject> getFileList(String className,
+ TestElem type ) {
+
+ String template = Helper.template;
+ String replaceStr = "/*"+type+"*/";
+ StringBuilder annoData = new StringBuilder();
+ annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+
+ JavaFileObject pkgInfoFile = null;
+
+ if (type.equals("PACKAGE")) {
+ srcContent = template.replace(replaceStr, "package testpkg;")
+ .replace("#ClassName", className);
+
+ String pkgInfoName = TESTPKG+"."+"package-info";
+ pkgInfoContent = Helper.ContentVars.REPEATABLEANNO.getVal()
+ + "package " + TESTPKG + ";"
+ + annoData;
+ pkgInfoFile = getFile(pkgInfoName, pkgInfoContent);
+ } else {
+ template = template.replace(replaceStr, Helper.ContentVars.REPEATABLEANNO.getVal())
+ .replace("#ClassName", className);
+ srcContent = annoData + template;
+ }
+
+ JavaFileObject srcFile = getFile(className, srcContent);
+
+ Iterable<? extends JavaFileObject> files = null;
+ if (pkgInfoFile != null) {
+ files = Arrays.asList(pkgInfoFile,srcFile);
+ }
+ else {
+ files = Arrays.asList(srcFile);
+ }
+ return files;
+ }
+
+ private void error(String msg, String... contents) throws Exception {
+ System.out.println("error: " + msg);
+ errors++;
+ if (contents.length == 1) {
+ System.out.println("Contents = " + contents[0]);
+ }
+ // Test exits as soon as it gets a failure
+ if (exitMode) throw new Exception();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8002157
+ * @author sogoel
+ * @summary Combo test to check for usage of Deprecated
+ * @build Helper
+ * @compile DeprecatedAnnoCombo.java
+ * @run main DeprecatedAnnoCombo
+ */
+
+import java.util.List;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+
+/*
+ * Generate test src for use of @Deprecated on base anno
+ * or container anno or on both. In all cases, test src should compile and a
+ * warning should be generated. Repeating annotations used only on class for
+ * these generated test src.
+ */
+
+public class DeprecatedAnnoCombo extends Helper {
+ static int errors = 0;
+
+ enum TestCases {
+ DeprecatedonBoth,
+ DeprecatedonContainer,
+ DeprecatedonBase;
+ }
+
+ public static void main(String[] args) throws Exception {
+ new DeprecatedAnnoCombo().runTest();
+ }
+
+ public void runTest() throws Exception {
+ boolean ok = false;
+ int testCtr = 0;
+
+ for (TestCases clName : TestCases.values()) {
+ testCtr++;
+
+ // Create test source content
+ String contents = getContent(clName.toString());
+
+ // Compile the generated source file
+ DiagnosticCollector<JavaFileObject> diagnostics =
+ new DiagnosticCollector<JavaFileObject>();
+ ok = compileCode(clName.toString(), contents, diagnostics);
+
+ String errorKey1 = "compiler.note.deprecated.filename";
+ String errorKey2 = "compiler.note.deprecated.recompile";
+ List<Diagnostic<? extends JavaFileObject>> diags = diagnostics.getDiagnostics();
+
+ //Check for deprecated warnings
+ if (ok) {
+ if (diags.size() == 0) {
+ error("Did not get any warnings for @Deprecated usage");
+ } else {
+ for (Diagnostic<?> d : diags) {
+ if (d.getKind() == Diagnostic.Kind.NOTE) {
+ if (d.getCode().contains(errorKey1)
+ || d.getCode().contains(errorKey2)) {
+ System.out.println("TestCase =" + clName + " passed as expected");
+ } else {
+ error("TestCase =" + clName + " did not give correct warnings" +
+ "Expected warning keys: " +
+ "errorKey1 = " + errorKey1 +
+ "errorKey2 = " + errorKey2 +
+ "actualErrorKey = " + d.getCode(), contents);
+ }
+ } else {
+ error("Diagnostic Kind is incorrect, expected = " +
+ Diagnostic.Kind.NOTE + "actual = " + d.getKind(), contents);
+ }
+ }
+ }
+ } else {
+ error("TestCase =" + clName + " did not compile as expected", contents);
+ }
+ }
+
+ System.out.println("Total number of tests run: " + testCtr);
+ System.out.println("Total number of errors: " + errors);
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ private String getContent(String className) {
+ StringBuilder annoData = new StringBuilder();
+
+ switch(className) {
+ case "DeprecatedonBoth":
+ annoData.append(Helper.ContentVars.DEPRECATED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.DEPRECATED.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ case "DeprecatedonBase":
+ annoData.append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.DEPRECATED.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ case "DeprecatedonContainer":
+ annoData.append(Helper.ContentVars.DEPRECATED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ }
+
+ String contents = Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()
+ + Helper.ContentVars.IMPORTDEPRECATED.getVal()
+ + annoData
+ + Helper.ContentVars.REPEATABLEANNO.getVal()
+ + "\nclass "+ className + "{}";
+ return contents;
+ }
+
+ private void error(String msg, String... contents) {
+ System.out.println("error: " + msg);
+ errors++;
+ if (contents.length == 1) {
+ System.out.println("Contents = " + contents[0]);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8002157
+ * @author sogoel
+ * @summary Positive combo test for use of Documented on baseAnno/containerAnno
+ * @build Helper
+ * @compile DocumentedAnnoCombo.java
+ * @run main DocumentedAnnoCombo
+ */
+
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+
+/*
+ * Generate valid test src for the use of @Documented on container anno
+ * or on both base anno and container anno. Both test src should compile.
+ * Repeating annotations used only on class for these generated test src.
+ */
+public class DocumentedAnnoCombo extends Helper {
+ static int errors = 0;
+
+ enum TestCases {
+ DocumentedonBothAnno(true),
+ DocumentedonContainer(true);
+
+ TestCases(boolean compile) {
+ this.compile = compile;
+ }
+
+ boolean compile;
+ boolean shouldCompile() {
+ return compile;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ new DocumentedAnnoCombo().runTest();
+ }
+
+ public void runTest() throws Exception {
+ boolean ok = false;
+ int testCtr = 0;
+
+ // Create test source content
+ for (TestCases className : TestCases.values()) {
+ testCtr++;
+ String contents = getContent(className.toString());
+
+ // Compile the generated source file
+ DiagnosticCollector<JavaFileObject> diagnostics =
+ new DiagnosticCollector<JavaFileObject>();
+ ok = compileCode(className.toString(), contents, diagnostics);
+ if (!ok) {
+ error("Class="+ className +" did not compile as expected", contents);
+ } else {
+ System.out.println("Test passed for className: " + className);
+ }
+ }
+
+ System.out.println("Total number of tests run: " + testCtr);
+ System.out.println("Total number of errors: " + errors);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ private String getContent(String className) {
+
+ StringBuilder annoData = new StringBuilder();
+ switch(className) {
+ case "DocumentedonBothAnno":
+ annoData.append(Helper.ContentVars.DOCUMENTED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.DOCUMENTED.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ case "DocumentedonContainer":
+ annoData.append(Helper.ContentVars.DOCUMENTED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ }
+
+ String contents = Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()
+ + Helper.ContentVars.IMPORTDOCUMENTED.getVal()
+ + annoData
+ + Helper.ContentVars.REPEATABLEANNO.getVal()
+ + "\nclass "+ className + "{}";
+ return contents;
+ }
+
+ private void error(String msg, String... contents) {
+ System.out.println("error: " + msg);
+ errors++;
+ if (contents.length == 1) {
+ System.out.println("Contents = " + contents[0]);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+import javax.tools.JavaCompiler.CompilationTask;
+
+public class Helper {
+
+ enum ContentVars {
+ IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.ContainedBy;\n" +
+ "\nimport java.lang.annotation.ContainerFor;\n"),
+ IMPORTDEPRECATED("import java.lang.Deprecated;\n"),
+ IMPORTDOCUMENTED("import java.lang.annotation.Documented;\n"),
+ IMPORTINHERITED("import java.lang.annotation.Inherited;\n"),
+ IMPORTRETENTION("import java.lang.annotation.Retention;\n" +
+ "\nimport java.lang.annotation.RetentionPolicy;\n"),
+ CONTAINEDBY("\n@ContainedBy(FooContainer.class)\n"),
+ CONTAINERFOR("@ContainerFor(Foo.class)\n"),
+ CONTAINER("@interface FooContainer {\n" +" Foo[] value();\n}\n"),
+ BASE("@interface Foo {}\n"),
+ REPEATABLEANNO("\n@Foo() @Foo()"),
+ DEPRECATED("\n@Deprecated"),
+ DOCUMENTED("\n@Documented"),
+ INHERITED("\n@Inherited"),
+ RETENTION("@Retention(RetentionPolicy.#VAL)\n");
+
+ private String val;
+
+
+ private ContentVars(String val) {
+ this.val = val;
+ }
+
+ public String getVal() {
+ return val;
+ }
+ }
+
+ /* String template where /*<TYPE>*/ /*gets replaced by repeating anno
+ * Used to generate test src for combo tests
+ * - BasicSyntaxCombo.java
+ * - TargetAnnoCombo.java
+ */
+ public static final String template =
+ "/*PACKAGE*/\n" +
+ "//pkg test;\n\n" +
+ "/*TYPE*/ //class\n" +
+ "class #ClassName {\n" +
+ " /*FIELD*/ //instance var\n" +
+ " public int x = 0;\n\n" +
+ " /*FIELD*/ //Enum constants\n" +
+ " TestEnum testEnum;\n\n" +
+ " /*FIELD*/ // Static field\n" +
+ " public static int num;\n\n" +
+ " /*STATIC_INI*/\n" +
+ " static { \n" + "num = 10; \n }\n\n" +
+ " /*CONSTRUCTOR*/\n" +
+ " #ClassName() {}\n\n" +
+ " /*INSTANCE_INI*/\n" +
+ " { \n x = 10; \n }" +
+ " /*INNER_CLASS*/\n" +
+ " class innerClass {}\n" +
+ " /*METHOD*/\n" +
+ " void bar(/*PARAMETER*/ int baz) {\n" +
+ " /*LOCAL_VARIABLE*/\n" +
+ " int y = 0;\n" +
+ " }\n" +
+ "}\n\n" +
+ "/*TYPE*/ //Enum\n" +
+ "enum TestEnum {}\n\n" +
+ "/*TYPE*/ //Interface\n" +
+ "interface TestInterface {}\n\n" +
+ "/*TYPE*/\n" +
+ "/*ANNOTATION_TYPE*/\n" +
+ "@interface TestAnnotationType{}\n";
+
+ // Create and compile FileObject using values for className and contents
+ public static boolean compileCode(String className, String contents,
+ DiagnosticCollector<JavaFileObject> diagnostics) {
+ boolean ok = false;
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ if (compiler == null) {
+ throw new RuntimeException("can't get javax.tools.JavaCompiler!");
+ }
+
+ JavaFileObject file = getFile(className, contents);
+ Iterable<? extends JavaFileObject> compilationUnit = Arrays.asList(file);
+
+ CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnit);
+ ok = task.call();
+ return ok;
+
+ }
+
+ // Compile a list of FileObjects
+ public static boolean compileCode(DiagnosticCollector<JavaFileObject> diagnostics, Iterable<? extends JavaFileObject> files) {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ if (compiler == null) {
+ throw new RuntimeException("can't get javax.tools.JavaCompiler!");
+ }
+
+ CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, files);
+ boolean ok = task.call();
+ return ok;
+ }
+
+ static JavaFileObject getFile(String name, String code) {
+ JavaFileObject o = null;
+ try {
+ o = new JavaStringFileObject(name, code);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ return o;
+ }
+ static class JavaStringFileObject extends SimpleJavaFileObject {
+ final String theCode;
+ public JavaStringFileObject(String fileName, String theCode) throws URISyntaxException {
+ super(new URI("string:///" + fileName.replace('.','/') + ".java"), Kind.SOURCE);
+ this.theCode = theCode;
+ }
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return theCode;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8002157
+ * @author sogoel
+ * @summary Positive combo test for use of Inherited on baseAnno/containerAnno
+ * @build Helper
+ * @compile InheritedAnnoCombo.java
+ * @run main InheritedAnnoCombo
+ */
+
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+
+/*
+ * Generate valid test src for the use of @Inherited on container anno
+ * or on both base anno and container anno. Both test src should compile.
+ * Repeating annotations used only on class for these generated test src.
+ */
+
+public class InheritedAnnoCombo extends Helper {
+ static int errors = 0;
+ enum TestCases {
+ InheritedonBothAnno(true),
+ InheritedonBase(true);
+
+ TestCases(boolean compile) {
+ this.compile = compile;
+ }
+
+ boolean compile;
+ boolean shouldCompile() {
+ return compile;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ new InheritedAnnoCombo().runTest();
+ }
+
+ public void runTest() throws Exception {
+ int testCtr = 0;
+ boolean ok = false;
+
+ // Create test source content
+ for (TestCases className : TestCases.values()) {
+ testCtr++;
+ String contents = getContent(className.toString());
+
+ // Compile the generated code
+ DiagnosticCollector<JavaFileObject> diagnostics =
+ new DiagnosticCollector<JavaFileObject>();
+ ok = compileCode(className.toString(), contents, diagnostics);
+
+ if (!ok) {
+ error("Class="+ className +" did not compile as expected", contents);
+ } else {
+ System.out.println("Test passed for className: " + className);
+ }
+ }
+
+ System.out.println("Total number of tests run: " + testCtr);
+ System.out.println("Total number of errors: " + errors);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ private String getContent(String className) {
+
+ StringBuilder annoData = new StringBuilder();
+ switch(className) {
+ case "InheritedonBothAnno":
+ annoData.append(Helper.ContentVars.INHERITED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.INHERITED.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ case "InheritedonBase":
+ annoData.append(Helper.ContentVars.INHERITED.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(Helper.ContentVars.BASE.getVal());
+ break;
+ }
+
+ String contents = Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()
+ + Helper.ContentVars.IMPORTINHERITED.getVal()
+ + annoData
+ + Helper.ContentVars.REPEATABLEANNO.getVal()
+ + "\nclass "+ className + "{}";
+ return contents;
+ }
+
+ private void error(String msg, String... contents) {
+ System.out.println("error: " + msg);
+ errors++;
+ if (contents.length == 1) {
+ System.out.println("Contents = " + contents[0]);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8002157
+ * @author sogoel
+ * @summary Combo test for all possible combinations for Retention Values
+ * @build Helper
+ * @compile RetentionAnnoCombo.java
+ * @run main RetentionAnnoCombo
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+import javax.tools.Diagnostic;
+
+/*
+ * Generate all combinations for the use of @Retention on base anno or container
+ * anno or both. The test passes if valid test src compile as expected and
+ * and invalid test src fail as expected.
+ * Repeating annotations used only on class for these generated test src.
+ */
+
+public class RetentionAnnoCombo extends Helper {
+ static int errors = 0;
+ static boolean exitMode = false;
+ static {
+ String exitOnFail = System.getenv("EXIT_ON_FAIL");
+ if (exitOnFail == null || exitOnFail == "" ) {
+ exitMode = false;
+ }
+ else {
+ if (exitOnFail.equalsIgnoreCase("YES") ||
+ exitOnFail.equalsIgnoreCase("Y") ||
+ exitOnFail.equalsIgnoreCase("TRUE") ||
+ exitOnFail.equalsIgnoreCase("T")) {
+ exitMode = true;
+ }
+ }
+ }
+
+ public static void main(String args[]) throws Exception {
+ new RetentionAnnoCombo().runTest();
+ }
+
+ public void runTest() throws Exception {
+
+ /* 4x4 matrix for Retention values SOURCE, DEFAULT, CLASS, RUNTIME
+ * i -> Retention value on ContainerAnno
+ * j -> Retention value on BaseAnno
+ * 1 -> retention value combo should compile
+ */
+ int[][] retention = { {1, 0, 0, 0},
+ {1, 1, 1, 0},
+ {1, 1, 1, 0},
+ {1, 1, 1, 1} };
+
+ Map<Integer, String> retMap = setRetentionValMatrix();
+ String contents = "";
+ boolean result = false;
+ int testCtr = 0;
+ for (int i = 0; i < 4 ; i ++) {
+ for (int j = 0; j < 4; j++ ) {
+ testCtr++;
+ String className = "RetentionTest_"+i+"_"+j;
+ contents = getContent(className, retMap, i, j);
+ if (retention[i][j] == 1) {
+ // Code generated should compile
+ result = getCompileResult(contents,className, true);
+ if (!result) {
+ error("FAIL: " + className + " did not compile as expected!", contents);
+ }
+ } else {
+ result = getCompileResult(contents,className, false);
+ if (!result) {
+ error("FAIL: " + className + " compiled unexpectedly!", contents);
+ }
+ }
+ if (result) {
+ System.out.println("Test passed for className = " + className);
+ }
+ }
+ }
+
+ System.out.println("Total number of tests run: " + testCtr);
+ System.out.println("Total number of errors: " + errors);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ private boolean getCompileResult(String contents, String className,
+ boolean shouldCompile) throws Exception{
+
+ DiagnosticCollector<JavaFileObject> diagnostics =
+ new DiagnosticCollector<JavaFileObject>();
+ boolean ok = compileCode(className, contents, diagnostics);
+
+ String expectedErrKey = "compiler.err.invalid.containedby" +
+ ".annotation.retention";
+ if (!shouldCompile && !ok) {
+ for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
+ if (!((d.getKind() == Diagnostic.Kind.ERROR) &&
+ d.getCode().contains(expectedErrKey))) {
+ error("FAIL: Incorrect error given, expected = "
+ + expectedErrKey + ", Actual = " + d.getCode()
+ + " for className = " + className, contents);
+ }
+ }
+ }
+
+ return (shouldCompile == ok);
+ }
+
+ private Map<Integer,String> setRetentionValMatrix() {
+ HashMap<Integer,String> hm = new HashMap<>();
+ hm.put(0,"SOURCE");
+ hm.put(1,"DEFAULT");
+ hm.put(2,"CLASS");
+ hm.put(3,"RUNTIME");
+ return hm;
+ }
+
+ private String getContent(String className, Map<Integer, String> retMap,
+ int i, int j) {
+
+ String retContainerVal = retMap.get(i).toString();
+ String retBaseVal = retMap.get(j).toString();
+ String replacedRetBaseVal = "", replacedRetCAVal = "";
+ String retention = Helper.ContentVars.RETENTION.getVal();
+
+ // @Retention is available as default for both base and container anno
+ if (retContainerVal.equalsIgnoreCase("DEFAULT")
+ && retBaseVal.equalsIgnoreCase("DEFAULT")) {
+ replacedRetBaseVal = "";
+ replacedRetCAVal = "";
+ // @Retention is available as default for container anno
+ } else if (retContainerVal.equalsIgnoreCase("DEFAULT")) {
+ replacedRetBaseVal = retention.replace("#VAL", retBaseVal);
+ replacedRetCAVal = "";
+ // @Retention is available as default for base anno
+ } else if (retBaseVal.equalsIgnoreCase("DEFAULT")) {
+ replacedRetBaseVal = "";
+ replacedRetCAVal = retention.replace("#VAL", retContainerVal);
+ // @Retention is not available as default for both base and container anno
+ } else {
+ replacedRetBaseVal = retention.replace("#VAL", retBaseVal);
+ replacedRetCAVal = retention.replace("#VAL", retContainerVal);
+ }
+
+ StringBuilder annoData = new StringBuilder();
+ annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal())
+ .append(Helper.ContentVars.IMPORTRETENTION.getVal())
+ .append(Helper.ContentVars.CONTAINERFOR.getVal())
+ .append(replacedRetCAVal)
+ .append(Helper.ContentVars.CONTAINER.getVal())
+ .append(Helper.ContentVars.CONTAINEDBY.getVal())
+ .append(replacedRetBaseVal)
+ .append(Helper.ContentVars.BASE.getVal());
+
+ String contents = annoData
+ + Helper.ContentVars.REPEATABLEANNO.getVal()
+ + "\nclass "+ className + "{}";
+ return contents;
+ }
+
+ private void error(String msg,String... contents) throws Exception {
+ System.out.println("error: " + msg);
+ errors++;
+ if (contents.length == 1) {
+ System.out.println("Contents = " + contents[0]);
+ }
+ // Test exits as soon as it gets a failure
+ if (exitMode) throw new Exception();
+ }
+}
+
--- a/langtools/test/tools/javac/classfiles/ClassVersionChecker.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/classfiles/ClassVersionChecker.java Thu Nov 15 00:54:54 2012 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7157626
+ * @bug 7157626 8001112
* @summary Test major version for all legal combinations for -source and -target
* @author sgoel
*
@@ -57,14 +57,14 @@
* -1 => invalid combinations
*/
int[][] ver =
- {{51, -1, -1, -1, -1, -1, -1, -1},
- {48, 46, 47, 48, 49, 50, 51, 51},
- {48, 46, 47, 48, 49, 50, 51, 51},
- {48, -1, -1, 48, 49, 50, 51, 51},
- {51, -1, -1, -1, 49, 50, 51, 51},
- {51, -1, -1, -1, -1, 50, 51, 51},
- {51, -1, -1, -1, -1, -1, 51, 51},
- {51, -1, -1, -1, -1, -1, -1, 51}};
+ {{52, -1, -1, -1, -1, -1, -1, -1},
+ {48, 46, 47, 48, 49, 50, 51, 52},
+ {48, 46, 47, 48, 49, 50, 51, 52},
+ {48, -1, -1, 48, 49, 50, 51, 52},
+ {52, -1, -1, -1, 49, 50, 51, 52},
+ {52, -1, -1, -1, -1, 50, 51, 52},
+ {52, -1, -1, -1, -1, -1, 51, 52},
+ {52, -1, -1, -1, -1, -1, -1, 52}};
// Loop to run all possible combinations of source/target values
for (int i = 0; i< ver.length; i++) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/ClassReaderTest/ClassReaderTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that default methods don't cause ClassReader to complete classes recursively
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods pkg/Foo.java
+ * @compile ClassReaderTest.java
+ */
+
+abstract class ClassReaderTest implements pkg.Foo {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/ClassReaderTest/pkg/Foo.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+public interface Foo {
+ default void m1() { Impl.m1(this); }
+ default void m2() { Impl.m2(this); }
+}
+
+class Impl {
+ static void m1(Foo f) { }
+ static void m2(Foo f) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg01.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary negative test for ambiguous defaults
+ * @compile/fail/ref=Neg01.out -XDallowDefaultMethods -XDrawDiagnostics Neg01.java
+ */
+
+class Neg01 {
+ interface IA { default int m() { return Neg01.m1(this); } }
+ interface IB { default int m() { return Neg01.m2(this); } }
+
+ static class A implements IA {}
+ static class B implements IB {}
+
+ static class AB implements IA, IB {}
+
+ static int m1(IA a) { return 0; }
+ static int m2(IB b) { return 0; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg01.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg01.java:14:12: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg01.AB, m, , Neg01.IA, Neg01.IB
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg02.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,26 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that ill-formed MI hierarchies do not compile
+ * @compile/fail/ref=Neg02.out -XDallowDefaultMethods -XDrawDiagnostics Neg02.java
+ */
+
+class Neg02 {
+ interface A {
+ default void m() { Neg02.impl(this); }
+ }
+
+ interface B {
+ default void m() { Neg02.impl(this); }
+ }
+
+ static class X implements A, B { } //error
+
+ void test(X x) {
+ x.m();
+ ((A)x).m();
+ ((B)x).m();
+ }
+
+ static void impl(A a) { }
+ static void impl(B b) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg02.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg02.java:16:13: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg02.X, m, , Neg02.A, Neg02.B
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg03.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,38 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that re-abstraction works properly
+ * @compile/fail/ref=Neg03.out -XDallowDefaultMethods -XDrawDiagnostics Neg03.java
+ */
+
+class Neg03 {
+ interface A {
+ default void m() { Neg03.one(this); }
+ }
+
+ interface B {
+ default void m() { Neg03.two(this); }
+ }
+
+ interface C extends A, B {
+ default void m() { Neg03.one(this); }
+ }
+
+ static class X implements C, A { } //ok - ignore extraneous remix of A
+
+ interface D extends A, B {
+ void m(); // ok - m() is not reabstracted!
+ }
+
+ static class Y implements D, A { } // invalid - abstract D.m()
+
+ interface E extends A {
+ void m(); // reabstraction of m()
+ }
+
+ static class W implements D, E { } // invalid - abstracts D.m()/E.m()
+
+ static class Z implements D, A, B { } // invalid - abstract D.m()
+
+ static void one(Object a) { }
+ static void two(Object a) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg03.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,4 @@
+Neg03.java:26:12: compiler.err.does.not.override.abstract: Neg03.Y, m(), Neg03.D
+Neg03.java:32:12: compiler.err.does.not.override.abstract: Neg03.W, m(), Neg03.D
+Neg03.java:34:12: compiler.err.does.not.override.abstract: Neg03.Z, m(), Neg03.D
+3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg04.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default method must have most specific return type
+ * @compile/fail/ref=Neg04.out -XDallowDefaultMethods -XDrawDiagnostics Neg04.java
+ */
+
+class Neg04 {
+ interface IA1 { Integer m(); }
+ interface IA2 extends IA1 { default Number m() { return Neg04.m(this); } } //error
+
+ abstract class C implements IA1, IA2 {}
+
+ static int m(IA2 a) { return 0; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg04.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg04.java:9:48: compiler.err.override.incompatible.ret: (compiler.misc.clashes.with: m(), Neg04.IA2, m(), Neg04.IA1), java.lang.Number, java.lang.Integer
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg05.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that abstract methods are compatible with inherited defaults
+ * @compile/fail/ref=Neg05.out -XDallowDefaultMethods -XDrawDiagnostics Neg05.java
+ */
+
+class Neg05 {
+ interface IA1 { default Number m() { return Neg05.m1(this); } }
+ interface IA2 extends IA1 { default Integer m() { return Neg05.m2(this); } }
+ interface IA3 extends IA2 { Number m(); } //error
+
+ static class C implements IA3{}
+
+ static int m1(IA1 a) { return 0; }
+ static int m2(IA2 b) { return 0; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg05.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,3 @@
+Neg05.java:10:40: compiler.err.override.incompatible.ret: (compiler.misc.clashes.with: m(), Neg05.IA3, m(), Neg05.IA2), java.lang.Number, java.lang.Integer
+Neg05.java:12:12: compiler.err.does.not.override.abstract: Neg05.C, m(), Neg05.IA3
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg06.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary flow analysis is not run on inlined default bodies
+ * @compile/fail/ref=Neg06.out -XDallowDefaultMethods -XDrawDiagnostics Neg06.java
+ */
+
+class Neg06 {
+
+ interface A {
+ default String m() { C.m(); }
+ }
+
+ static class C {
+ static String m() { return ""; }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg06.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg06.java:10:37: compiler.err.missing.ret.stmt
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg07.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default overrides are properly type-checked
+ * @compile/fail/ref=Neg07.out -XDallowDefaultMethods -XDrawDiagnostics Neg07.java
+ */
+
+class Neg07 {
+ interface I {
+ default int m() { return 1; }
+ }
+
+ static class C1 {
+ public void m() { } //incompatible return
+ }
+
+ static class C2 extends C1 implements I { }
+
+ static class C3 implements I {
+ public void m() { } //incompatible return
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg07.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,3 @@
+Neg07.java:16:12: compiler.err.override.incompatible.ret: (compiler.misc.cant.implement: m(), Neg07.C1, m(), Neg07.I), void, int
+Neg07.java:19:21: compiler.err.override.incompatible.ret: (compiler.misc.cant.implement: m(), Neg07.C3, m(), Neg07.I), void, int
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg08.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default overrides are properly type-checked
+ * @compile/fail/ref=Neg08.out -XDallowDefaultMethods -XDrawDiagnostics Neg08.java
+ */
+class Neg08 {
+ interface I {
+ default void m() { }
+ }
+
+ static class C1 {
+ void m() { } //weaker modifier
+ }
+
+ static class C2 extends C1 implements I { }
+
+ static class C3 implements I {
+ void m() { } //weaker modifier
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg08.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,3 @@
+Neg08.java:15:12: compiler.err.override.weaker.access: (compiler.misc.cant.implement: m(), Neg08.C1, m(), Neg08.I), public
+Neg08.java:18:14: compiler.err.override.weaker.access: (compiler.misc.cant.implement: m(), Neg08.C3, m(), Neg08.I), public
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg09.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default overrides are properly type-checked
+ * @compile/fail/ref=Neg09.out -Werror -Xlint:unchecked -XDallowDefaultMethods -XDrawDiagnostics Neg09.java
+ */
+import java.util.List;
+
+class Neg09 {
+ interface I {
+ default List<String> m() { return null; }
+ }
+
+ static class C1 {
+ public List m() { return null; } //unchecked (return) override
+ }
+
+ static class C2 extends C1 implements I { }
+
+ static class C3 implements I {
+ public List m() { return null; } //unchecked (return) override
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg09.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,5 @@
+Neg09.java:17:12: compiler.warn.override.unchecked.ret: (compiler.misc.unchecked.implement: m(), Neg09.C1, m(), Neg09.I), java.util.List, java.util.List<java.lang.String>
+Neg09.java:20:21: compiler.warn.override.unchecked.ret: (compiler.misc.unchecked.implement: m(), Neg09.C3, m(), Neg09.I), java.util.List, java.util.List<java.lang.String>
+- compiler.err.warnings.and.werror
+1 error
+2 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg10.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default overrides are properly type-checked
+ * @compile/fail/ref=Neg10.out -Werror -Xlint:unchecked -XDallowDefaultMethods -XDrawDiagnostics Neg10.java
+ */
+class Neg10 {
+ interface I<X extends Exception> {
+ default void m() throws X { }
+ }
+
+ static class C1 {
+ public void m() throws Exception { } //unchecked (throws) override
+ }
+
+ static class C2<Z extends Exception> extends C1 implements I<Z> { }
+
+ static class C3<Z extends Exception> implements I<Z> {
+ public void m() throws Exception { } //unchecked (throws) override
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg10.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,5 @@
+Neg10.java:15:12: compiler.warn.override.unchecked.thrown: (compiler.misc.cant.implement: m(), Neg10.C1, m(), Neg10.I), java.lang.Exception
+Neg10.java:18:21: compiler.warn.override.unchecked.thrown: (compiler.misc.cant.implement: m(), Neg10.C3, m(), Neg10.I), java.lang.Exception
+- compiler.err.warnings.and.werror
+1 error
+2 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg11.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default overrides are properly type-checked
+ * @compile/fail/ref=Neg11.out -XDallowDefaultMethods -XDrawDiagnostics Neg11.java
+ */
+class Neg11 {
+ interface I {
+ default void m() { }
+ }
+
+ static class C1 {
+ public void m() throws Exception { } //bad throws
+ }
+
+ static class C2 extends C1 implements I { }
+
+ static class C3 implements I {
+ public void m() throws Exception { } //bad throws
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg11.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,3 @@
+Neg11.java:15:12: compiler.err.override.meth.doesnt.throw: (compiler.misc.cant.implement: m(), Neg11.C1, m(), Neg11.I), java.lang.Exception
+Neg11.java:18:21: compiler.err.override.meth.doesnt.throw: (compiler.misc.cant.implement: m(), Neg11.C3, m(), Neg11.I), java.lang.Exception
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg12.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that abstract methods are discarded in overload resolution diags
+ * @compile/fail/ref=Neg12.out -XDallowDefaultMethods -XDrawDiagnostics Neg12.java
+ */
+class Neg12 {
+
+ interface I1 {
+ default void m(String s) {};
+ }
+
+ interface I2 {
+ void m(String s);
+ }
+
+ static class B {
+ void m(Integer i) { }
+ }
+
+ static class C extends B implements I1 { }
+ static class D extends B implements I2 { }
+
+ void test(C c, D d) {
+ c.m();
+ d.m();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg12.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,4 @@
+Neg12.java:21:12: compiler.err.does.not.override.abstract: Neg12.D, m(java.lang.String), Neg12.I2
+Neg12.java:24:10: compiler.err.cant.apply.symbols: kindname.method, m, ,{(compiler.misc.inapplicable.method: kindname.method, Neg12.I1, m(java.lang.String), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, Neg12.B, m(java.lang.Integer), (compiler.misc.arg.length.mismatch))}
+Neg12.java:25:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Integer, compiler.misc.no.args, kindname.class, Neg12.B, (compiler.misc.arg.length.mismatch)
+3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg13.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that default method overriding object members are flagged as error
+ * @compile/fail/ref=Neg13.out -XDallowDefaultMethods -XDrawDiagnostics Neg13.java
+ */
+interface Neg13 {
+ default protected Object clone() { return null; } //protected not allowed here
+ default boolean equals(Object obj) { return false; }
+ default protected void finalize() { } //protected not allowed here
+ default Class<?> getClass() { return null; }
+ default int hashCode() { return 0; }
+ default void notify() { }
+ default void notifyAll() { }
+ default String toString() { return null; }
+ default void wait() { }
+ default void wait(long timeout) { }
+ default void wait(long timeout, int nanos) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg13.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,12 @@
+Neg13.java:7:30: compiler.err.mod.not.allowed.here: protected
+Neg13.java:9:28: compiler.err.mod.not.allowed.here: protected
+Neg13.java:8:21: compiler.err.default.overrides.object.member: equals, kindname.interface, Neg13
+Neg13.java:10:22: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), Neg13, getClass(), java.lang.Object), final
+Neg13.java:11:17: compiler.err.default.overrides.object.member: hashCode, kindname.interface, Neg13
+Neg13.java:12:18: compiler.err.override.meth: (compiler.misc.cant.override: notify(), Neg13, notify(), java.lang.Object), final
+Neg13.java:13:18: compiler.err.override.meth: (compiler.misc.cant.override: notifyAll(), Neg13, notifyAll(), java.lang.Object), final
+Neg13.java:14:20: compiler.err.default.overrides.object.member: toString, kindname.interface, Neg13
+Neg13.java:15:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(), Neg13, wait(), java.lang.Object), final
+Neg13.java:16:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(long), Neg13, wait(long), java.lang.Object), final
+Neg13.java:17:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(long,int), Neg13, wait(long,int), java.lang.Object), final
+11 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg14.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,11 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that a class cannot have two sibling interfaces with a default and abstract method
+ * @compile/fail/ref=Neg14.out -XDallowDefaultMethods -XDrawDiagnostics Neg14.java
+ */
+class Neg14 {
+ interface IA { int m(); }
+ interface IB { default int m() { return 1; } }
+
+ abstract class AB implements IA, IB {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg14.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg14.java:10:14: compiler.err.types.incompatible.abstract.default: kindname.class, Neg14.AB, m, , Neg14.IB, Neg14.IA
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg15.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that level skipping in default super calls is correctly rejected
+ * @compile/fail/ref=Neg15.out -XDallowDefaultMethods -XDrawDiagnostics Neg15.java
+ */
+class Neg15 {
+ interface I { default void m() { } }
+ interface J extends I { default void m() { } }
+ interface K extends I {}
+
+ static class C implements J, K {
+ void foo() { K.super.m(); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg15.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg15.java:12:31: compiler.err.illegal.default.super.call: Neg15.K, (compiler.misc.overridden.default: m(), Neg15.J)
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg16.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that level skipping in default super calls is correctly rejected
+ * @compile/fail/ref=Neg16.out -XDallowDefaultMethods -XDrawDiagnostics Neg16.java
+ */
+class Neg16 {
+ interface I { default void m() { } }
+ interface J extends I { default void m() { } }
+
+ static class C implements I, J {
+ void foo() { I.super.m(); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Neg16.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,2 @@
+Neg16.java:11:23: compiler.err.illegal.default.super.call: Neg16.I, (compiler.misc.redundant.supertype: Neg16.I, Neg16.J)
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos01.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary basic test for default methods
+ * @ignore awaits lambda support
+ * @author Maurizio Cimadamore
+ * @compile -XDallowLambda -XDallowPoly -XDallowDefaultMethods Pos01.java
+ */
+
+import java.util.*;
+
+class Pos01 {
+
+ interface Mapper<T> {
+ T map(T in);
+ }
+
+ interface ExtendedList<T> extends List<T> {
+ default List<T> testMap(Mapper<T> r) {
+ return Pos01.<T>listMapper(this, r);
+ }
+ }
+
+ static class MyList<E> extends ArrayList<E> implements ExtendedList<E> {}
+
+ public static void main(String[] args) {
+ MyList<Integer> l = new MyList<Integer>();
+ l.add(1); l.add(2); l.add(3);
+ l.testMap((Integer x) -> x * x );
+ }
+
+ static <T> List<T> listMapper(List<T> l, Mapper<T> mapper) {
+ MyList<T> new_list = new MyList<T>();
+ for (T el : l) {
+ new_list.add(mapper.map(el));
+ }
+ return new_list;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos02.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary test for explicit resolution of ambiguous default methods
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos02.java
+ */
+
+class Pos02 {
+ interface IA { default int m() { return Pos02.m1(this); } }
+ interface IB { default int m() { return Pos02.m2(this); } }
+
+ static class A implements IA {}
+ static class B implements IB {}
+
+ static class AB implements IA, IB {
+ public int m() { return 0; }
+ void test() {
+ AB.this.m();
+ IA.super.m();
+ }
+ }
+
+ static int m1(IA a) { return 0; }
+ static int m2(IB b) { return 0; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos04.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary test for overriding with default method
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos04.java
+ */
+
+class Pos04 {
+ interface A { default int m() { return Pos04.m(this); } }
+ static abstract class B { public int m() { return 0; } }
+
+ static class C extends B implements A {
+ void test() {
+ C.this.m();
+ A.super.m();
+ }
+ }
+
+ static int m(A a) { return 0; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos05.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that indirectly inherited default methods are discovered during resolution
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos05.java
+ */
+
+class Pos05 {
+ interface A {
+ default void m() { Pos05.impl(this); }
+ }
+
+ interface B extends A { }
+
+ static class E implements B { }
+
+ void test(E e) {
+ e.m();
+ }
+
+ static void impl(A a) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos06.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that well-formed MI hierarchies behaves well w.r.t. method resolution (i.e. no ambiguities)
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos06.java
+ */
+
+class Pos06 {
+ interface A {
+ default void m() { Pos06.impl(this); }
+ }
+
+ interface B extends A {
+ default void m() { Pos06.impl(this); }
+ }
+
+ static class X implements A, B { }
+
+ void test(X x) {
+ x.m();
+ ((A)x).m();
+ ((B)x).m();
+ }
+
+ static void impl(Object a) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos07.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that compilation order does not matter
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos07.java
+ */
+
+class Pos07 {
+ interface A {
+ default void foo() { Pos07.impl(this); }
+ default void bar() { Pos07.impl(this); }
+ }
+
+ static class C implements B, A {}
+
+ interface B extends A {
+ default void foo() { Pos07.impl(this); }
+ }
+
+ static void impl(A a) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos08.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that common overrider solves default method conflicts
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos08.java
+ */
+
+class Pos08 {
+ interface A {
+ default void m() { Pos08.a(this); }
+ }
+
+ interface B {
+ default void m() { Pos08.b(this); }
+ }
+
+ interface C extends A, B {
+ default void m() { Pos08.b(this); }
+ }
+
+ static void a(A o) { }
+ static void b(B o) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos10.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that type-variables in generic extension decl can be accessed from default impl
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods Pos10.java
+ */
+
+class Pos10 {
+ interface Function<X,Y> {
+ Y apply(X x);
+ }
+
+ interface A<T> {
+ default <R> void m(Function<T,R> f) { Impl.<T,R>m(this, f); }
+ }
+
+ static class Impl {
+ static <T,R> void m(A<T> a, Function<T,R> f) { }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos11.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary complex test with conflict resolution via overriding
+ * @author Brian Goetz
+ * @compile -XDallowDefaultMethods Pos11.java
+ */
+
+class Pos11 {
+ interface A {
+ default void get() { Pos11.one(this); }
+ }
+
+ interface B {
+ default void get() { Pos11.two(this); }
+ }
+
+ interface C extends A {
+ default void get() { Pos11.two(this); }
+ }
+
+ interface D extends A, B {
+ default void get() { Pos11.two(this); }
+ }
+
+ static class X implements C { }
+
+ static class Y implements C, A { }
+
+ static class Z implements D, A, B { }
+
+ static void one(Object a) { }
+ static void two(Object a) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos12.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that 'this' can be used from within an extension method
+ * @compile -XDallowDefaultMethods Pos12.java
+ */
+
+interface Pos12 {
+
+ default Object m() {
+ Object o = this;
+ f(this);
+ return this;
+ }
+
+ void f(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos13.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary qualified 'this' inside default method causes StackOverflowException
+ * @compile -XDallowDefaultMethods Pos13.java
+ */
+
+public class Pos13 {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ interface Outer {
+ abstract void doSomething();
+
+ default void m() {
+ new SubOuter() {
+ public void doSomething() {
+ Outer.this.doSomething();
+ }
+ }.doSomething();
+ }
+ }
+
+ interface SubOuter extends Outer { }
+
+ static class E implements Outer {
+ public void doSomething() { assertTrue(true); }
+ }
+
+ public static void main(String[] args) {
+ new E().m();
+ assertTrue(assertionCount == 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos14.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that overload resolution selects most specific signature
+ * @compile -XDallowDefaultMethods Pos14.java
+ */
+
+class Pos14 {
+ interface A { default Object m() { return null; } }
+ static abstract class B { abstract public String m(); }
+
+ static abstract class C extends B implements A {
+ void test() {
+ m().length();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos15.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that overload resolution selects most specific signature
+ * @compile -XDallowDefaultMethods Pos15.java
+ */
+
+class Pos15 {
+ interface A { default String m() { return null; } }
+ static abstract class B { abstract public Object m(); }
+
+ static abstract class C extends B implements A {
+ void test() {
+ m().length();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/Pos16.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary 'class wins' should not short-circuit overload resolution
+ * @compile -XDallowDefaultMethods Pos16.java
+ */
+
+class Pos16 {
+ interface I {
+ default String m(Integer i) { return ""; }
+ }
+
+ class C implements I {
+ Integer m(Object o) { return 1; }
+ }
+
+ void test(C c) {
+ c.m(1).length();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/TestDefaultBody.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @ignore awaits for VM support
+ * @summary check that code attributed for default methods is correctly generated
+ * @compile -XDallowDefaultMethods TestDefaultBody.java
+ * @run main TestDefaultBody
+ */
+
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.Instruction;
+import com.sun.tools.classfile.Method;
+
+import com.sun.tools.classfile.Opcode;
+import java.io.*;
+
+public class TestDefaultBody {
+
+ interface TestInterface {
+ int no_default(int i);
+ default int yes_default(int i) { return impl(this, i); }
+ }
+
+ static int impl(TestInterface ti, int i) { return 0; }
+
+ static final String TARGET_CLASS_NAME = "TestDefaultBody";
+ static final String TARGET_NAME = "impl";
+ static final String TARGET_TYPE = "(LTestDefaultBody$TestInterface;I)I";
+ static final String SUBTEST_NAME = TestInterface.class.getName() + ".class";
+ static final String TEST_METHOD_NAME = "yes_default";
+
+ public static void main(String... args) throws Exception {
+ new TestDefaultBody().run();
+ }
+
+ public void run() throws Exception {
+ String workDir = System.getProperty("test.classes");
+ File compiledTest = new File(workDir, SUBTEST_NAME);
+ verifyDefaultBody(compiledTest);
+ }
+
+ void verifyDefaultBody(File f) {
+ System.err.println("verify: " + f);
+ try {
+ ClassFile cf = ClassFile.read(f);
+ Method testMethod = null;
+ Code_attribute codeAttr = null;
+ for (Method m : cf.methods) {
+ codeAttr = (Code_attribute)m.attributes.get(Attribute.Code);
+ String mname = m.getName(cf.constant_pool);
+ if (mname.equals(TEST_METHOD_NAME)) {
+ testMethod = m;
+ break;
+ } else {
+ codeAttr = null;
+ }
+ }
+ if (testMethod == null) {
+ throw new Error("Test method not found");
+ }
+ if (testMethod.access_flags.is(AccessFlags.ACC_ABSTRACT)) {
+ throw new Error("Test method is abstract");
+ }
+ if (codeAttr == null) {
+ throw new Error("Code attribute in test method not found");
+ }
+
+ boolean found = false;
+ for (Instruction instr : codeAttr.getInstructions()) {
+ if (instr.getOpcode() == Opcode.INVOKESTATIC) {
+ found = true;
+ int pc_index = instr.getShort(1);
+ CONSTANT_Methodref_info mref = (CONSTANT_Methodref_info)cf.constant_pool.get(pc_index);
+ String className = mref.getClassName();
+ String targetName = mref.getNameAndTypeInfo().getName();
+ String targetType = mref.getNameAndTypeInfo().getType();
+
+ if (!className.equals(TARGET_CLASS_NAME)) {
+ throw new Error("unexpected class in default method body " + className);
+ }
+ if (!targetName.equals(TARGET_NAME)) {
+ throw new Error("unexpected method name in default method body " + targetName);
+ }
+ if (!targetType.equals(TARGET_TYPE)) {
+ throw new Error("unexpected method type in default method body " + targetType);
+ }
+ break;
+ }
+ }
+
+ if (!found) {
+ throw new Error("no invokestatic found in default method body");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("error reading " + f +": " + e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @ignore awaits for VM support
+ * @summary check that javac does not generate bridge methods for defaults
+ * @compile -XDallowDefaultMethods TestNoBridgeOnDefaults.java
+ * @run main TestNoBridgeOnDefaults
+ */
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Method;
+
+import java.io.*;
+
+public class TestNoBridgeOnDefaults {
+
+ interface A<X> {
+ default <Y> A<X> m(X x, Y y) { return Impl.<X,Y>m1(this, x, y); }
+ }
+
+ static abstract class B<X> implements A<X> { }
+
+ interface C<X> extends A<X> {
+ default <Y> C<X> m(X x, Y y) { return Impl.<X,Y>m2(this, x, y); }
+ }
+
+ static abstract class D<X> extends B<X> implements C<X> { }
+
+ static class Impl {
+ static <X, Y> A<X> m1(A<X> rec, X x, Y y) { return null; }
+ static <X, Y> C<X> m2(C<X> rec, X x, Y y) { return null; }
+ }
+
+ static final String[] SUBTEST_NAMES = { B.class.getName() + ".class", D.class.getName() + ".class" };
+ static final String TEST_METHOD_NAME = "m";
+
+ public static void main(String... args) throws Exception {
+ new TestNoBridgeOnDefaults().run();
+ }
+
+ public void run() throws Exception {
+ String workDir = System.getProperty("test.classes");
+ for (int i = 0 ; i < SUBTEST_NAMES.length ; i ++) {
+ File compiledTest = new File(workDir, SUBTEST_NAMES[i]);
+ checkNoBridgeOnDefaults(compiledTest);
+ }
+ }
+
+ void checkNoBridgeOnDefaults(File f) {
+ System.err.println("check: " + f);
+ try {
+ ClassFile cf = ClassFile.read(f);
+ for (Method m : cf.methods) {
+ String mname = m.getName(cf.constant_pool);
+ if (mname.equals(TEST_METHOD_NAME)) {
+ throw new Error("unexpected bridge method found " + m);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("error reading " + f +": " + e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/crossCompile/Clinit.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+interface Clinit {
+ String s = Inner.m();
+
+ static class Inner {
+ static String m() { return ""; }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/crossCompile/CrossCompile.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary check that clinit in interface doesn't cause spurious default method diagnostics
+ * @compile -source 1.4 -target 1.4 Clinit.java
+ * @compile CrossCompile.java
+ */
+class CrossCompile {
+ void test() {
+ String s = Clinit.s;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/FDTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Automatic test for checking correctness of default resolution
+ */
+
+import shapegen.*;
+
+import com.sun.source.util.JavacTask;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+public class FDTest {
+
+ enum TestKind {
+ POSITIVE,
+ NEGATIVE;
+
+ Collection<Hierarchy> getHierarchy(HierarchyGenerator hg) {
+ return this == POSITIVE ?
+ hg.getOK() : hg.getErr();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ //create default shared JavaCompiler - reused across multiple compilations
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ HierarchyGenerator hg = new HierarchyGenerator();
+ for (TestKind tk : TestKind.values()) {
+ for (Hierarchy hs : tk.getHierarchy(hg)) {
+ new FDTest(tk, hs).run(comp, fm);
+ }
+ }
+ }
+
+ TestKind tk;
+ Hierarchy hs;
+ DefenderTestSource source;
+ DiagnosticChecker diagChecker;
+
+ FDTest(TestKind tk, Hierarchy hs) {
+ this.tk = tk;
+ this.hs = hs;
+ this.source = new DefenderTestSource();
+ this.diagChecker = new DiagnosticChecker();
+ }
+
+ void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
+ JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+ Arrays.asList("-XDallowDefaultMethods"), null, Arrays.asList(source));
+ try {
+ ct.analyze();
+ } catch (Throwable ex) {
+ throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
+ }
+ check();
+ }
+
+ void check() {
+ boolean errorExpected = tk == TestKind.NEGATIVE;
+ if (errorExpected != diagChecker.errorFound) {
+ throw new AssertionError("problem in source: \n" +
+ "\nerror found = " + diagChecker.errorFound +
+ "\nerror expected = " + errorExpected +
+ "\n" + dumpHierarchy() +
+ "\n" + source.getCharContent(true));
+ }
+ }
+
+ String dumpHierarchy() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("root = " + hs.root + "\n");
+ for (ClassCase cc : hs.all) {
+ buf.append(" class name = " + cc.getName() + "\n");
+ buf.append(" class OK = " + cc.get_OK() + "\n");
+ buf.append(" prov = " + cc.get_mprov() + "\n");
+
+ }
+ return buf.toString();
+ }
+
+ class DefenderTestSource extends SimpleJavaFileObject {
+
+ String source;
+
+ public DefenderTestSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ StringBuilder buf = new StringBuilder();
+ List<ClassCase> defaultRef = new ArrayList<>();
+ for (ClassCase cc : hs.all) {
+ hs.genClassDef(buf, cc, null, defaultRef);
+ }
+ source = buf.toString();
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+ static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+ boolean errorFound;
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+ errorFound = true;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/ClassCase.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author Robert Field
+ */
+public class ClassCase {
+
+ public enum Kind {
+ IVAC (true, "v"),
+ IPRESENT (true, "p"),
+ IDEFAULT (true, "d"),
+ CNONE (false, "n"),
+ CABSTRACT (false, "a"),
+ CCONCRETE (false, "c");
+
+ private final String prefix;
+ public final boolean isInterface;
+
+ Kind(boolean isInterface, String prefix) {
+ this.isInterface = isInterface;
+ this.prefix = prefix;
+ }
+ }
+
+ public final Kind kind;
+ private final ClassCase superclass;
+ private final List<ClassCase> supertypes;
+
+ private String name;
+ private boolean _OK;
+ private boolean _HasClassMethod;
+ private Set<ClassCase> _mprov;
+ private boolean _IsConcrete;
+ private boolean _HasDefault;
+ private ClassCase _mres;
+ private ClassCase _mdefend;
+
+ private Set<RuleGroup> executed = new HashSet<RuleGroup>() {};
+
+ public ClassCase(Kind kind, ClassCase superclass, List<ClassCase> interfaces) {
+ this.kind = kind;
+ this.superclass = superclass;
+
+ // Set supertypes from superclass (if any) and interfaces
+ List<ClassCase> lc;
+ if (superclass == null) {
+ lc = interfaces;
+ } else {
+ lc = new ArrayList<>();
+ lc.add(superclass);
+ lc.addAll(interfaces);
+ }
+ this.supertypes = lc;
+ }
+
+ public final boolean isInterface() { return kind.isInterface; }
+ public final boolean isClass() { return !kind.isInterface; }
+
+ public Set<ClassCase> get_mprov() {
+ exec(RuleGroup.PROVENENCE);
+ return _mprov;
+ }
+
+ public void set_mprov(ClassCase cc) {
+ Set<ClassCase> s = new HashSet<>();
+ s.add(cc);
+ _mprov = s;
+ }
+
+ public void set_mprov(Set<ClassCase> s) {
+ _mprov = s;
+ }
+
+ public ClassCase get_mres() {
+ exec(RuleGroup.RESOLUTION);
+ return _mres;
+ }
+
+ public void set_mres(ClassCase cc) {
+ _mres = cc;
+ }
+
+ public ClassCase get_mdefend() {
+ exec(RuleGroup.DEFENDER);
+ return _mdefend;
+ }
+
+ public void set_mdefend(ClassCase cc) {
+ _mdefend = cc;
+ }
+
+ public boolean get_HasClassMethod() {
+ exec(RuleGroup.PROVENENCE);
+ return _HasClassMethod;
+ }
+
+ public void set_HasClassMethod(boolean bool) {
+ _HasClassMethod = bool;
+ }
+
+ public boolean get_HasDefault() {
+ exec(RuleGroup.MARKER);
+ return _HasDefault;
+ }
+
+ public void set_HasDefault(boolean bool) {
+ _HasDefault = bool;
+ }
+
+ public boolean get_IsConcrete() {
+ exec(RuleGroup.MARKER);
+ return _IsConcrete;
+ }
+
+ public void set_IsConcrete(boolean bool) {
+ _IsConcrete = bool;
+ }
+
+ public boolean get_OK() {
+ exec(RuleGroup.CHECKING);
+ return _OK;
+ }
+
+ public void set_OK(boolean bool) {
+ _OK = bool;
+ }
+
+ public boolean isMethodDefined() {
+ for (ClassCase cc : supertypes) {
+ if (cc.isMethodDefined()) {
+ return true;
+ }
+ }
+ switch (kind) {
+ case CCONCRETE:
+ case CABSTRACT:
+ case IPRESENT:
+ case IDEFAULT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean isAbstract() {
+ return isMethodDefined() && (get_mres()==null);
+ }
+
+ public boolean hasSuperclass() {
+ return superclass != null;
+ }
+
+ public ClassCase getSuperclass() {
+ return superclass;
+ }
+
+ public List<ClassCase> getSupertypes() {
+ return supertypes;
+ }
+
+ public List<ClassCase> getInterfaces() {
+ if (superclass != null) {
+ if (supertypes.get(0) != superclass) {
+ throw new AssertionError("superclass missing from supertypes");
+ }
+ return supertypes.subList(1, supertypes.size());
+ } else {
+ return supertypes;
+ }
+ }
+
+ public boolean isSubtypeOf(ClassCase cc) {
+ // S-Refl
+ if (cc.equals(this)) {
+ return true;
+ }
+
+ // S-Def
+ for (ClassCase sp : getSupertypes()) {
+ if (cc.equals(sp)) {
+ return true;
+ }
+ }
+
+ // _S-Trans
+ for (ClassCase sp : getSupertypes()) {
+ if (sp.isSubtypeOf(cc)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void init(Map<String, Integer> namingContext) {
+ if (name != null) {
+ return; // Already inited
+ }
+
+ for (ClassCase sup : supertypes) {
+ sup.init(namingContext);
+ }
+
+ // Build name
+ StringBuilder sb = new StringBuilder();
+ if (!supertypes.isEmpty()) {
+ sb.append(isInterface() ? "I" : "C");
+ for (ClassCase cc : supertypes) {
+ sb.append(cc.getName());
+ }
+ sb.append(kind.isInterface ? "i" : "c");
+ }
+ sb.append(kind.prefix);
+ String pname = sb.toString();
+ Integer icnt = namingContext.get(pname);
+ int cnt = icnt == null ? 0 : icnt;
+ ++cnt;
+ namingContext.put(pname, cnt);
+ if (cnt > 1) {
+ sb.append(cnt);
+ }
+ this.name = sb.toString();
+ }
+
+ public boolean isa(Kind... kinds) {
+ for (Kind k : kinds) {
+ if (kind == k) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void exec(RuleGroup rg ) {
+ if (!executed.contains(rg)) {
+ rg.exec(this);
+ executed.add(rg);
+ }
+ }
+
+ public void collectClasses(Set<ClassCase> seen) {
+ seen.add(this);
+ for (ClassCase cc : supertypes) {
+ cc.collectClasses(seen);
+ }
+ }
+
+ public String getID() {
+ if (name == null) {
+ throw new Error("Access to uninitialized ClassCase");
+ } else {
+ return name;
+ }
+ }
+
+ public final String getName() {
+ if (name == null) {
+ return "ClassCase uninited@" + hashCode();
+ } else {
+ return name;
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID());
+ }
+
+ @Override
+ public int hashCode() {
+ return getID().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/Hierarchy.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import static shapegen.ClassCase.Kind.*;
+
+/**
+ *
+ * @author Robert Field
+ */
+public class Hierarchy {
+
+ public final ClassCase root;
+ public final Set<ClassCase> all;
+
+ public Hierarchy(ClassCase root) {
+ this.root = root;
+ root.init(new HashMap<String,Integer>());
+ Set<ClassCase> allClasses = new HashSet<>();
+ root.collectClasses(allClasses);
+ this.all = allClasses;
+ }
+
+ public boolean anyDefaults() {
+ for (ClassCase cc : all) {
+ if (cc.kind == IDEFAULT) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean get_OK() {
+ return root.get_OK();
+ }
+
+ public String testName() {
+ return root + "Test";
+ }
+
+ private static void genInterfaceList(StringBuilder buf, String prefix, List<ClassCase> interfaces) {
+ if (!interfaces.isEmpty()) {
+ buf.append(" ");
+ buf.append(prefix);
+ buf.append(" ");
+ buf.append(interfaces.get(0));
+ for (int i = 1; i < interfaces.size(); ++i) {
+ buf.append(", " + interfaces.get(i));
+ }
+ }
+ }
+
+ public static void genClassDef(StringBuilder buf, ClassCase cc, String implClass, List<ClassCase> defaultRef) {
+ if (cc.isInterface()) {
+ buf.append("interface ");
+ buf.append(cc.getName() + " ");
+ genInterfaceList(buf, "extends", cc.getInterfaces());
+ buf.append(" {\n");
+
+ switch (cc.kind) {
+ case IDEFAULT:
+ buf.append(" default String m() { return \"\"; }\n");
+ defaultRef.add(cc);
+ break;
+ case IPRESENT:
+ buf.append(" String m();\n");
+ break;
+ case IVAC:
+ break;
+ default:
+ throw new AssertionError("Unexpected kind");
+ }
+ buf.append("}\n\n");
+ } else {
+ buf.append((cc.isAbstract()? "abstract " : ""));
+ buf.append(" class " + cc.getName());
+ if (cc.getSuperclass() != null) {
+ buf.append(" extends " + cc.getSuperclass());
+ }
+
+ genInterfaceList(buf, "implements", cc.getInterfaces());
+ buf.append(" {\n");
+
+ switch (cc.kind) {
+ case CCONCRETE:
+ buf.append(" public String m() { return \"\"; }\n");
+ break;
+ case CABSTRACT:
+ buf.append(" public abstract String m();\n");
+ break;
+ case CNONE:
+ break;
+ default:
+ throw new AssertionError("Unexpected kind");
+ }
+ buf.append("}\n\n");
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Hierarchy && root.getID().equals(((Hierarchy)obj).root.getID());
+ }
+
+ @Override
+ public int hashCode() {
+ return root.getID().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return root.getName();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/HierarchyGenerator.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import shapegen.ClassCase.Kind;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.ArrayList;
+import java.util.List;
+
+import static shapegen.ClassCase.Kind.*;
+
+import static java.lang.Math.pow;
+
+/**
+ *
+ * @author Robert Field
+ */
+public final class HierarchyGenerator {
+
+ private static int okcnt = 0;
+ private static int errcnt = 0;
+ private static Set<Hierarchy> uniqueOK = new HashSet<>();
+ private static Set<Hierarchy> uniqueErr = new HashSet<>();
+
+ /**
+ * @param args the command line arguments
+ */
+ public HierarchyGenerator() {
+ organize("exhaustive interface", iExhaustive(2));
+ organize("exhaustive class", cExhaustive());
+ organize("shapes interface", iShapes());
+ organize("shapes class/interface", ciShapes());
+
+ System.out.printf("\nExpect OK: %d -- unique %d", okcnt, uniqueOK.size());
+ System.out.printf("\nExpect Error: %d -- unique %d\n", errcnt, uniqueErr.size());
+ }
+
+ public Collection<Hierarchy> getOK() {
+ return uniqueOK;
+ }
+
+ public Collection<Hierarchy> getErr() {
+ return uniqueErr;
+ }
+
+ private void organize(String tname, List<Hierarchy> totest) {
+ System.out.printf("\nTesting %s....\n", tname);
+ int nodefault = 0;
+ List<Hierarchy> ok = new ArrayList<>();
+ List<Hierarchy> err = new ArrayList<>();
+ for (Hierarchy cc : totest) {
+ if (cc.anyDefaults()) {
+ //System.out.printf(" %s\n", cc);
+ if (cc.get_OK()) {
+ ok.add(cc);
+ } else {
+ err.add(cc);
+ }
+ } else {
+ ++nodefault;
+ }
+ }
+
+ errcnt += err.size();
+ okcnt += ok.size();
+ uniqueErr.addAll(err);
+ uniqueOK.addAll(ok);
+
+ System.out.printf(" %5d No default\n %5d Error\n %5d OK\n %5d Total\n",
+ nodefault, err.size(), ok.size(), totest.size());
+ }
+
+ public List<Hierarchy> iExhaustive(int idepth) {
+ List<ClassCase> current = new ArrayList<>();
+ for (int i = 0; i < idepth; ++i) {
+ current = ilayer(current);
+ }
+ return wrapInClassAndHierarchy(current);
+ }
+
+ private List<ClassCase> ilayer(List<ClassCase> srcLayer) {
+ List<ClassCase> lay = new ArrayList<>();
+ for (int i = (int) pow(2, srcLayer.size()) - 1; i >= 0; --i) {
+ List<ClassCase> itfs = new ArrayList<>();
+ for (int b = srcLayer.size() - 1; b >= 0; --b) {
+ if ((i & (1<<b)) != 0) {
+ itfs.add(srcLayer.get(b));
+ }
+ }
+ lay.add(new ClassCase(IVAC, null, itfs));
+ lay.add(new ClassCase(IPRESENT, null, itfs));
+ lay.add(new ClassCase(IDEFAULT, null, itfs));
+ lay.add(new ClassCase(IDEFAULT, null, itfs));
+ }
+ return lay;
+ }
+
+ public List<Hierarchy> cExhaustive() {
+ final Kind[] iKinds = new Kind[]{IDEFAULT, IVAC, IPRESENT, null};
+ final Kind[] cKinds = new Kind[]{CNONE, CABSTRACT, CCONCRETE};
+ List<Hierarchy> totest = new ArrayList<>();
+ for (int i1 = 0; i1 < iKinds.length; ++i1) {
+ for (int i2 = 0; i2 < iKinds.length; ++i2) {
+ for (int i3 = 0; i3 < iKinds.length; ++i3) {
+ for (int c1 = 0; c1 < cKinds.length; ++c1) {
+ for (int c2 = 0; c2 < cKinds.length; ++c2) {
+ for (int c3 = 0; c3 < cKinds.length; ++c3) {
+ totest.add( new Hierarchy(
+ new ClassCase(cKinds[c1],
+ new ClassCase(cKinds[c2],
+ new ClassCase(cKinds[c3],
+ null,
+ iList(iKinds[i1])
+ ),
+ iList(iKinds[i2])
+ ),
+ iList(iKinds[i3])
+ )));
+ }
+ }
+ }
+ }
+ }
+ }
+ return totest;
+ }
+
+ private List<ClassCase> iList(Kind kind) {
+ if (kind == null) {
+ return Collections.EMPTY_LIST;
+ } else {
+ List<ClassCase> itfs = new ArrayList<>();
+ itfs.add(new ClassCase(kind, null, Collections.EMPTY_LIST));
+ return itfs;
+ }
+ }
+
+ public List<Hierarchy> ciShapes() {
+ return wrapInHierarchy(TTShape.allCases(true));
+ }
+
+ public List<Hierarchy> iShapes() {
+ return wrapInClassAndHierarchy(TTShape.allCases(false));
+ }
+
+ public List<Hierarchy> wrapInClassAndHierarchy(List<ClassCase> ihs) {
+ List<Hierarchy> totest = new ArrayList<>();
+ for (ClassCase cc : ihs) {
+ List<ClassCase> interfaces = new ArrayList<>();
+ interfaces.add(cc);
+ totest.add(new Hierarchy(new ClassCase(CNONE, null, interfaces)));
+ }
+ return totest;
+ }
+
+ public List<Hierarchy> wrapInHierarchy(List<ClassCase> ihs) {
+ List<Hierarchy> totest = new ArrayList<>();
+ for (ClassCase cc : ihs) {
+ totest.add(new Hierarchy(cc));
+ }
+ return totest;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/Rule.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+/**
+ *
+ * @author Robert Field
+ */
+public abstract class Rule {
+
+ public final String name;
+
+ public Rule(String name) {
+ this.name = name;
+ }
+
+ abstract boolean guard(ClassCase cc);
+
+ abstract void eval(ClassCase cc);
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/RuleGroup.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static shapegen.ClassCase.Kind.*;
+
+/**
+ *
+ * @author Robert Field
+ */
+public class RuleGroup {
+
+ final String name;
+ private final Rule[] rules;
+
+ public RuleGroup(String name, Rule[] rules) {
+ this.name = name;
+ this.rules = rules;
+ }
+
+ public boolean exec(ClassCase cc) {
+ boolean found = false;
+ for (Rule rule : rules) {
+ if (rule.guard(cc)) {
+ if (found) {
+ throw new RuntimeException("Bad rules -- multiple matches " + toString() + " for " + cc);
+ } else {
+ rule.eval(cc);
+ found = true;
+ }
+ }
+ }
+ return found;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ public static RuleGroup PROVENENCE = new RuleGroup("Provenence", new Rule[] {
+ new Rule("P-CDeclare") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(CCONCRETE, CABSTRACT);
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_mprov(cc);
+ cc.set_HasClassMethod(true);
+ }
+ },
+
+ new Rule("P-IDeclare") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(IDEFAULT, IPRESENT);
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_mprov(cc);
+ }
+ },
+
+ new Rule("P-IntfInh") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(IVAC, CNONE) && !(cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod());
+ }
+
+ void eval(ClassCase cc) {
+ Set<ClassCase> _S = new HashSet<>();
+ for (ClassCase t : cc.getSupertypes()) {
+ _S.addAll(t.get_mprov());
+ }
+ Set<ClassCase> tops = new HashSet<>();
+ for (ClassCase _W : _S) {
+ for (ClassCase _V : _S) {
+ if (_V.equals(_W) || !(_V.isSubtypeOf(_W))) {
+ tops.add(_W);
+ }
+ }
+ }
+ cc.set_mprov(tops);
+ }
+ },
+
+ new Rule("P-ClassInh") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(CNONE) && (cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod());
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_mprov(cc.getSuperclass());
+ cc.set_HasClassMethod(true);
+ }
+ },
+
+ });
+
+ public static RuleGroup MARKER = new RuleGroup("Marker", new Rule[] {
+ new Rule("M-Default") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(IDEFAULT);
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_HasDefault(true);
+ }
+ },
+
+ new Rule("M-Conc") {
+ boolean guard(ClassCase cc) {
+ return cc.isa(CCONCRETE);
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_IsConcrete(true);
+ }
+ },
+
+ });
+
+ public static RuleGroup RESOLUTION = new RuleGroup("Resolution", new Rule[] {
+ new Rule("R-Resolve") {
+ boolean guard(ClassCase cc) {
+ if (!(cc.isClass() && cc.get_mprov().size() == 1)) {
+ return false;
+ }
+ ClassCase _V = cc.get_mprov().iterator().next();
+ return _V.get_IsConcrete() || _V.get_HasDefault();
+ }
+
+ void eval(ClassCase cc) {
+ ClassCase _V = cc.get_mprov().iterator().next();
+ cc.set_mres(_V);
+ }
+ },
+
+ });
+
+ public static RuleGroup DEFENDER = new RuleGroup("Defender", new Rule[] {
+ new Rule("D-Defend") {
+ boolean guard(ClassCase cc) {
+ ClassCase mresSuper = cc.hasSuperclass() ? cc.getSuperclass().get_mres() : null;
+ boolean eq = cc.get_mres() == null ? mresSuper == null : cc.get_mres().equals(mresSuper);
+ return cc.isa(CNONE) && !eq;
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_mdefend(cc.get_mres());
+ }
+ },
+
+ });
+
+ public static RuleGroup CHECKING = new RuleGroup("Checking", new Rule[] {
+ new Rule("C-Check") {
+ boolean guard(ClassCase cc) {
+ for (ClassCase t : cc.getSupertypes()) {
+ if (! t.get_OK()) {
+ return false;
+ }
+ }
+ int defenderCount = 0;
+ int provCount = 0;
+ for (ClassCase prov : cc.get_mprov()) {
+ if (prov.get_HasDefault()) {
+ defenderCount++;
+ }
+ provCount++;
+ }
+ return provCount <= 1 || defenderCount == 0;
+ }
+
+ void eval(ClassCase cc) {
+ cc.set_OK(true);
+ }
+ },
+
+ });
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/TTNode.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import shapegen.ClassCase.Kind;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static shapegen.ClassCase.Kind.*;
+
+/**
+ * Type Template Node
+ *
+ * @author Robert Field
+ */
+public class TTNode {
+
+ final List<TTNode> supertypes;
+ final boolean canBeClass;
+
+ private int currentKindIndex;
+ private Kind[] kinds;
+
+ public TTNode(List<TTNode> subtypes, boolean canBeClass) {
+ this.supertypes = subtypes;
+ this.canBeClass = canBeClass;
+ }
+
+ public void start(boolean includeClasses) {
+ kinds =
+ supertypes.isEmpty()?
+ (new Kind[]{IDEFAULT, IPRESENT})
+ : ((includeClasses && canBeClass)?
+ new Kind[]{CNONE, IVAC, IDEFAULT, IPRESENT}
+ : new Kind[]{IVAC, IDEFAULT, IPRESENT});
+ currentKindIndex = 0;
+
+ for (TTNode sub : supertypes) {
+ sub.start(includeClasses);
+ }
+ }
+
+ public boolean next() {
+ ++currentKindIndex;
+ if (currentKindIndex >= kinds.length) {
+ currentKindIndex = 0;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public void collectAllSubtypes(Set<TTNode> subs) {
+ subs.add(this);
+ for (TTNode n : supertypes) {
+ n.collectAllSubtypes(subs);
+ }
+ }
+
+ private Kind getKind() {
+ return kinds[currentKindIndex];
+ }
+
+ boolean isInterface() {
+ return getKind().isInterface;
+ }
+
+ boolean isClass() {
+ return !isInterface();
+ }
+
+ boolean hasDefault() {
+ return getKind() == IDEFAULT;
+ }
+
+ public boolean isValid() {
+ for (TTNode n : supertypes) {
+ if (!n.isValid() || (isInterface() && n.isClass())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public ClassCase genCase() {
+ ClassCase subclass;
+ List<TTNode> ttintfs;
+ if (isClass() && !supertypes.isEmpty() && supertypes.get(0).isClass()) {
+ subclass = supertypes.get(0).genCase();
+ ttintfs = supertypes.subList(1, supertypes.size());
+ } else {
+ subclass = null;
+ ttintfs = supertypes;
+ }
+ List<ClassCase> intfs = new ArrayList<>();
+ for (TTNode node : ttintfs) {
+ intfs.add(node.genCase());
+ }
+ return new ClassCase(getKind(), subclass, intfs);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/TTParser.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.io.IOException;
+import java.io.StringReader;
+
+import static java.lang.Character.isLetter;
+import static java.lang.Character.isUpperCase;
+import static java.lang.Character.isWhitespace;
+
+/**
+ * Parse a type template definition string
+ *
+ * input :: classDef
+ * classDef :: letter [ ( classDef* ) ]
+ *
+ * @author Robert Field
+ */
+public class TTParser extends StringReader {
+
+ private Map<Character, TTNode> letterMap = new HashMap<>();
+ private char ch;
+
+ private final String def;
+
+ public TTParser(String s) {
+ super(s);
+ this.def = s;
+ }
+
+ private void advance() throws IOException {
+ do {
+ ch = (char)read();
+ } while (isWhitespace(ch));
+ }
+
+ public TTNode parse() {
+ try {
+ advance();
+ return classDef();
+ } catch (IOException t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ private TTNode classDef() throws IOException {
+ if (!isLetter(ch)) {
+ if (ch == (char)-1) {
+ throw new IOException("Unexpected end of type template in " + def);
+ } else {
+ throw new IOException("Unexpected character in type template: " + (Character)ch + " in " + def);
+ }
+ }
+ char nodeCh = ch;
+ TTNode node = letterMap.get(nodeCh);
+ boolean canBeClass = isUpperCase(nodeCh);
+ advance();
+ if (node == null) {
+ List<TTNode> subtypes = new ArrayList<>();
+ if (ch == '(') {
+ advance();
+ while (ch != ')') {
+ subtypes.add(classDef());
+ }
+ advance();
+ }
+ node = new TTNode(subtypes, canBeClass);
+ letterMap.put(nodeCh, node);
+ }
+ return node;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/fd/shapegen/TTShape.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shapegen;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * @author Robert Field
+ */
+public class TTShape {
+
+ private final TTNode root;
+ private final TTNode[] nodes;
+
+ TTShape(TTNode root) {
+ this.root = root;
+ Set<TTNode> subs = new HashSet<>();
+ root.collectAllSubtypes(subs);
+ nodes = subs.toArray(new TTNode[subs.size()]);
+ }
+
+ private List<ClassCase> toCases(boolean includeClasses) {
+ List<ClassCase> ccs = new ArrayList<>();
+ root.start(includeClasses);
+ int i;
+ outer:
+ while (true) {
+ if (root.isValid()) {
+ ClassCase cc = root.genCase();
+ //System.out.println(cc);
+ ccs.add(cc);
+ }
+
+ i = 0;
+ do {
+ if (i >= nodes.length) {
+ break outer;
+ }
+ } while(!nodes[i++].next());
+ }
+ return ccs;
+ }
+
+ public static List<ClassCase> allCases(boolean includeClasses) {
+ List<ClassCase> ccs = new ArrayList<>();
+ for (TTShape shape : SHAPES) {
+ ccs.addAll(shape.toCases(includeClasses));
+ }
+ return ccs;
+ }
+
+ public static TTShape parse(String s) {
+ return new TTShape(new TTParser(s).parse());
+ }
+
+ public static final TTShape[] SHAPES = new TTShape[] {
+ parse("a"),
+ parse("a(b)"),
+ parse("A(bb)"),
+ parse("A(B(d)c(d))"),
+ parse("A(b(c))"),
+ parse("A(B(cd)d)"),
+ parse("A(B(c)c)"),
+ parse("A(B(Ce)d(e))"),
+ parse("A(B(C)d(e))"),
+ parse("A(Bc(d))"),
+ parse("A(B(d)dc)"),
+ parse("A(B(dc)dc)"),
+ parse("A(B(c(d))d)"),
+ parse("A(B(C(d))d)"),
+ parse("A(B(C(e)d(e))e)"),
+ parse("A(B(c(d))c)"),
+ parse("A(B(dc(d))c)"),
+ parse("A(B(C(d))d)"),
+ };
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/separate/Separate.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary smoke test for separate compilation of default methods
+ * @author Maurizio Cimadamore
+ * @compile -XDallowDefaultMethods pkg1/A.java
+ * @compile -XDallowDefaultMethods Separate.java
+ */
+
+import pkg1.A;
+
+class Separate {
+ interface B extends A.I {
+ default void m() { A.m(this); }
+ }
+
+ interface C extends A.I, B { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/separate/pkg1/A.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg1;
+
+public class A {
+ public interface I {
+ default void m() { A.m(this); }
+ }
+
+ public static void m(Object o) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Automatic test for checking correctness of default super/this resolution
+ */
+
+import com.sun.source.util.JavacTask;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+public class TestDefaultSuperCall {
+
+ static int checkCount = 0;
+
+ enum InterfaceKind {
+ DEFAULT("interface A extends B { default void m() { } }"),
+ ABSTRACT("interface A extends B { void m(); }"),
+ NONE("interface A extends B { }");
+
+ String interfaceStr;
+
+ InterfaceKind(String interfaceStr) {
+ this.interfaceStr = interfaceStr;
+ }
+
+ boolean methodDefined() {
+ return this == DEFAULT;
+ }
+ }
+
+ enum PruneKind {
+ NO_PRUNE("interface C { }"),
+ PRUNE("interface C extends A { }");
+
+ boolean methodDefined(InterfaceKind ik) {
+ return this == PRUNE &&
+ ik.methodDefined();
+ }
+
+ String interfaceStr;
+
+ PruneKind(String interfaceStr) {
+ this.interfaceStr = interfaceStr;
+ }
+ }
+
+ enum QualifierKind {
+ DIRECT_1("C"),
+ DIRECT_2("A"),
+ INDIRECT("B"),
+ UNRELATED("E"),
+ ENCLOSING_1(null),
+ ENCLOSING_2(null);
+
+ String qualifierStr;
+
+ QualifierKind(String qualifierStr) {
+ this.qualifierStr = qualifierStr;
+ }
+
+ String getQualifier(Shape sh) {
+ switch (this) {
+ case ENCLOSING_1: return sh.enclosingAt(0);
+ case ENCLOSING_2: return sh.enclosingAt(1);
+ default:
+ return qualifierStr;
+ }
+ }
+
+ boolean isEnclosing() {
+ return this == ENCLOSING_1 ||
+ this == ENCLOSING_2;
+ }
+
+ boolean allowSuperCall(InterfaceKind ik, PruneKind pk) {
+ switch (this) {
+ case DIRECT_1:
+ return pk.methodDefined(ik);
+ case DIRECT_2:
+ return ik.methodDefined() && pk == PruneKind.NO_PRUNE;
+ default:
+ return false;
+ }
+ }
+ }
+
+ enum ExprKind {
+ THIS("this"),
+ SUPER("super");
+
+ String exprStr;
+
+ ExprKind(String exprStr) {
+ this.exprStr = exprStr;
+ }
+ }
+
+ enum ElementKind {
+ INTERFACE("interface #N { #B }", true),
+ INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
+ CLASS("class #N { #B }", false),
+ CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
+ STATIC_CLASS("static class #N { #B }", true),
+ STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
+ ANON_CLASS("new Object() { #B };", false),
+ METHOD("void test() { #B }", false),
+ STATIC_METHOD("static void test() { #B }", true),
+ DEFAULT_METHOD("default void test() { #B }", false);
+
+ String templateDecl;
+ boolean isStatic;
+
+ ElementKind(String templateDecl, boolean isStatic) {
+ this.templateDecl = templateDecl;
+ this.isStatic = isStatic;
+ }
+
+ boolean isClassDecl() {
+ switch(this) {
+ case METHOD:
+ case STATIC_METHOD:
+ case DEFAULT_METHOD:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ boolean isAllowedEnclosing(ElementKind ek, boolean isTop) {
+ switch (this) {
+ case CLASS:
+ case CLASS_EXTENDS:
+ //class is implicitly static inside interface, so skip this combo
+ return ek.isClassDecl() &&
+ ek != INTERFACE && ek != INTERFACE_EXTENDS;
+ case ANON_CLASS:
+ return !ek.isClassDecl();
+ case METHOD:
+ return ek == CLASS || ek == CLASS_EXTENDS ||
+ ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS ||
+ ek == ANON_CLASS;
+ case INTERFACE:
+ case INTERFACE_EXTENDS:
+ case STATIC_CLASS:
+ case STATIC_CLASS_EXTENDS:
+ case STATIC_METHOD:
+ return (isTop && (ek == CLASS || ek == CLASS_EXTENDS)) ||
+ ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS;
+ case DEFAULT_METHOD:
+ return ek == INTERFACE || ek == INTERFACE_EXTENDS;
+ default:
+ throw new AssertionError("Bad enclosing element kind" + this);
+ }
+ }
+
+ boolean isAllowedTop() {
+ switch (this) {
+ case CLASS:
+ case CLASS_EXTENDS:
+ case INTERFACE:
+ case INTERFACE_EXTENDS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ boolean hasSuper() {
+ return this == INTERFACE_EXTENDS ||
+ this == STATIC_CLASS_EXTENDS ||
+ this == CLASS_EXTENDS;
+ }
+ }
+
+ static class Shape {
+
+ String shapeStr;
+ List<ElementKind> enclosingElements;
+ List<String> enclosingNames;
+ List<String> elementsWithMethod;
+
+ Shape(ElementKind... elements) {
+ System.err.println("elements = " + Arrays.toString(elements));
+ enclosingElements = new ArrayList<>();
+ enclosingNames = new ArrayList<>();
+ elementsWithMethod = new ArrayList<>();
+ int count = 0;
+ String prevName = null;
+ for (ElementKind ek : elements) {
+ String name = "name"+count++;
+ if (ek.isStatic) {
+ enclosingElements = new ArrayList<>();
+ enclosingNames = new ArrayList<>();
+ }
+ if (ek.isClassDecl()) {
+ enclosingElements.add(ek);
+ enclosingNames.add(name);
+ } else {
+ elementsWithMethod.add(prevName);
+ }
+ String element = ek.templateDecl.replaceAll("#N", name);
+ shapeStr = shapeStr == null ? element : shapeStr.replaceAll("#B", element);
+ prevName = name;
+ }
+ }
+
+ String getShape(QualifierKind qk, ExprKind ek) {
+ String methName = ek == ExprKind.THIS ? "test" : "m";
+ String call = qk.getQualifier(this) + "." + ek.exprStr + "." + methName + "();";
+ return shapeStr.replaceAll("#B", call);
+ }
+
+ String enclosingAt(int index) {
+ return index < enclosingNames.size() ? enclosingNames.get(index) : "BAD";
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+
+ //create default shared JavaCompiler - reused across multiple compilations
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ for (InterfaceKind ik : InterfaceKind.values()) {
+ for (PruneKind pk : PruneKind.values()) {
+ for (ElementKind ek1 : ElementKind.values()) {
+ if (!ek1.isAllowedTop()) continue;
+ for (ElementKind ek2 : ElementKind.values()) {
+ if (!ek2.isAllowedEnclosing(ek1, true)) continue;
+ for (ElementKind ek3 : ElementKind.values()) {
+ if (!ek3.isAllowedEnclosing(ek2, false)) continue;
+ for (ElementKind ek4 : ElementKind.values()) {
+ if (!ek4.isAllowedEnclosing(ek3, false)) continue;
+ for (ElementKind ek5 : ElementKind.values()) {
+ if (!ek5.isAllowedEnclosing(ek4, false) || ek5.isClassDecl()) continue;
+ for (QualifierKind qk : QualifierKind.values()) {
+ for (ExprKind ek : ExprKind.values()) {
+ new TestDefaultSuperCall(ik, pk, new Shape(ek1, ek2, ek3, ek4, ek5), qk, ek).run(comp, fm);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ System.out.println("Total check executed: " + checkCount);
+ }
+
+ InterfaceKind ik;
+ PruneKind pk;
+ Shape sh;
+ QualifierKind qk;
+ ExprKind ek;
+ JavaSource source;
+ DiagnosticChecker diagChecker;
+
+ TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh, QualifierKind qk, ExprKind ek) {
+ this.ik = ik;
+ this.pk = pk;
+ this.sh = sh;
+ this.qk = qk;
+ this.ek = ek;
+ this.source = new JavaSource();
+ this.diagChecker = new DiagnosticChecker();
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ String template = "interface E {}\n" +
+ "interface B { }\n" +
+ "#I\n" +
+ "#P\n" +
+ "#C";
+
+ String source;
+
+ public JavaSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ source = template.replaceAll("#I", ik.interfaceStr)
+ .replaceAll("#P", pk.interfaceStr)
+ .replaceAll("#C", sh.getShape(qk, ek));
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+ void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
+ JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+ Arrays.asList("-XDallowDefaultMethods"), null, Arrays.asList(source));
+ try {
+ ct.analyze();
+ } catch (Throwable ex) {
+ throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
+ }
+ check();
+ }
+
+ void check() {
+ boolean errorExpected = false;
+
+ boolean badEnclosing = false;
+ boolean badThis = false;
+ boolean badSuper = false;
+
+ if (qk == QualifierKind.ENCLOSING_1 &&
+ sh.enclosingNames.size() < 1) {
+ errorExpected |= true;
+ badEnclosing = true;
+ }
+
+ if (qk == QualifierKind.ENCLOSING_2 &&
+ sh.enclosingNames.size() < 2) {
+ errorExpected |= true;
+ badEnclosing = true;
+ }
+
+ if (ek == ExprKind.THIS) {
+ boolean found = false;
+ for (int i = 0; i < sh.enclosingElements.size(); i++) {
+ if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
+ if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
+ found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
+ break;
+ }
+ }
+ errorExpected |= !found;
+ if (!found) {
+ badThis = true;
+ }
+ }
+
+ if (ek == ExprKind.SUPER) {
+
+ int lastIdx = sh.enclosingElements.size() - 1;
+ boolean found = lastIdx == -1 ? false :
+ sh.enclosingElements.get(lastIdx).hasSuper() && qk.allowSuperCall(ik, pk);
+
+ errorExpected |= !found;
+ if (!found) {
+ badSuper = true;
+ }
+ }
+
+ checkCount++;
+ if (diagChecker.errorFound != errorExpected) {
+ throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) +
+ "\nenclosingElems: " + sh.enclosingElements +
+ "\nenclosingNames: " + sh.enclosingNames +
+ "\nelementsWithMethod: " + sh.elementsWithMethod +
+ "\nbad encl: " + badEnclosing +
+ "\nbad this: " + badThis +
+ "\nbad super: " + badSuper +
+ "\nqual kind: " + qk +
+ "\nfound error: " + diagChecker.errorFound);
+ }
+ }
+
+ static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+ boolean errorFound;
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+ System.err.println(diagnostic.getMessage(Locale.getDefault()));
+ errorFound = true;
+ }
+ }
+ }
+}
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Thu Nov 15 00:54:54 2012 +0000
@@ -310,9 +310,8 @@
pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) {
String name = fo.getName();
// ignore resource files, and files which are not really part of javac
- if (name.contains("resources")
- || name.contains("Launcher.class")
- || name.contains("CreateSymbols.class"))
+ if (name.matches(".*resources.[A-Za-z_0-9]+\\.class.*")
+ || name.matches(".*CreateSymbols\\.class.*"))
continue;
scan(fo, results);
}
--- a/langtools/test/tools/javac/diags/examples/CatchWithoutTry.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/diags/examples/CatchWithoutTry.java Thu Nov 15 00:54:54 2012 +0000
@@ -22,9 +22,6 @@
*/
// key: compiler.err.catch.without.try
-// key: compiler.err.expected
-// key: compiler.err.not.stmt
-// key: compiler.err.lambda.not.supported.in.source
class CatchWithoutTry {
void m() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DefaultOverridesObjectMember.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.default.overrides.object.member
+// options: -XDallowDefaultMethods
+
+interface DefaultOverridesObjectMember {
+ default String toString() { return ""; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/OverriddenDefault.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.illegal.default.super.call
+// key: compiler.misc.overridden.default
+// options: -XDallowDefaultMethods
+
+class OverriddenDefault {
+ interface I { default void m() { } }
+ interface J extends I { default void m() { } }
+ interface K extends I {}
+
+ static class C implements J, K {
+ void foo() { K.super.m(); }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RedundantSupertype.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.illegal.default.super.call
+// key: compiler.misc.redundant.supertype
+// options: -XDallowDefaultMethods
+
+class RedundantSupertype {
+ interface I { default void m() { } }
+ interface J extends I { default void m() { } }
+
+ static class C implements I, J {
+ void foo() { I.super.m(); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TypesIncompatibleAbstractDefault.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.types.incompatible.abstract.default
+// options: -XDallowDefaultMethods
+
+class TypesIncompatibleAbstractDefault {
+ interface A {
+ default void m() { }
+ }
+
+ interface B {
+ void m();
+ }
+
+ interface AB extends A, B { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TypesIncompatibleUnrelatedDefaults.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.types.incompatible.unrelated.defaults
+// options: -XDallowDefaultMethods
+
+class TypesIncompatibleUnrelatedDefaults {
+ interface A {
+ default void m() { }
+ }
+
+ interface B {
+ default void m() { }
+ }
+
+ interface AB extends A, B { }
+}
--- a/langtools/test/tools/javac/generics/7022054/T7022054pos1.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/generics/7022054/T7022054pos1.java Thu Nov 15 00:54:54 2012 +0000
@@ -26,7 +26,8 @@
* @bug 7022054
*
* @summary Invalid compiler error on covariant overriding methods with the same erasure
- * @compile T7022054pos1.java
+ * @compile -source 7 T7022054pos1.java
+ * @compile/fail -XDstrictMethodClashCheck T7022054pos1.java
*
*/
--- a/langtools/test/tools/javac/generics/7022054/T7022054pos2.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/generics/7022054/T7022054pos2.java Thu Nov 15 00:54:54 2012 +0000
@@ -26,8 +26,8 @@
* @bug 7022054
*
* @summary Invalid compiler error on covariant overriding methods with the same erasure
- * @compile T7022054pos2.java
- *
+ * @compile -source 7 T7022054pos2.java
+ * @compile/fail -XDstrictMethodClashCheck T7022054pos2.java
*/
class T7022054pos2 {
--- a/langtools/test/tools/javac/generics/inference/6611449/T6611449.out Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/generics/inference/6611449/T6611449.out Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
-T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S))}
-T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T))}
+T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T))}
+T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S))}
T6611449.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S)
T6611449.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, S)
4 errors
--- a/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
-T7086601a.java:20:9: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m1(java.lang.Iterable<? super S>,java.lang.Iterable<? super S>), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String,java.lang.Object))}
-T7086601a.java:24:9: compiler.err.cant.apply.symbols: kindname.method, m2, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,java.lang.Iterable<java.lang.Double>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m2(java.lang.Iterable<? super S>,java.lang.Iterable<? super S>,java.lang.Iterable<? super S>), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Object))}
-T7086601a.java:28:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m3(java.lang.Iterable<? super S>...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String,java.lang.Object))}
-T7086601a.java:32:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,java.lang.Iterable<java.lang.Double>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m3(java.lang.Iterable<? super S>...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Object))}
+T7086601a.java:20:9: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m1(java.lang.Iterable<? super S>,java.lang.Iterable<? super S>), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String,java.lang.Object)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Object), (compiler.misc.arg.length.mismatch))}
+T7086601a.java:24:9: compiler.err.cant.apply.symbols: kindname.method, m2, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,java.lang.Iterable<java.lang.Double>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m2(java.lang.Iterable<? super S>,java.lang.Iterable<? super S>,java.lang.Iterable<? super S>), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Object)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Object), (compiler.misc.arg.length.mismatch))}
+T7086601a.java:28:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m3(java.lang.Iterable<? super S>...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String,java.lang.Object)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch))}
+T7086601a.java:32:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable<java.lang.String>,java.lang.Iterable<java.lang.Integer>,java.lang.Iterable<java.lang.Double>,{(compiler.misc.inapplicable.method: kindname.method, T7086601, <S>m3(java.lang.Iterable<? super S>...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Object)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch))}
4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/incompleteStatements/T8000484.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,17 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8000484
+ * @summary Bad error recovery when 'catch' without 'try' is found
+ * @compile/fail/ref=T8000484.out -XDrawDiagnostics T8000484.java
+ */
+
+public class T8000484 {
+ void m() {
+ catch (Exception e){}
+ else{}
+ finally{}
+ catch (Exception e) {catch (Exception e){}}
+ else{else{}}
+ finally{finally{}}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/incompleteStatements/T8000484.out Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,10 @@
+T8000484.java:10:9: compiler.err.catch.without.try
+T8000484.java:11:9: compiler.err.else.without.if
+T8000484.java:12:9: compiler.err.finally.without.try
+T8000484.java:13:30: compiler.err.catch.without.try
+T8000484.java:13:9: compiler.err.catch.without.try
+T8000484.java:14:14: compiler.err.else.without.if
+T8000484.java:14:9: compiler.err.else.without.if
+T8000484.java:15:17: compiler.err.finally.without.try
+T8000484.java:15:9: compiler.err.finally.without.try
+9 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/options/T6949443.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6949443
+ * @summary VisitTree assertion triggered using -Xjcov on small sample program
+ * @compile -Xjcov T6949443.java
+ */
+
+public class T6949443 {
+ public static void main(String[] args) {
+ Integer i = 0;
+ i++;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/AmbiguityPrecedence.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve(keys={"compiler.err.ref.ambiguous"})
+class AmbiguityPrecedence {
+
+ @Candidate(applicable=Phase.BASIC)
+ static void m1(long l, int i) {}
+ @Candidate(applicable=Phase.BASIC)
+ static void m1(int i, long l) {}
+ @Candidate
+ static void m1(Integer i1, Integer i2) {}
+
+ @Candidate(applicable=Phase.BOX)
+ static void m2(Object o, Integer i) {}
+ @Candidate(applicable=Phase.BOX)
+ static void m2(Integer i, Object o) {}
+ @Candidate
+ static void m2(Integer... o) {}
+
+ {
+ m1(1, 1);
+ m2(1, 1);
+ }
+}
--- a/langtools/test/tools/javac/scope/7046348/EagerInterfaceCompletionTest.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/scope/7046348/EagerInterfaceCompletionTest.java Thu Nov 15 00:54:54 2012 +0000
@@ -30,6 +30,7 @@
import java.io.File;
import java.net.URI;
import java.util.Arrays;
+import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
@@ -43,13 +44,15 @@
JavaCompiler javacTool;
File testDir;
+ VersionKind versionKind;
HierarchyKind hierarchyKind;
TestKind testKind;
ActionKind actionKind;
- EagerInterfaceCompletionTest(JavaCompiler javacTool, File testDir,
+ EagerInterfaceCompletionTest(JavaCompiler javacTool, File testDir, VersionKind versionKind,
HierarchyKind hierarchyKind, TestKind testKind, ActionKind actionKind) {
this.javacTool = javacTool;
+ this.versionKind = versionKind;
this.hierarchyKind = hierarchyKind;
this.testDir = testDir;
this.testKind = testKind;
@@ -62,7 +65,7 @@
actionKind.doAction(this);
DiagnosticChecker dc = new DiagnosticChecker();
compile(dc, testKind.source);
- if (testKind.completionFailure(actionKind, hierarchyKind) != dc.errorFound) {
+ if (testKind.completionFailure(versionKind, actionKind, hierarchyKind) != dc.errorFound) {
if (dc.errorFound) {
error("Unexpected completion failure" +
"\nhierarhcyKind " + hierarchyKind +
@@ -80,7 +83,8 @@
void compile(DiagnosticChecker dc, JavaSource... sources) {
try {
CompilationTask ct = javacTool.getTask(null, null, dc,
- Arrays.asList("-d", testDir.getAbsolutePath(), "-cp", testDir.getAbsolutePath()),
+ Arrays.asList("-d", testDir.getAbsolutePath(), "-cp",
+ testDir.getAbsolutePath(), versionKind.optsArr[0], versionKind.optsArr[1]),
null, Arrays.asList(sources));
ct.call();
}
@@ -108,12 +112,25 @@
boolean errorFound = false;
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- errorFound = true;
+ if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+ errorFound = true;
+ }
}
}
//global declarations
+ enum VersionKind {
+ PRE_LAMBDA("-source", "7"),
+ LAMBDA("-source", "8");
+
+ String[] optsArr;
+
+ VersionKind(String... optsArr) {
+ this.optsArr = optsArr;
+ }
+ }
+
enum HierarchyKind {
INTERFACE("interface A { boolean f = false; void m(); }\n" +
"class B implements A { public void m() {} }"),
@@ -157,13 +174,14 @@
this.source = new JavaSource("Test2.java", code);
}
- boolean completionFailure(ActionKind ak, HierarchyKind hk) {
+ boolean completionFailure(VersionKind vk, ActionKind ak, HierarchyKind hk) {
switch (this) {
case ACCESS_ONLY:
case CONSTR: return ak == ActionKind.REMOVE_B;
case FIELD:
case SUPER: return true;
- case METHOD: return hk != HierarchyKind.INTERFACE || ak == ActionKind.REMOVE_B;
+ case METHOD: return hk != HierarchyKind.INTERFACE || ak == ActionKind.REMOVE_B ||
+ (hk == HierarchyKind.INTERFACE && ak == ActionKind.REMOVE_A && vk == VersionKind.LAMBDA);
default: throw new AssertionError("Unexpected test kind " + this);
}
}
@@ -173,12 +191,15 @@
String SCRATCH_DIR = System.getProperty("user.dir");
JavaCompiler javacTool = ToolProvider.getSystemJavaCompiler();
int n = 0;
- for (HierarchyKind hierarchyKind : HierarchyKind.values()) {
- for (TestKind testKind : TestKind.values()) {
- for (ActionKind actionKind : ActionKind.values()) {
- File testDir = new File(SCRATCH_DIR, "test"+n);
- new EagerInterfaceCompletionTest(javacTool, testDir, hierarchyKind, testKind, actionKind).test();
- n++;
+ for (VersionKind versionKind : VersionKind.values()) {
+ for (HierarchyKind hierarchyKind : HierarchyKind.values()) {
+ for (TestKind testKind : TestKind.values()) {
+ for (ActionKind actionKind : ActionKind.values()) {
+ File testDir = new File(SCRATCH_DIR, "test"+n);
+ new EagerInterfaceCompletionTest(javacTool, testDir, versionKind,
+ hierarchyKind, testKind, actionKind).test();
+ n++;
+ }
}
}
}
--- a/langtools/test/tools/javac/versions/check.sh Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javac/versions/check.sh Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. 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
@@ -22,7 +22,7 @@
#
# @test
-# @bug 4981566 5028634 5094412 6304984 7025786 7025789
+# @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112
# @summary Check interpretation of -target and -source options
# @build CheckClassFileVersion
# @run shell check.sh
@@ -47,32 +47,39 @@
"$JC" ${TESTTOOLVMOPTS} -d $TC $* $TC/X.java && "$J" $CFV $TC/X.class $V || exit 2
}
+# check for all combinations of target values
+check_target() {
+ check $1 -source $2 -target $3
+ check $1 -source $2 -target 1.${3}
+}
+# check for all combinations of source and target values
+check_source_target() {
+ check_target $1 $2 $3
+ check_target $1 1.${2} $3
+}
+
check 48.0 -source 1.4
check 49.0 -source 1.4 -target 1.5
check 49.0 -source 1.5 -target 1.5
-check 50.0 -source 1.4 -target 1.6
-check 50.0 -source 1.5 -target 1.6
-check 50.0 -source 1.6 -target 1.6
-check 50.0 -source 1.6 -target 6
-check 50.0 -source 6 -target 1.6
-check 50.0 -source 6 -target 6
+check_target 50.0 1.4 6
+check_target 50.0 1.5 6
+check_source_target 50.0 6 6
+
+check_target 51.0 1.4 7
+check_target 51.0 1.5 7
+check_source_target 51.0 6 7
+check_source_target 51.0 7 7
-check 51.0
-check 51.0 -source 1.5
-check 51.0 -source 1.6
-check 51.0 -source 6
-check 51.0 -source 1.7
-check 51.0 -source 7
-check 51.0 -source 7 -target 1.7
-check 51.0 -source 7 -target 7
+check_target 52.0 1.4 8
+check_target 52.0 1.5 8
+check_source_target 52.0 6 8
+check_source_target 52.0 7 8
+check_source_target 52.0 8 8
-# Update when class file version is revved
-check 51.0 -source 1.8
-check 51.0 -source 8
-check 51.0 -target 1.8
-check 51.0 -target 8
+# and finally the default with no options
+check 52.0
# Check source versions
--- a/langtools/test/tools/javadoc/6958836/Test.java Wed Nov 14 10:20:25 2012 -0800
+++ b/langtools/test/tools/javadoc/6958836/Test.java Thu Nov 15 00:54:54 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. 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 6958836
+ * @bug 6958836 8002168
* @summary javadoc should support -Xmaxerrs and -Xmaxwarns
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/CheckResourceKeys.java Thu Nov 15 00:54:54 2012 +0000
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8000612
+ * @summary need test program to validate javadoc resource bundles
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import com.sun.tools.classfile.*;
+
+/**
+ * Compare string constants in javadoc classes against keys in javadoc resource bundles.
+ */
+public class CheckResourceKeys {
+ /**
+ * Main program.
+ * Options:
+ * -finddeadkeys
+ * look for keys in resource bundles that are no longer required
+ * -findmissingkeys
+ * look for keys in resource bundles that are missing
+ *
+ * @throws Exception if invoked by jtreg and errors occur
+ */
+ public static void main(String... args) throws Exception {
+ CheckResourceKeys c = new CheckResourceKeys();
+ if (c.run(args))
+ return;
+
+ if (is_jtreg())
+ throw new Exception(c.errors + " errors occurred");
+ else
+ System.exit(1);
+ }
+
+ static boolean is_jtreg() {
+ return (System.getProperty("test.src") != null);
+ }
+
+ /**
+ * Main entry point.
+ */
+ boolean run(String... args) throws Exception {
+ boolean findDeadKeys = false;
+ boolean findMissingKeys = false;
+
+ if (args.length == 0) {
+ if (is_jtreg()) {
+ findDeadKeys = true;
+ findMissingKeys = true;
+ } else {
+ System.err.println("Usage: java CheckResourceKeys <options>");
+ System.err.println("where options include");
+ System.err.println(" -finddeadkeys find keys in resource bundles which are no longer required");
+ System.err.println(" -findmissingkeys find keys in resource bundles that are required but missing");
+ return true;
+ }
+ } else {
+ for (String arg: args) {
+ if (arg.equalsIgnoreCase("-finddeadkeys"))
+ findDeadKeys = true;
+ else if (arg.equalsIgnoreCase("-findmissingkeys"))
+ findMissingKeys = true;
+ else
+ error("bad option: " + arg);
+ }
+ }
+
+ if (errors > 0)
+ return false;
+
+ Set<String> codeKeys = getCodeKeys();
+ Set<String> resourceKeys = getResourceKeys();
+
+ System.err.println("found " + codeKeys.size() + " keys in code");
+ System.err.println("found " + resourceKeys.size() + " keys in resource bundles");
+
+ if (findDeadKeys)
+ findDeadKeys(codeKeys, resourceKeys);
+
+ if (findMissingKeys)
+ findMissingKeys(codeKeys, resourceKeys);
+
+ return (errors == 0);
+ }
+
+ /**
+ * Find keys in resource bundles which are probably no longer required.
+ * A key is required if there is a string in the code that is a resource key,
+ * or if the key is well-known according to various pragmatic rules.
+ */
+ void findDeadKeys(Set<String> codeKeys, Set<String> resourceKeys) {
+ for (String rk: resourceKeys) {
+ if (codeKeys.contains(rk))
+ continue;
+
+ error("Resource key not found in code: " + rk);
+ }
+ }
+
+ /**
+ * For all strings in the code that look like they might be
+ * a resource key, verify that a key exists.
+ */
+ void findMissingKeys(Set<String> codeKeys, Set<String> resourceKeys) {
+ for (String ck: codeKeys) {
+ if (resourceKeys.contains(ck))
+ continue;
+ error("No resource for \"" + ck + "\"");
+ }
+ }
+
+ /**
+ * Get the set of strings from (most of) the javadoc classfiles.
+ */
+ Set<String> getCodeKeys() throws IOException {
+ Set<String> results = new TreeSet<String>();
+ JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+ JavaFileManager fm = c.getStandardFileManager(null, null, null);
+ JavaFileManager.Location javadocLoc = findJavadocLocation(fm);
+ String[] pkgs = {
+ "com.sun.tools.doclets",
+ "com.sun.tools.javadoc"
+ };
+ for (String pkg: pkgs) {
+ for (JavaFileObject fo: fm.list(javadocLoc,
+ pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) {
+ String name = fo.getName();
+ // ignore resource files
+ if (name.matches(".*resources.[A-Za-z_0-9]+\\.class.*"))
+ continue;
+ scan(fo, results);
+ }
+ }
+
+ // special handling for code strings synthesized in
+ // com.sun.tools.doclets.internal.toolkit.util.Util.getTypeName
+ String[] extras = {
+ "AnnotationType", "Class", "Enum", "Error", "Exception", "Interface"
+ };
+ for (String s: extras) {
+ if (results.contains("doclet." + s))
+ results.add("doclet." + s.toLowerCase());
+ }
+
+ return results;
+ }
+
+ // depending on how the test is run, javadoc may be on bootclasspath or classpath
+ JavaFileManager.Location findJavadocLocation(JavaFileManager fm) {
+ JavaFileManager.Location[] locns =
+ { StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH };
+ try {
+ for (JavaFileManager.Location l: locns) {
+ JavaFileObject fo = fm.getJavaFileForInput(l,
+ "com.sun.tools.javadoc.Main", JavaFileObject.Kind.CLASS);
+ if (fo != null) {
+ System.err.println("found javadoc in " + l);
+ return l;
+ }
+ }
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ throw new IllegalStateException("Cannot find javadoc");
+ }
+
+ /**
+ * Get the set of strings from a class file.
+ * Only strings that look like they might be a resource key are returned.
+ */
+ void scan(JavaFileObject fo, Set<String> results) throws IOException {
+ //System.err.println("scan " + fo.getName());
+ InputStream in = fo.openInputStream();
+ try {
+ ClassFile cf = ClassFile.read(in);
+ for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) {
+ if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) {
+ String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value;
+ if (v.matches("(doclet|main|javadoc|tag)\\.[A-Za-z0-9-_.]+"))
+ results.add(v);
+ }
+ }
+ } catch (ConstantPoolException ignore) {
+ } finally {
+ in.close();
+ }
+ }
+
+ /**
+ * Get the set of keys from the javadoc resource bundles.
+ */
+ Set<String> getResourceKeys() {
+ String[] names = {
+ "com.sun.tools.doclets.formats.html.resources.standard",
+ "com.sun.tools.doclets.internal.toolkit.resources.doclets",
+ "com.sun.tools.javadoc.resources.javadoc",
+ };
+ Set<String> results = new TreeSet<String>();
+ for (String name : names) {
+ ResourceBundle b = ResourceBundle.getBundle(name);
+ results.addAll(b.keySet());
+ }
+ return results;
+ }
+
+ /**
+ * Report an error.
+ */
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int errors;
+}