--- a/.hgtags-top-repo Sat Jan 24 23:23:06 2015 -0800
+++ b/.hgtags-top-repo Wed Jul 05 20:15:59 2017 +0200
@@ -289,3 +289,4 @@
8994f5d87b3bb5e8d317d4e8ccb326da1a73684a jdk9-b44
3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
+b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
--- a/corba/.hgtags Sat Jan 24 23:23:06 2015 -0800
+++ b/corba/.hgtags Wed Jul 05 20:15:59 2017 +0200
@@ -289,3 +289,4 @@
1f57bd728c9e6865ccb9d43ccd80a1c11230a32f jdk9-b44
9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
+ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
--- a/hotspot/.hgtags Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/.hgtags Wed Jul 05 20:15:59 2017 +0200
@@ -449,3 +449,4 @@
43a44b56dca61a4d766a20f0528fdd8b5ceff873 jdk9-b44
5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
+3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -284,19 +284,20 @@
MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT),
MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT),
- MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT),
- MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT),
- MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT),
- MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT),
- MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT),
- MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT),
- MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT),
- MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT),
+ // Attention: Higher and lower half are inserted in reversed order.
+ MTTFHAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MFTFHAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MTTFIAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+ MFTFIAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+ MTTEXASR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+ MFTEXASR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+ MTTEXASRU_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
+ MFTEXASRU_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
- MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT),
- MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT),
+ MTVRSAVE_OPCODE = (MTSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MFVRSAVE_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
- MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT),
+ MFTB_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 12 << SPR_0_4_SHIFT),
MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1),
MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1),
@@ -1494,6 +1495,26 @@
inline void mftexasr(Register d);
inline void mftexasru(Register d);
+ // TEXASR bit description
+ enum transaction_failure_reason {
+ // Upper half (TEXASRU):
+ tm_failure_persistent = 7, // The failure is likely to recur on each execution.
+ tm_disallowed = 8, // The instruction is not permitted.
+ tm_nesting_of = 9, // The maximum transaction level was exceeded.
+ tm_footprint_of = 10, // The tracking limit for transactional storage accesses was exceeded.
+ tm_self_induced_cf = 11, // A self-induced conflict occurred in Suspended state.
+ tm_non_trans_cf = 12, // A conflict occurred with a non-transactional access by another processor.
+ tm_trans_cf = 13, // A conflict occurred with another transaction.
+ tm_translation_cf = 14, // A conflict occurred with a TLB invalidation.
+ tm_inst_fetch_cf = 16, // An instruction fetch was performed from a block that was previously written transactionally.
+ tm_tabort = 31, // Termination was caused by the execution of an abort instruction.
+ // Lower half:
+ tm_suspended = 32, // Failure was recorded in Suspended state.
+ tm_failure_summary = 36, // Failure has been detected and recorded.
+ tm_tfiar_exact = 37, // Value in the TFIAR is exact.
+ tm_rot = 38, // Rollback-only transaction.
+ };
+
// PPC 1, section 2.4.1 Branch Instructions
inline void b( address a, relocInfo::relocType rt = relocInfo::none);
inline void b( Label& L);
@@ -1581,6 +1602,7 @@
inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none);
// condition register logic instructions
+ // NOTE: There's a preferred form: d and s2 should point into the same condition register.
inline void crand( int d, int s1, int s2);
inline void crnand(int d, int s1, int s2);
inline void cror( int d, int s1, int s2);
@@ -1590,6 +1612,19 @@
inline void crandc(int d, int s1, int s2);
inline void crorc( int d, int s1, int s2);
+ // More convenient version.
+ int condition_register_bit(ConditionRegister cr, Condition c) {
+ return 4 * (int)(intptr_t)cr + c;
+ }
+ void crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+
// icache and dcache related instructions
inline void icbi( Register s1, Register s2);
//inline void dcba(Register s1, Register s2); // Instruction for embedded processor only.
@@ -1673,6 +1708,10 @@
inline void smt_prio_low();
inline void smt_prio_medium_low();
inline void smt_prio_medium();
+ // >= Power7
+ inline void smt_yield();
+ inline void smt_mdoio();
+ inline void smt_mdoom();
// trap instructions
inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur)
@@ -1958,6 +1997,7 @@
inline void tbeginrot_(); // R=1 Rollback-Only Transaction
inline void tend_(); // A=0
inline void tendall_(); // A=1
+ inline void tabort_();
inline void tabort_(Register a);
inline void tabortwc_(int t, Register a, Register b);
inline void tabortwci_(int t, Register a, int si);
@@ -1967,6 +2007,10 @@
inline void tresume_(); // tsr with L=1
inline void tcheck(int f);
+ static bool is_tbegin(int x) {
+ return TBEGIN_OPCODE == (x & (0x3f << OPCODE_SHIFT | 0x3ff << 1));
+ }
+
// The following encoders use r0 as second operand. These instructions
// read r0 as '0'.
inline void lwzx( Register d, Register s2);
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -453,6 +453,48 @@
inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
+// More convenient version.
+inline void Assembler::crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crnand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ cror(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crxor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crnor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ creqv(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crandc(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crorc(dst_bit, src_bit, dst_bit);
+}
+
// Conditional move (>= Power7)
inline void Assembler::isel(Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b) {
if (b == noreg) {
@@ -516,6 +558,10 @@
inline void Assembler::smt_prio_medium() { Assembler::or_unchecked(R2, R2, R2); }
inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5, R5, R5); }
inline void Assembler::smt_prio_high() { Assembler::or_unchecked(R3, R3, R3); }
+// >= Power7
+inline void Assembler::smt_yield() { Assembler::or_unchecked(R27, R27, R27); }
+inline void Assembler::smt_mdoio() { Assembler::or_unchecked(R29, R29, R29); }
+inline void Assembler::smt_mdoom() { Assembler::or_unchecked(R30, R30, R30); }
inline void Assembler::twi_0(Register a) { twi_unchecked(0, a, 0);}
@@ -778,7 +824,8 @@
inline void Assembler::tbeginrot_() { emit_int32( TBEGIN_OPCODE | /*R=1*/ 1u << (31-10) | rc(1)); }
inline void Assembler::tend_() { emit_int32( TEND_OPCODE | rc(1)); }
inline void Assembler::tendall_() { emit_int32( TEND_OPCODE | /*A=1*/ 1u << (31-6) | rc(1)); }
-inline void Assembler::tabort_(Register a) { emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
+inline void Assembler::tabort_() { emit_int32( TABORT_OPCODE | rc(1)); }
+inline void Assembler::tabort_(Register a) { assert(a != R0, "r0 not allowed"); emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
inline void Assembler::tabortwc_(int t, Register a, Register b) { emit_int32( TABORTWC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
inline void Assembler::tabortwci_(int t, Register a, int si) { emit_int32( TABORTWCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); }
inline void Assembler::tabortdc_(int t, Register a, Register b) { emit_int32( TABORTDC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1712,7 +1712,7 @@
andi_(R0, klass, TypeEntries::type_unknown);
// Already unknown. Nothing to do anymore.
//bne(CCR0, do_nothing);
- crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne
+ crorc(CCR0, Assembler::equal, CCR1, Assembler::equal); // cr0 eq = cr1 eq or cr0 ne
beq(CCR0, do_nothing);
clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask));
@@ -1826,9 +1826,9 @@
lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method);
cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic);
cmpwi(CCR1, tmp1, Bytecodes::_invokehandle);
- cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm);
- cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
bne(CCR0, profile_continue);
}
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1079,7 +1079,7 @@
__ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes
__ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison!
__ cmpld(CCR1, tmp1, tmp2);
- __ crand(/*CCR0 lt*/0, /*CCR1 lt*/4+0, /*CCR0 lt*/0);
+ __ crand(CCR0, Assembler::less, CCR1, Assembler::less);
__ blt(CCR0, l_overlap); // Src before dst and distance smaller than size.
// need to copy forwards
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -264,11 +264,11 @@
__ cmpdi(CCR0, Rmdo, 0);
__ beq(CCR0, no_mdo);
- // Increment backedge counter in the MDO.
- const int mdo_bc_offs = in_bytes(MethodData::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
- __ lwz(Rscratch2, mdo_bc_offs, Rmdo);
+ // Increment invocation counter in the MDO.
+ const int mdo_ic_offs = in_bytes(MethodData::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
+ __ lwz(Rscratch2, mdo_ic_offs, Rmdo);
__ addi(Rscratch2, Rscratch2, increment);
- __ stw(Rscratch2, mdo_bc_offs, Rmdo);
+ __ stw(Rscratch2, mdo_ic_offs, Rmdo);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ bne(CCR0, done);
@@ -276,12 +276,12 @@
}
// Increment counter in MethodCounters*.
- const int mo_bc_offs = in_bytes(MethodCounters::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
+ const int mo_ic_offs = in_bytes(MethodCounters::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
__ bind(no_mdo);
__ get_method_counters(R19_method, R3_counters, done);
- __ lwz(Rscratch2, mo_bc_offs, R3_counters);
+ __ lwz(Rscratch2, mo_ic_offs, R3_counters);
__ addi(Rscratch2, Rscratch2, increment);
- __ stw(Rscratch2, mo_bc_offs, R3_counters);
+ __ stw(Rscratch2, mo_ic_offs, R3_counters);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ beq(CCR0, *overflow);
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -335,11 +335,11 @@
__ cmpwi(CCR0, Rscratch2, JVM_CONSTANT_UnresolvedClass); // Unresolved class?
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_UnresolvedClassInError); // Unresolved class in error state?
- __ cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ __ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
// Resolved class - need to call vm to get java mirror of the class.
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_Class);
- __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // Neither resolved class nor unresolved case from above?
+ __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal); // Neither resolved class nor unresolved case from above?
__ beq(CCR0, notClass);
__ li(R4, wide ? 1 : 0);
@@ -2611,7 +2611,7 @@
__ cmpwi(CCR0, Rflags, ltos);
__ cmpwi(CCR1, Rflags, dtos);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(1));
- __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal);
__ beq(CCR0, is_one_slot);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(2));
__ bind(is_one_slot);
@@ -3563,7 +3563,7 @@
// Make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class.
__ andi_(R0, Rinstance_size, Klass::_lh_instance_slow_path_bit); // slow path bit equals 0?
- __ crnand(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // slow path bit set or not fully initialized?
+ __ crnand(CCR0, Assembler::equal, CCR1, Assembler::equal); // slow path bit set or not fully initialized?
__ beq(CCR0, Lslow_case);
// --------------------------------------------------------------------------
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -3184,7 +3184,24 @@
jmp(done);
} else {
// Stack: X Y
- Label x_negative, y_odd;
+ Label x_negative, y_not_2;
+
+ static double two = 2.0;
+ ExternalAddress two_addr((address)&two);
+
+ // constant maybe too far on 64 bit
+ lea(tmp2, two_addr);
+ fld_d(Address(tmp2, 0)); // Stack: 2 X Y
+ fcmp(tmp, 2, true, false); // Stack: X Y
+ jcc(Assembler::parity, y_not_2);
+ jcc(Assembler::notEqual, y_not_2);
+
+ fxch(); fpop(); // Stack: X
+ fmul(0); // Stack: X*X
+
+ jmp(done);
+
+ bind(y_not_2);
fldz(); // Stack: 0 X Y
fcmp(tmp, 1, true, false); // Stack: X Y
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -197,7 +197,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -211,27 +242,185 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirfd(dirp))) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirfd(dirp);
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
-
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@@ -317,9 +506,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -344,25 +535,14 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
continue;
}
- // Since we don't create the backing store files in directories
- // pointed to by symbolic links, we also don't follow them when
- // looking for the files. We check for a symbolic link after the
- // call to opendir in order to eliminate a small window where the
- // symlink can be exploited.
- //
- if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
- os::closedir(subdirp);
- continue;
- }
-
struct dirent* udentry;
char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
@@ -465,26 +645,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -496,17 +656,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -520,6 +674,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -530,7 +685,7 @@
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -553,11 +708,14 @@
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -614,19 +772,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -684,8 +877,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -717,13 +917,21 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -838,12 +1046,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -197,7 +197,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -211,22 +242,180 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirfd(dirp))) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirfd(dirp);
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
@@ -317,9 +506,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -344,7 +535,8 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -465,26 +657,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -496,17 +668,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -520,6 +686,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -528,9 +695,8 @@
if (pid == 0) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
-
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -552,12 +718,14 @@
//
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
-
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -614,19 +782,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -684,8 +887,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -716,6 +926,13 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
@@ -723,7 +940,7 @@
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -838,12 +1055,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -199,7 +199,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -213,27 +244,185 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirp->dd_fd)) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirp->dd_fd;
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
-
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@@ -308,9 +497,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -335,7 +526,8 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -504,26 +696,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -535,17 +707,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -559,6 +725,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -569,7 +736,7 @@
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -592,11 +759,14 @@
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -653,19 +823,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -701,8 +906,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -734,13 +946,21 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -856,12 +1076,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -237,7 +237,13 @@
// operation. Note that some platforms only support this with the
// limitation that the only valid value to store is the immediate
// constant 1. There is a test for this in JNI_CreateJavaVM().
- return __sync_lock_test_and_set (dest, exchange_value);
+ jint result = __sync_lock_test_and_set (dest, exchange_value);
+ // All atomic operations are expected to be full memory barriers
+ // (see atomic.hpp). However, __sync_lock_test_and_set is not
+ // a full memory barrier, but an acquire barrier. Hence, this added
+ // barrier.
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
@@ -250,7 +256,9 @@
#ifdef M68K
return m68k_lock_test_and_set(dest, exchange_value);
#else
- return __sync_lock_test_and_set (dest, exchange_value);
+ intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
--- a/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -231,7 +231,13 @@
// operation. Note that some platforms only support this with the
// limitation that the only valid value to store is the immediate
// constant 1. There is a test for this in JNI_CreateJavaVM().
- return __sync_lock_test_and_set (dest, exchange_value);
+ jint result = __sync_lock_test_and_set (dest, exchange_value);
+ // All atomic operations are expected to be full memory barriers
+ // (see atomic.hpp). However, __sync_lock_test_and_set is not
+ // a full memory barrier, but an acquire barrier. Hence, this added
+ // barrier.
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
@@ -244,7 +250,9 @@
#ifdef M68K
return m68k_lock_test_and_set(dest, exchange_value);
#else
- return __sync_lock_test_and_set (dest, exchange_value);
+ intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -89,8 +89,8 @@
public:
ArgumentMap *_vars;
ArgumentMap *_stack;
- short _stack_height;
- short _max_stack;
+ int _stack_height;
+ int _max_stack;
bool _initialized;
ArgumentMap empty_map;
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1905,11 +1905,12 @@
InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
- initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
+ initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK);
InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
+ InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
// JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -128,6 +128,7 @@
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
+ do_klass(Cleaner_klass, sun_misc_Cleaner, Pre ) \
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
\
do_klass(Thread_klass, java_lang_Thread, Pre ) \
--- a/hotspot/src/share/vm/classfile/verifier.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1555,14 +1555,14 @@
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
- &bcs, code_length, ¤t_frame,
- &this_uninit, return_type, cp, CHECK_VERIFY(this));
+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic :
verify_invoke_instructions(
- &bcs, code_length, ¤t_frame,
- &this_uninit, return_type, cp, CHECK_VERIFY(this));
+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_new :
{
@@ -2406,8 +2406,9 @@
void ClassVerifier::verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
- StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
- constantPoolHandle cp, TRAPS) {
+ StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+ bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+ TRAPS) {
u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
@@ -2423,28 +2424,36 @@
return;
}
- // Check if this call is done from inside of a TRY block. If so, make
- // sure that all catch clause paths end in a throw. Otherwise, this
- // can result in returning an incomplete object.
- ExceptionTable exhandlers(_method());
- int exlength = exhandlers.length();
- for(int i = 0; i < exlength; i++) {
- u2 start_pc = exhandlers.start_pc(i);
- u2 end_pc = exhandlers.end_pc(i);
+ // If this invokespecial call is done from inside of a TRY block then make
+ // sure that all catch clause paths end in a throw. Otherwise, this can
+ // result in returning an incomplete object.
+ if (in_try_block) {
+ ExceptionTable exhandlers(_method());
+ int exlength = exhandlers.length();
+ for(int i = 0; i < exlength; i++) {
+ u2 start_pc = exhandlers.start_pc(i);
+ u2 end_pc = exhandlers.end_pc(i);
- if (bci >= start_pc && bci < end_pc) {
- if (!ends_in_athrow(exhandlers.handler_pc(i))) {
- verify_error(ErrorContext::bad_code(bci),
- "Bad <init> method call from after the start of a try block");
- return;
- } else if (VerboseVerification) {
- ResourceMark rm;
- tty->print_cr(
- "Survived call to ends_in_athrow(): %s",
- current_class()->name()->as_C_string());
+ if (bci >= start_pc && bci < end_pc) {
+ if (!ends_in_athrow(exhandlers.handler_pc(i))) {
+ verify_error(ErrorContext::bad_code(bci),
+ "Bad <init> method call from after the start of a try block");
+ return;
+ } else if (VerboseVerification) {
+ ResourceMark rm;
+ tty->print_cr(
+ "Survived call to ends_in_athrow(): %s",
+ current_class()->name()->as_C_string());
+ }
}
}
- }
+
+ // Check the exception handler target stackmaps with the locals from the
+ // incoming stackmap (before initialize_object() changes them to outgoing
+ // state).
+ verify_exception_handler_targets(bci, true, current_frame,
+ stackmap_table, CHECK_VERIFY(this));
+ } // in_try_block
current_frame->initialize_object(type, current_type());
*this_uninit = true;
@@ -2498,6 +2507,13 @@
}
}
}
+ // Check the exception handler target stackmaps with the locals from the
+ // incoming stackmap (before initialize_object() changes them to outgoing
+ // state).
+ if (in_try_block) {
+ verify_exception_handler_targets(bci, *this_uninit, current_frame,
+ stackmap_table, CHECK_VERIFY(this));
+ }
current_frame->initialize_object(type, new_class_type);
} else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
@@ -2526,8 +2542,8 @@
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
- bool *this_uninit, VerificationType return_type,
- constantPoolHandle cp, TRAPS) {
+ bool in_try_block, bool *this_uninit, VerificationType return_type,
+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
@@ -2693,7 +2709,8 @@
opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method
verify_invoke_init(bcs, index, ref_class_type, current_frame,
- code_length, this_uninit, cp, CHECK_VERIFY(this));
+ code_length, in_try_block, this_uninit, cp, stackmap_table,
+ CHECK_VERIFY(this));
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
--- a/hotspot/src/share/vm/classfile/verifier.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -301,8 +301,9 @@
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
- StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
- constantPoolHandle cp, TRAPS);
+ StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+ bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+ TRAPS);
// Used by ends_in_athrow() to push all handlers that contain bci onto
// the handler_stack, if the handler is not already on the stack.
@@ -316,8 +317,8 @@
void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
- bool* this_uninit, VerificationType return_type,
- constantPoolHandle cp, TRAPS);
+ bool in_try_block, bool* this_uninit, VerificationType return_type,
+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -79,6 +79,7 @@
template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \
+ template(sun_misc_Cleaner, "sun/misc/Cleaner") \
template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \
template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
--- a/hotspot/src/share/vm/code/dependencies.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -560,7 +560,7 @@
put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value());
} else if (arg.is_method()) {
what = "method ";
- put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value());
+ put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL);
} else if (arg.is_klass()) {
what = "class ";
} else {
@@ -878,8 +878,8 @@
// Static methods don't override non-static so punt
return true;
}
- if ( !Dependencies::is_concrete_method(lm)
- && !Dependencies::is_concrete_method(m)
+ if ( !Dependencies::is_concrete_method(lm, k)
+ && !Dependencies::is_concrete_method(m, ctxk)
&& lm->method_holder()->is_subtype_of(m->method_holder()))
// Method m is overridden by lm, but both are non-concrete.
return true;
@@ -915,8 +915,17 @@
} else if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
- Method* m = InstanceKlass::cast(k)->find_method(_name, _signature);
- if (m == NULL || !Dependencies::is_concrete_method(m)) return false;
+ // Search class hierarchy first.
+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+ if (!Dependencies::is_concrete_method(m, k)) {
+ // Check interface defaults also, if any exist.
+ Array<Method*>* default_methods = InstanceKlass::cast(k)->default_methods();
+ if (default_methods == NULL)
+ return false;
+ m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature);
+ if (!Dependencies::is_concrete_method(m, NULL))
+ return false;
+ }
_found_methods[_num_participants] = m;
// Note: If add_participant(k) is called,
// the method m will already be memoized for it.
@@ -1209,15 +1218,17 @@
return true;
}
-bool Dependencies::is_concrete_method(Method* m) {
- // Statics are irrelevant to virtual call sites.
- if (m->is_static()) return false;
-
- // We could also return false if m does not yet appear to be
- // executed, if the VM version supports this distinction also.
- // Default methods are considered "concrete" as well.
- return !m->is_abstract() &&
- !m->is_overpass(); // error functions aren't concrete
+bool Dependencies::is_concrete_method(Method* m, Klass * k) {
+ // NULL is not a concrete method,
+ // statics are irrelevant to virtual call sites,
+ // abstract methods are not concrete,
+ // overpass (error) methods are not concrete if k is abstract
+ //
+ // note "true" is conservative answer --
+ // overpass clause is false if k == NULL, implies return true if
+ // answer depends on overpass clause.
+ return ! ( m == NULL || m -> is_static() || m -> is_abstract() ||
+ m->is_overpass() && k != NULL && k -> is_abstract() );
}
@@ -1242,16 +1253,6 @@
return true;
}
-bool Dependencies::is_concrete_method(ciMethod* m) {
- // Statics are irrelevant to virtual call sites.
- if (m->is_static()) return false;
-
- // 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();
-}
-
-
bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
return k->has_finalizable_subclass();
}
@@ -1469,7 +1470,7 @@
Klass* wit = wf.find_witness_definer(ctxk);
if (wit != NULL) return NULL; // Too many witnesses.
Method* fm = wf.found_method(0); // Will be NULL if num_parts == 0.
- if (Dependencies::is_concrete_method(m)) {
+ if (Dependencies::is_concrete_method(m, ctxk)) {
if (fm == NULL) {
// It turns out that m was always the only implementation.
fm = m;
@@ -1499,61 +1500,6 @@
return wf.find_witness_definer(ctxk, changes);
}
-// Find the set of all non-abstract methods under ctxk that match m[0].
-// (The method m[0] must be defined or inherited in ctxk.)
-// Include m itself in the set, unless it is abstract.
-// Fill the given array m[0..(mlen-1)] with this set, and return the length.
-// (The length may be zero if no concrete methods are found anywhere.)
-// If there are too many concrete methods to fit in marray, return -1.
-int Dependencies::find_exclusive_concrete_methods(Klass* ctxk,
- int mlen,
- Method* marray[]) {
- Method* m0 = marray[0];
- ClassHierarchyWalker wf(m0);
- assert(wf.check_method_context(ctxk, m0), "proper context");
- wf.record_witnesses(mlen);
- bool participants_hide_witnesses = true;
- Klass* wit = wf.find_witness_definer(ctxk);
- if (wit != NULL) return -1; // Too many witnesses.
- int num = wf.num_participants();
- assert(num <= mlen, "oob");
- // Keep track of whether m is also part of the result set.
- int mfill = 0;
- assert(marray[mfill] == m0, "sanity");
- if (Dependencies::is_concrete_method(m0))
- mfill++; // keep m0 as marray[0], the first result
- for (int i = 0; i < num; i++) {
- Method* fm = wf.found_method(i);
- if (fm == m0) continue; // Already put this guy in the list.
- if (mfill == mlen) {
- return -1; // Oops. Too many methods after all!
- }
- marray[mfill++] = fm;
- }
-#ifndef PRODUCT
- // Make sure the dependency mechanism will pass this discovery:
- if (VerifyDependencies) {
- // Turn off dependency tracing while actually testing deps.
- FlagSetting fs(TraceDependencies, false);
- switch (mfill) {
- case 1:
- guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]),
- "verify dep.");
- break;
- case 2:
- guarantee(NULL == (void *)
- check_exclusive_concrete_methods(ctxk, marray[0], marray[1]),
- "verify dep.");
- break;
- default:
- ShouldNotReachHere(); // mlen > 2 yet supported
- }
- }
-#endif //PRODUCT
- return mfill;
-}
-
-
Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) {
Klass* search_at = ctxk;
if (changes != NULL)
@@ -1561,7 +1507,6 @@
return find_finalizable_subclass(search_at);
}
-
Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity");
assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
--- a/hotspot/src/share/vm/code/dependencies.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -288,7 +288,7 @@
// In that case, there would be a middle ground between concrete
// and abstract (as defined by the Java language and VM).
static bool is_concrete_klass(Klass* k); // k is instantiable
- static bool is_concrete_method(Method* m); // m is invocable
+ static bool is_concrete_method(Method* m, Klass* k); // m is invocable
static Klass* find_finalizable_subclass(Klass* k);
// These versions of the concreteness queries work through the CI.
@@ -302,7 +302,6 @@
// not go back into the VM to get their value; they must cache the
// bit in the CI, either eagerly or lazily.)
static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable
- static bool is_concrete_method(ciMethod* m); // m appears invocable
static bool has_finalizable_subclass(ciInstanceKlass* k);
// As a general rule, it is OK to compile under the assumption that
@@ -349,7 +348,6 @@
static Klass* find_unique_concrete_subtype(Klass* ctxk);
static Method* find_unique_concrete_method(Klass* ctxk, Method* m);
static int find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]);
- static int find_exclusive_concrete_methods(Klass* ctxk, int mlen, Method* m[]);
// Create the encoding which will be stored in an nmethod.
void encode_content_bytes();
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -252,7 +252,7 @@
} else {
task = new CompileTask();
DEBUG_ONLY(_num_allocated_tasks++;)
- assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");
+ assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
task->set_next(NULL);
task->set_is_free(true);
}
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -105,7 +105,6 @@
tty->print(".");
print_symbol(method_name(), _method_mode);
if (signature() != NULL) {
- tty->print(" ");
signature()->print_symbol_on(tty);
}
}
@@ -467,43 +466,85 @@
return UnknownCommand;
}
-
static void usage() {
- tty->print_cr(" CompileCommand and the CompilerOracle allows simple control over");
- tty->print_cr(" what's allowed to be compiled. The standard supported directives");
- tty->print_cr(" are exclude and compileonly. The exclude directive stops a method");
- tty->print_cr(" from being compiled and compileonly excludes all methods except for");
- tty->print_cr(" the ones mentioned by compileonly directives. The basic form of");
- tty->print_cr(" all commands is a command name followed by the name of the method");
- tty->print_cr(" in one of two forms: the standard class file format as in");
- tty->print_cr(" class/name.methodName or the PrintCompilation format");
- tty->print_cr(" class.name::methodName. The method name can optionally be followed");
- tty->print_cr(" by a space then the signature of the method in the class file");
- tty->print_cr(" format. Otherwise the directive applies to all methods with the");
- tty->print_cr(" same name and class regardless of signature. Leading and trailing");
- tty->print_cr(" *'s in the class and/or method name allows a small amount of");
- tty->print_cr(" wildcarding. ");
+ tty->cr();
+ tty->print_cr("The CompileCommand option enables the user of the JVM to control specific");
+ tty->print_cr("behavior of the dynamic compilers. Many commands require a pattern that defines");
+ tty->print_cr("the set of methods the command shall be applied to. The CompileCommand");
+ tty->print_cr("option provides the following commands:");
tty->cr();
- tty->print_cr(" Examples:");
+ tty->print_cr(" break,<pattern> - debug breakpoint in compiler and in generated code");
+ tty->print_cr(" print,<pattern> - print assembly");
+ tty->print_cr(" exclude,<pattern> - don't compile or inline");
+ tty->print_cr(" inline,<pattern> - always inline");
+ tty->print_cr(" dontinline,<pattern> - don't inline");
+ tty->print_cr(" compileonly,<pattern> - compile only");
+ tty->print_cr(" log,<pattern> - log compilation");
+ tty->print_cr(" option,<pattern>,<option type>,<option name>,<value>");
+ tty->print_cr(" - set value of custom option");
+ tty->print_cr(" option,<pattern>,<bool option name>");
+ tty->print_cr(" - shorthand for setting boolean flag");
+ tty->print_cr(" quiet - silence the compile command output");
+ tty->print_cr(" help - print this text");
+ tty->cr();
+ tty->print_cr("The preferred format for the method matching pattern is:");
+ tty->print_cr(" package/Class.method()");
+ tty->cr();
+ tty->print_cr("For backward compatibility this form is also allowed:");
+ tty->print_cr(" package.Class::method()");
+ tty->cr();
+ tty->print_cr("The signature can be separated by an optional whitespace or comma:");
+ tty->print_cr(" package/Class.method ()");
+ tty->cr();
+ tty->print_cr("The class and method identifier can be used together with leading or");
+ tty->print_cr("trailing *'s for a small amount of wildcarding:");
+ tty->print_cr(" *ackage/Clas*.*etho*()");
+ tty->cr();
+ tty->print_cr("It is possible to use more than one CompileCommand on the command line:");
+ tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*");
tty->cr();
- tty->print_cr(" exclude java/lang/StringBuffer.append");
- tty->print_cr(" compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;");
- tty->print_cr(" exclude java/lang/String*.*");
- tty->print_cr(" exclude *.toString");
-}
-
+ tty->print_cr("The CompileCommands can be loaded from a file with the flag");
+ tty->print_cr("-XX:CompileCommandFile=<file> or be added to the file '.hotspot_compiler'");
+ tty->print_cr("Use the same format in the file as the argument to the CompileCommand flag.");
+ tty->print_cr("Add one command on each line.");
+ tty->print_cr(" exclude java/*.*");
+ tty->print_cr(" option java/*.* ReplayInline");
+ tty->cr();
+ tty->print_cr("The following commands have conflicting behavior: 'exclude', 'inline', 'dontinline',");
+ tty->print_cr("and 'compileonly'. There is no priority of commands. Applying (a subset of) these");
+ tty->print_cr("commands to the same method results in undefined behavior.");
+ tty->cr();
+};
-// The characters allowed in a class or method name. All characters > 0x7f
-// are allowed in order to handle obfuscated class files (e.g. Volano)
-#define RANGEBASE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_<>" \
- "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
- "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \
- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+// The JVM specification defines the allowed characters.
+// Tokens that are disallowed by the JVM specification can have
+// a meaning to the parser so we need to include them here.
+// The parser does not enforce all rules of the JVMS - a successful parse
+// does not mean that it is an allowed name. Illegal names will
+// be ignored since they never can match a class or method.
+//
+// '\0' and 0xf0-0xff are disallowed in constant string values
+// 0x20 ' ', 0x09 '\t' and, 0x2c ',' are used in the matching
+// 0x5b '[' and 0x5d ']' can not be used because of the matcher
+// 0x28 '(' and 0x29 ')' are used for the signature
+// 0x2e '.' is always replaced before the matching
+// 0x2f '/' is only used in the class name as package separator
+
+#define RANGEBASE "\x1\x2\x3\x4\x5\x6\x7\x8\xa\xb\xc\xd\xe\xf" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x21\x22\x23\x24\x25\x26\x27\x2a\x2b\x2c\x2d" \
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" \
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5c\x5e\x5f" \
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" \
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" \
+ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
#define RANGE0 "[*" RANGEBASE "]"
#define RANGESLASH "[*" RANGEBASE "/]"
@@ -681,8 +722,9 @@
if (command == UnknownCommand) {
ttyLocker ttyl;
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: unrecognized command");
tty->print_cr(" \"%s\"", original_line);
+ CompilerOracle::print_tip();
return;
}
@@ -712,9 +754,17 @@
Symbol* signature = NULL;
line += bytes_read;
+
+ // Skip any leading spaces before signature
+ int whitespace_read = 0;
+ sscanf(line, "%*[ \t]%n", &whitespace_read);
+ if (whitespace_read > 0) {
+ line += whitespace_read;
+ }
+
// there might be a signature following the method.
// signatures always begin with ( so match that by hand
- if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
+ if (1 == sscanf(line, "(%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
sig[0] = '(';
line += bytes_read;
signature = SymbolTable::new_symbol(sig, CHECK);
@@ -740,7 +790,7 @@
if (match != NULL && !_quiet) {
// Print out the last match added
ttyLocker ttyl;
- tty->print("CompilerOracle: %s ", command_names[command]);
+ tty->print("CompileCommand: %s ", command_names[command]);
match->print();
}
line += bytes_read;
@@ -775,26 +825,36 @@
ttyLocker ttyl;
if (error_msg != NULL) {
// an error has happened
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: An error occured during parsing");
tty->print_cr(" \"%s\"", original_line);
if (error_msg != NULL) {
tty->print_cr("%s", error_msg);
}
+ CompilerOracle::print_tip();
+
} else {
// check for remaining characters
bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (line[bytes_read] != '\0') {
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: Bad pattern");
tty->print_cr(" \"%s\"", original_line);
tty->print_cr(" Unrecognized text %s after command ", line);
+ CompilerOracle::print_tip();
} else if (match != NULL && !_quiet) {
- tty->print("CompilerOracle: %s ", command_names[command]);
+ tty->print("CompileCommand: %s ", command_names[command]);
match->print();
}
}
}
+void CompilerOracle::print_tip() {
+ tty->cr();
+ tty->print_cr("Usage: '-XX:CompileCommand=command,\"package/Class.method()\"'");
+ tty->print_cr("Use: '-XX:CompileCommand=help' for more information.");
+ tty->cr();
+}
+
static const char* default_cc_file = ".hotspot_compiler";
static const char* cc_file() {
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -34,6 +34,7 @@
class CompilerOracle : AllStatic {
private:
static bool _quiet;
+ static void print_tip();
public:
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -645,7 +645,7 @@
// Support for parallelizing survivor space rescan
if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
const size_t max_plab_samples =
- ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize;
+ ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
_survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
_survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
@@ -703,6 +703,12 @@
_inter_sweep_timer.start(); // start of time
}
+size_t CMSCollector::plab_sample_minimum_size() {
+ // The default value of MinTLABSize is 2k, but there is
+ // no way to get the default value if the flag has been overridden.
+ return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
+}
+
const char* ConcurrentMarkSweepGeneration::name() const {
return "concurrent mark-sweep generation";
}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -737,6 +737,10 @@
size_t* _cursor;
ChunkArray* _survivor_plab_array;
+ // A bounded minimum size of PLABs, should not return too small values since
+ // this will affect the size of the data structures used for parallel young gen rescan
+ size_t plab_sample_minimum_size();
+
// Support for marking stack overflow handling
bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
bool par_take_from_overflow_list(size_t num,
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1910,7 +1910,6 @@
}
void work(uint worker_id) {
- double start = os::elapsedTime();
FreeRegionList local_cleanup_list("Local Cleanup List");
HRRSCleanupTask hrrs_cleanup_task;
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -47,6 +47,13 @@
// active field set to true.
PtrQueue(qset_, perm, true /* active */) { }
+ // Flush before destroying; queue may be used to capture pending work while
+ // doing something else, with auto-flush on completion.
+ ~DirtyCardQueue() { if (!is_permanent()) flush(); }
+
+ // Process queue entries and release resources.
+ void flush() { flush_impl(); }
+
// Apply the closure to all elements, and reset the index to make the
// buffer empty. If a closure application returns "false", return
// "false" immediately, halting the iteration. If "consume" is true,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1229,7 +1229,6 @@
TraceCollectorStats tcs(g1mm()->full_collection_counters());
TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
- double start = os::elapsedTime();
g1_policy()->record_full_collection_start();
// Note: When we have a more flexible GC logging framework that
@@ -1436,7 +1435,6 @@
_allocator->init_mutator_alloc_region();
- double end = os::elapsedTime();
g1_policy()->record_full_collection_end();
if (G1Log::fine()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -56,7 +56,6 @@
class GenerationSpec;
class OopsInHeapRegionClosure;
class G1KlassScanClosure;
-class G1ScanHeapEvacClosure;
class ObjectClosure;
class SpaceClosure;
class CompactibleSpaceClosure;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -153,14 +153,6 @@
_inc_cset_predicted_elapsed_time_ms(0.0),
_inc_cset_predicted_elapsed_time_ms_diffs(0.0),
-#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
-#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
-#endif // _MSC_VER
-
- _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived",
- G1YoungSurvRateNumRegionsSummary)),
- _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor",
- G1YoungSurvRateNumRegionsSummary)),
// add here any more surv rate groups
_recorded_survivor_regions(0),
_recorded_survivor_head(NULL),
@@ -169,6 +161,22 @@
_gc_overhead_perc(0.0) {
+ uintx confidence_perc = G1ConfidencePercent;
+ // Put an artificial ceiling on this so that it's not set to a silly value.
+ if (confidence_perc > 100) {
+ confidence_perc = 100;
+ warning("G1ConfidencePercent is set to a value that is too large, "
+ "it's been updated to %u", confidence_perc);
+ }
+ // '_sigma' must be initialized before the SurvRateGroups below because they
+ // indirecty access '_sigma' trough the 'this' pointer in their constructor.
+ _sigma = (double) confidence_perc / 100.0;
+
+ _short_lived_surv_rate_group =
+ new SurvRateGroup(this, "Short Lived", G1YoungSurvRateNumRegionsSummary);
+ _survivor_surv_rate_group =
+ new SurvRateGroup(this, "Survivor", G1YoungSurvRateNumRegionsSummary);
+
// Set up the region size and associated fields. Given that the
// policy is created before the heap, we have to set this up here,
// so it's done as soon as possible.
@@ -283,15 +291,6 @@
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
- uintx confidence_perc = G1ConfidencePercent;
- // Put an artificial ceiling on this so that it's not set to a silly value.
- if (confidence_perc > 100) {
- confidence_perc = 100;
- warning("G1ConfidencePercent is set to a value that is too large, "
- "it's been updated to %u", confidence_perc);
- }
- _sigma = (double) confidence_perc / 100.0;
-
// start conservatively (around 50ms is about right)
_concurrent_mark_remark_times_ms->add(0.05);
_concurrent_mark_cleanup_times_ms->add(0.20);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -46,9 +46,6 @@
class G1PrepareCompactClosure;
class G1MarkSweep : AllStatic {
- friend class VM_G1MarkSweep;
- friend class Scavenge;
-
public:
static void invoke_at_safepoint(ReferenceProcessor* rp,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -45,7 +45,8 @@
#include "utilities/bitMap.inline.hpp"
G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL),
- _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) {
+ _high_boundary(NULL), _committed(), _page_size(0), _special(false),
+ _dirty(), _executable(false) {
}
bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
@@ -66,6 +67,9 @@
assert(_committed.size() == 0, "virtual space initialized more than once");
uintx size_in_bits = rs.size() / page_size;
_committed.resize(size_in_bits, /* in_resource_area */ false);
+ if (_special) {
+ _dirty.resize(size_in_bits, /* in_resource_area */ false);
+ }
return true;
}
@@ -84,6 +88,7 @@
_executable = false;
_page_size = 0;
_committed.resize(0, false);
+ _dirty.resize(0, false);
}
size_t G1PageBasedVirtualSpace::committed_size() const {
@@ -120,34 +125,43 @@
return num * _page_size;
}
-MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
+bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
// We need to make sure to commit all pages covered by the given area.
guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
- if (!_special) {
+ bool zero_filled = true;
+ uintptr_t end = start + size_in_pages;
+
+ if (_special) {
+ // Check for dirty pages and update zero_filled if any found.
+ if (_dirty.get_next_one_offset(start,end) < end) {
+ zero_filled = false;
+ _dirty.clear_range(start, end);
+ }
+ } else {
os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable,
err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
}
- _committed.set_range(start, start + size_in_pages);
+ _committed.set_range(start, end);
- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
if (AlwaysPreTouch) {
- os::pretouch_memory((char*)result.start(), (char*)result.end());
+ os::pretouch_memory(page_start(start), page_start(end));
}
- return result;
+ return zero_filled;
}
-MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
+void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
guarantee(is_area_committed(start, size_in_pages), "checking");
- if (!_special) {
+ if (_special) {
+ // Mark that memory is dirty. If committed again the memory might
+ // need to be cleared explicitly.
+ _dirty.set_range(start, start + size_in_pages);
+ } else {
os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
}
_committed.clear_range(start, start + size_in_pages);
-
- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
- return result;
}
bool G1PageBasedVirtualSpace::contains(const void* p) const {
@@ -157,7 +171,7 @@
#ifndef PRODUCT
void G1PageBasedVirtualSpace::print_on(outputStream* out) {
out->print ("Virtual space:");
- if (special()) out->print(" (pinned in memory)");
+ if (_special) out->print(" (pinned in memory)");
out->cr();
out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -49,6 +49,12 @@
// Bitmap used for verification of commit/uncommit operations.
BitMap _committed;
+ // Bitmap used to keep track of which pages are dirty or not for _special
+ // spaces. This is needed because for those spaces the underlying memory
+ // will only be zero filled the first time it is committed. Calls to commit
+ // will use this bitmap and return whether or not the memory is zero filled.
+ BitMap _dirty;
+
// Indicates that the entire space has been committed and pinned in memory,
// os::commit_memory() or os::uncommit_memory() have no function.
bool _special;
@@ -71,12 +77,11 @@
public:
// Commit the given area of pages starting at start being size_in_pages large.
- MemRegion commit(uintptr_t start, size_t size_in_pages);
+ // Returns true if the given area is zero filled upon completion.
+ bool commit(uintptr_t start, size_t size_in_pages);
// Uncommit the given area of pages starting at start being size_in_pages large.
- MemRegion uncommit(uintptr_t start, size_t size_in_pages);
-
- bool special() const { return _special; }
+ void uncommit(uintptr_t start, size_t size_in_pages);
// Initialization
G1PageBasedVirtualSpace();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -67,9 +67,9 @@
}
virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
- _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
+ bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
_commit_map.set_range(start_idx, start_idx + num_regions);
- fire_on_commit(start_idx, num_regions, true);
+ fire_on_commit(start_idx, num_regions, zero_filled);
}
virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
@@ -117,8 +117,7 @@
uint old_refcount = _refcounts.get_by_index(idx);
bool zero_filled = false;
if (old_refcount == 0) {
- _storage.commit(idx, 1);
- zero_filled = true;
+ zero_filled = _storage.commit(idx, 1);
}
_refcounts.set_by_index(idx, old_refcount + 1);
_commit_map.set_bit(i);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -31,7 +31,6 @@
// collection set.
class G1CollectedHeap;
-class CardTableModRefBarrierSet;
class ConcurrentG1Refine;
class G1ParPushHeapRSClosure;
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -31,11 +31,15 @@
#include "runtime/thread.inline.hpp"
PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
- _qset(qset), _buf(NULL), _index(0), _active(active),
+ _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active),
_perm(perm), _lock(NULL)
{}
-void PtrQueue::flush() {
+PtrQueue::~PtrQueue() {
+ assert(_perm || (_buf == NULL), "queue must be flushed before delete");
+}
+
+void PtrQueue::flush_impl() {
if (!_perm && _buf != NULL) {
if (_index == _sz) {
// No work to do.
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -65,15 +65,18 @@
Mutex* _lock;
PtrQueueSet* qset() { return _qset; }
+ bool is_permanent() const { return _perm; }
+
+ // Process queue entries and release resources, if not permanent.
+ void flush_impl();
public:
// Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet.
PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
- // Release any contained resources.
- virtual void flush();
- // Calls flush() when destroyed.
- ~PtrQueue() { flush(); }
+
+ // Requires queue flushed or permanent.
+ ~PtrQueue();
// Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; }
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -39,7 +39,7 @@
// first before we flush it, otherwise we might end up with an
// enqueued buffer with refs into the CSet which breaks our invariants.
filter();
- PtrQueue::flush();
+ flush_impl();
}
// This method removes entries from an SATB buffer that will not be
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -60,9 +60,8 @@
// field to true. This is done in JavaThread::initialize_queues().
PtrQueue(qset, perm, false /* active */) { }
- // Overrides PtrQueue::flush() so that it can filter the buffer
- // before it is flushed.
- virtual void flush();
+ // Process queue entries and free resources.
+ void flush();
// Overrides PtrQueue::should_enqueue_buffer(). See the method's
// definition for more information.
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -63,7 +63,8 @@
virtual ~ParGCAllocBuffer() {}
static const size_t min_size() {
- return ThreadLocalAllocBuffer::min_size();
+ // Make sure that we return something that is larger than AlignmentReserve
+ return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
}
static const size_t max_size() {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -320,7 +320,7 @@
// First check in default method array
if (!resolved_method->is_abstract() &&
(InstanceKlass::cast(klass())->default_methods() != NULL)) {
- int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false);
+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false, false);
if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
}
--- a/hotspot/src/share/vm/memory/heap.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/heap.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -279,10 +279,12 @@
return sizeof(HeapBlock) & (_segment_size - 1);
}
-// Finds the next free heapblock. If the current one is free, that it returned
-void* CodeHeap::next_free(HeapBlock* b) const {
- // Since free blocks are merged, there is max. on free block
- // between two used ones
+// Returns the current block if available and used.
+// If not, it returns the subsequent block (if available), NULL otherwise.
+// Free blocks are merged, therefore there is at most one free block
+// between two used ones. As a result, the subsequent block (if available) is
+// guaranteed to be used.
+void* CodeHeap::next_used(HeapBlock* b) const {
if (b != NULL && b->free()) b = next_block(b);
assert(b == NULL || !b->free(), "must be in use or at end of heap");
return (b == NULL) ? NULL : b->allocated_space();
--- a/hotspot/src/share/vm/memory/heap.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/heap.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -123,7 +123,7 @@
FreeBlock* search_freelist(size_t length);
// Iteration helpers
- void* next_free(HeapBlock* b) const;
+ void* next_used(HeapBlock* b) const;
HeapBlock* first_block() const;
HeapBlock* next_block(HeapBlock* b) const;
HeapBlock* block_start(void* p) const;
@@ -158,9 +158,9 @@
int freelist_length() const { return _freelist_length; } // number of elements in the freelist
// returns the first block or NULL
- void* first() const { return next_free(first_block()); }
+ void* first() const { return next_used(first_block()); }
// returns the next block given a block p or NULL
- void* next(void* p) const { return next_free(next_block(block_start(p))); }
+ void* next(void* p) const { return next_used(next_block(block_start(p))); }
// Statistics
size_t capacity() const;
--- a/hotspot/src/share/vm/memory/metaspace.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -3170,7 +3170,9 @@
}
// the min_misc_data_size and min_misc_code_size estimates are based on
- // MetaspaceShared::generate_vtable_methods()
+ // MetaspaceShared::generate_vtable_methods().
+ // The minimum size only accounts for the vtable methods. Any size less than the
+ // minimum required size would cause vm crash when allocating the vtable methods.
uint min_misc_data_size = align_size_up(
MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment);
@@ -3336,6 +3338,10 @@
Metachunk* new_chunk = get_initialization_chunk(NonClassType,
word_size,
vsm()->medium_chunk_bunch());
+ // For dumping shared archive, report error if allocation has failed.
+ if (DumpSharedSpaces && new_chunk == NULL) {
+ report_insufficient_metaspace(MetaspaceAux::committed_bytes() + word_size * BytesPerWord);
+ }
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
if (new_chunk != NULL) {
// Add to this manager's list of chunks in use and current_chunk().
@@ -3349,6 +3355,11 @@
class_vsm()->medium_chunk_bunch());
if (class_chunk != NULL) {
class_vsm()->add_chunk(class_chunk, true);
+ } else {
+ // For dumping shared archive, report error if allocation has failed.
+ if (DumpSharedSpaces) {
+ report_insufficient_metaspace(MetaspaceAux::committed_bytes() + class_word_size * BytesPerWord);
+ }
}
}
@@ -3829,11 +3840,13 @@
assert(cm.sum_free_chunks() == 2*MediumChunk, "sizes should add up");
}
- { // 4 pages of VSN is committed, some is used by chunks
+ const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
+ // This doesn't work for systems with vm_page_size >= 16K.
+ if (page_chunks < MediumChunk) {
+ // 4 pages of VSN is committed, some is used by chunks
ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
VirtualSpaceNode vsn(vsn_test_size_bytes);
- const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
- assert(page_chunks < MediumChunk, "Test expects medium chunks to be at least 4*page_size");
+
vsn.initialize();
vsn.expand_by(page_chunks, page_chunks);
vsn.get_chunk_vs(SmallChunk);
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -118,6 +118,7 @@
_discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q];
_discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q];
_discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
+ _discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q];
// Initialize all entries to NULL
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
@@ -246,6 +247,13 @@
phantom_count =
process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
is_alive, keep_alive, complete_gc, task_executor);
+
+ // Process cleaners, but include them in phantom statistics. We expect
+ // Cleaner references to be temporary, and don't want to deal with
+ // possible incompatibilities arising from making it more visible.
+ phantom_count +=
+ process_discovered_reflist(_discoveredCleanerRefs, NULL, false,
+ is_alive, keep_alive, complete_gc, task_executor);
}
// Weak global JNI references. It would make more sense (semantically) to
@@ -885,6 +893,7 @@
balance_queues(_discoveredWeakRefs);
balance_queues(_discoveredFinalRefs);
balance_queues(_discoveredPhantomRefs);
+ balance_queues(_discoveredCleanerRefs);
}
size_t
@@ -998,6 +1007,9 @@
case REF_PHANTOM:
list = &_discoveredPhantomRefs[id];
break;
+ case REF_CLEANER:
+ list = &_discoveredCleanerRefs[id];
+ break;
case REF_NONE:
// we should not reach here if we are an InstanceRefKlass
default:
@@ -1263,6 +1275,17 @@
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
+
+ // Cleaner references. Included in timing for phantom references. We
+ // expect Cleaner references to be temporary, and don't want to deal with
+ // possible incompatibilities arising from making it more visible.
+ for (uint i = 0; i < _max_num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
+ preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive,
+ keep_alive, complete_gc, yield);
+ }
}
}
@@ -1331,6 +1354,7 @@
case 1: return "WeakRef";
case 2: return "FinalRef";
case 3: return "PhantomRef";
+ case 4: return "CleanerRef";
}
ShouldNotReachHere();
return NULL;
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -264,9 +264,10 @@
DiscoveredList* _discoveredWeakRefs;
DiscoveredList* _discoveredFinalRefs;
DiscoveredList* _discoveredPhantomRefs;
+ DiscoveredList* _discoveredCleanerRefs;
public:
- static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); }
+ static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); }
uint num_q() { return _num_q; }
uint max_num_q() { return _max_num_q; }
--- a/hotspot/src/share/vm/memory/referenceType.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceType.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -35,7 +35,8 @@
REF_SOFT, // Subclass of java/lang/ref/SoftReference
REF_WEAK, // Subclass of java/lang/ref/WeakReference
REF_FINAL, // Subclass of java/lang/ref/FinalReference
- REF_PHANTOM // Subclass of java/lang/ref/PhantomReference
+ REF_PHANTOM, // Subclass of java/lang/ref/PhantomReference
+ REF_CLEANER // Subclass of sun/misc/Cleaner
};
#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -235,22 +235,19 @@
}
size_t ThreadLocalAllocBuffer::initial_desired_size() {
- size_t init_sz;
+ size_t init_sz = 0;
if (TLABSize > 0) {
- init_sz = MIN2(TLABSize / HeapWordSize, max_size());
- } else if (global_stats() == NULL) {
- // Startup issue - main thread initialized before heap initialized.
- init_sz = min_size();
- } else {
+ init_sz = TLABSize / HeapWordSize;
+ } else if (global_stats() != NULL) {
// Initial size is a function of the average number of allocating threads.
unsigned nof_threads = global_stats()->allocating_threads_avg();
init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
(nof_threads * target_refills());
init_sz = align_object_size(init_sz);
- init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
}
+ init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
return init_sz;
}
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -106,7 +106,7 @@
// do nothing. tlabs must be inited by initialize() calls
}
- static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); }
+ static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); }
static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; }
static void set_max_size(size_t max_size) { _max_size = max_size; }
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1420,32 +1420,41 @@
}
Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const {
- return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass);
+ return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false);
}
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
Method* InstanceKlass::find_instance_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- Method* meth = InstanceKlass::find_method(methods, name, signature);
- if (meth != NULL && meth->is_static()) {
- meth = NULL;
- }
+ Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true);
return meth;
}
+// find_instance_method looks up the name/signature in the local methods array
+// and skips over static methods
+Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
+ return InstanceKlass::find_instance_method(methods(), name, signature);
+}
+
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- return InstanceKlass::find_method_impl(methods, name, signature, false);
+ return InstanceKlass::find_method_impl(methods, name, signature, false, false);
}
Method* InstanceKlass::find_method_impl(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
- int hit = find_method_index(methods, name, signature, skipping_overpass);
+ Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+ int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static);
return hit >= 0 ? methods->at(hit): NULL;
}
+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+ return (m->signature() == signature) &&
+ (!skipping_overpass || !m->is_overpass()) &&
+ (!skipping_static || !m->is_static());
+}
+
// Used directly for default_methods to find the index into the
// default_vtable_indices, and indirectly by find_method
// find_method_index looks in the local methods array to return the index
@@ -1454,13 +1463,14 @@
// is important during method resolution to prefer a static method, for example,
// over an overpass method.
int InstanceKlass::find_method_index(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
+ Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
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, ignoring overpasses if requested.
- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit;
// search downwards through overloaded methods
int i;
@@ -1468,18 +1478,18 @@
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
}
// 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) && (!skipping_overpass || !m->is_overpass())) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
}
// not found
#ifdef ASSERT
- int index = skipping_overpass ? -1 : linear_search(methods, name, signature);
+ int index = skipping_overpass || skipping_static ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -490,10 +490,16 @@
// find a local method (returns NULL if not found)
Method* find_method(Symbol* name, Symbol* signature) const;
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+
+ // find a local method, but skip static methods
+ Method* find_instance_method(Symbol* name, Symbol* signature);
static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+ // true if method matches signature and conforms to skipping_X conditions.
+ static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
+
// find a local method index in default_methods (returns -1 if not found)
- static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+ static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// lookup operation (returns NULL if not found)
Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
@@ -1053,7 +1059,7 @@
// find a local method (returns NULL if not found)
Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const;
- static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+ static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// Free CHeap allocated fields.
void release_C_heap_structures();
--- a/hotspot/src/share/vm/opto/cfgnode.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/opto/cfgnode.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -361,22 +361,36 @@
#endif
};
-class IfTrueNode : public CProjNode {
+class IfProjNode : public CProjNode {
public:
- IfTrueNode( IfNode *ifnode ) : CProjNode(ifnode,1) {
+ IfProjNode(IfNode *ifnode, uint idx) : CProjNode(ifnode,idx) {}
+ virtual Node *Identity(PhaseTransform *phase);
+
+protected:
+ // Type of If input when this branch is always taken
+ virtual bool always_taken(const TypeTuple* t) const = 0;
+};
+
+class IfTrueNode : public IfProjNode {
+public:
+ IfTrueNode( IfNode *ifnode ) : IfProjNode(ifnode,1) {
init_class_id(Class_IfTrue);
}
virtual int Opcode() const;
- virtual Node *Identity( PhaseTransform *phase );
+
+protected:
+ virtual bool always_taken(const TypeTuple* t) const { return t == TypeTuple::IFTRUE; }
};
-class IfFalseNode : public CProjNode {
+class IfFalseNode : public IfProjNode {
public:
- IfFalseNode( IfNode *ifnode ) : CProjNode(ifnode,0) {
+ IfFalseNode( IfNode *ifnode ) : IfProjNode(ifnode,0) {
init_class_id(Class_IfFalse);
}
virtual int Opcode() const;
- virtual Node *Identity( PhaseTransform *phase );
+
+protected:
+ virtual bool always_taken(const TypeTuple* t) const { return t == TypeTuple::IFFALSE; }
};
--- a/hotspot/src/share/vm/opto/ifnode.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1122,12 +1122,21 @@
//------------------------------Identity---------------------------------------
// If the test is constant & we match, then we are the input Control
-Node *IfTrueNode::Identity( PhaseTransform *phase ) {
+Node *IfProjNode::Identity(PhaseTransform *phase) {
// Can only optimize if cannot go the other way
const TypeTuple *t = phase->type(in(0))->is_tuple();
- return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFTRUE )
- ? in(0)->in(0) // IfNode control
- : this; // no progress
+ if (t == TypeTuple::IFNEITHER ||
+ // kill dead branch first otherwise the IfNode's control will
+ // have 2 control uses (the IfNode that doesn't go away because
+ // it still has uses and this branch of the
+ // If). Node::has_special_unique_user() will cause this node to
+ // be reprocessed once the dead branch is killed.
+ (always_taken(t) && in(0)->outcnt() == 1)) {
+ // IfNode control
+ return in(0)->in(0);
+ }
+ // no progress
+ return this;
}
//------------------------------dump_spec--------------------------------------
@@ -1195,13 +1204,3 @@
// Progress
return iff;
}
-
-//------------------------------Identity---------------------------------------
-// If the test is constant & we match, then we are the input Control
-Node *IfFalseNode::Identity( PhaseTransform *phase ) {
- // Can only optimize if cannot go the other way
- const TypeTuple *t = phase->type(in(0))->is_tuple();
- return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFFALSE )
- ? in(0)->in(0) // IfNode control
- : this; // no progress
-}
--- a/hotspot/src/share/vm/opto/node.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/opto/node.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1080,18 +1080,21 @@
assert(outcnt() == 1, "match only for unique out");
Node* n = unique_out();
int op = Opcode();
- if( this->is_Store() ) {
+ if (this->is_Store()) {
// Condition for back-to-back stores folding.
return n->Opcode() == op && n->in(MemNode::Memory) == this;
} else if (this->is_Load()) {
// Condition for removing an unused LoadNode from the MemBarAcquire precedence input
return n->Opcode() == Op_MemBarAcquire;
- } else if( op == Op_AddL ) {
+ } else if (op == Op_AddL) {
// Condition for convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y))
return n->Opcode() == Op_ConvL2I && n->in(1) == this;
- } else if( op == Op_SubI || op == Op_SubL ) {
+ } else if (op == Op_SubI || op == Op_SubL) {
// Condition for subI(x,subI(y,z)) ==> subI(addI(x,z),y)
return n->Opcode() == op && n->in(2) == this;
+ } else if (is_If() && (n->is_IfFalse() || n->is_IfTrue())) {
+ // See IfProjNode::Identity()
+ return true;
}
return false;
};
--- a/hotspot/src/share/vm/runtime/globals.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -2951,10 +2951,6 @@
develop(intx, MallocCatchPtr, -1, \
"Hit breakpoint when mallocing/freeing this pointer") \
\
- notproduct(intx, AssertRepeat, 1, \
- "number of times to evaluate expression in assert " \
- "(to estimate overhead); only works with -DUSE_REPEATED_ASSERTS") \
- \
notproduct(ccstrlist, SuppressErrorAt, "", \
"List of assertions (file:line) to muzzle") \
\
--- a/hotspot/src/share/vm/runtime/os.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -547,20 +547,16 @@
// This function supports testing of the malloc out of memory
// condition without really running the system out of memory.
//
-static u_char* testMalloc(size_t alloc_size) {
- assert(MallocMaxTestWords > 0, "sanity check");
-
- if ((cur_malloc_words + (alloc_size / BytesPerWord)) > MallocMaxTestWords) {
- return NULL;
- }
+static bool has_reached_max_malloc_test_peak(size_t alloc_size) {
+ if (MallocMaxTestWords > 0) {
+ jint words = (jint)(alloc_size / BytesPerWord);
- u_char* ptr = (u_char*)::malloc(alloc_size);
-
- if (ptr != NULL) {
- Atomic::add(((jint) (alloc_size / BytesPerWord)),
- (volatile jint *) &cur_malloc_words);
+ if ((cur_malloc_words + words) > MallocMaxTestWords) {
+ return true;
+ }
+ Atomic::add(words, (volatile jint *)&cur_malloc_words);
}
- return ptr;
+ return false;
}
void* os::malloc(size_t size, MEMFLAGS flags) {
@@ -608,12 +604,13 @@
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
+ // For the test flag -XX:MallocMaxTestWords
+ if (has_reached_max_malloc_test_peak(size)) {
+ return NULL;
+ }
+
u_char* ptr;
- if (MallocMaxTestWords > 0) {
- ptr = testMalloc(alloc_size);
- } else {
- ptr = (u_char*)::malloc(alloc_size);
- }
+ ptr = (u_char*)::malloc(alloc_size);
#ifdef ASSERT
if (ptr == NULL) {
@@ -642,6 +639,11 @@
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
+ // For the test flag -XX:MallocMaxTestWords
+ if (has_reached_max_malloc_test_peak(size)) {
+ return NULL;
+ }
+
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -661,6 +661,7 @@
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
--- a/hotspot/src/share/vm/shark/llvmHeaders.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/shark/llvmHeaders.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -87,30 +87,7 @@
#undef assert
#endif
-// from hotspot/src/share/vm/utilities/debug.hpp
-#ifdef ASSERT
-#ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg) \
-do { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
-} while (0)
-#else // #ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg)
-do { \
- for (int __i = 0; __i < AssertRepeat; __i++) { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
- } \
-} while (0)
-#endif // #ifndef USE_REPEATED_ASSERTS
-#else
- #define assert(p, msg)
-#endif
+#define assert(p, msg) vmassert(p, msg)
#ifdef DEBUG
#undef DEBUG
--- a/hotspot/src/share/vm/utilities/debug.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -273,6 +273,14 @@
exit(2);
}
+void report_insufficient_metaspace(size_t required_size) {
+ warning("\nThe MaxMetaspaceSize of " UINTX_FORMAT " bytes is not large enough.\n"
+ "Either don't specify the -XX:MaxMetaspaceSize=<size>\n"
+ "or increase the size to at least " SIZE_FORMAT ".\n",
+ MaxMetaspaceSize, required_size);
+ exit(2);
+}
+
void report_java_out_of_memory(const char* message) {
static jint out_of_memory_reported = 0;
@@ -326,9 +334,9 @@
// Keep this in sync with test/runtime/6888954/vmerrors.sh.
switch (n) {
- case 1: assert(str == NULL, "expected null");
- case 2: assert(num == 1023 && *str == 'X',
- err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
+ case 1: vmassert(str == NULL, "expected null");
+ case 2: vmassert(num == 1023 && *str == 'X',
+ err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
case 3: guarantee(str == NULL, "expected null");
case 4: guarantee(num == 1023 && *str == 'X',
err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
--- a/hotspot/src/share/vm/utilities/debug.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/debug.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -105,58 +105,42 @@
va_end(argp);
}
-// Used to format messages for assert(), guarantee(), fatal(), etc.
+// Used to format messages for vmassert(), guarantee(), fatal(), etc.
typedef FormatBuffer<> err_msg;
typedef FormatBufferResource err_msg_res;
// assertions
-#ifdef ASSERT
-#ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg) \
+#ifndef ASSERT
+#define vmassert(p, msg)
+#else
+// Note: message says "assert" rather than "vmassert" for backward
+// compatibility with tools that parse/match the message text.
+#define vmassert(p, msg) \
do { \
if (!(p)) { \
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
BREAKPOINT; \
} \
} while (0)
-#else // #ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg)
-do { \
- for (int __i = 0; __i < AssertRepeat; __i++) { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
- } \
-} while (0)
-#endif // #ifndef USE_REPEATED_ASSERTS
+#endif
-// This version of assert is for use with checking return status from
+// For backward compatibility.
+#define assert(p, msg) vmassert(p, msg)
+
+// This version of vmassert is for use with checking return status from
// library calls that return actual error values eg. EINVAL,
// ENOMEM etc, rather than returning -1 and setting errno.
// When the status is not what is expected it is very useful to know
// what status was actually returned, so we pass the status variable as
// an extra arg and use strerror to convert it to a meaningful string
// like "Invalid argument", "out of memory" etc
-#define assert_status(p, status, msg) \
-do { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", \
- err_msg("error %s(%d) %s", strerror(status), \
- status, msg)); \
- BREAKPOINT; \
- } \
-} while (0)
+#define vmassert_status(p, status, msg) \
+ vmassert(p, err_msg("error %s(%d), %s", strerror(status), status, msg))
-// Do not assert this condition if there's already another error reported.
-#define assert_if_no_error(cond,msg) assert((cond) || is_error_reported(), msg)
-#else // #ifdef ASSERT
- #define assert(p,msg)
- #define assert_status(p,status,msg)
- #define assert_if_no_error(cond,msg)
-#endif // #ifdef ASSERT
+// For backward compatibility.
+#define assert_status(p, status, msg) vmassert_status(p, status, msg)
-// guarantee is like assert except it's always executed -- use it for
+// guarantee is like vmassert except it's always executed -- use it for
// cheap tests that catch errors that would otherwise be hard to find.
// guarantee is also used for Verify options.
#define guarantee(p, msg) \
@@ -225,21 +209,22 @@
void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2);
-#ifdef ASSERT
-// Compile-time asserts.
-template <bool> struct StaticAssert;
-template <> struct StaticAssert<true> {};
+// Compile-time asserts. Cond must be a compile-time constant expression that
+// is convertible to bool. STATIC_ASSERT() can be used anywhere a declaration
+// may appear.
+//
+// Implementation Note: STATIC_ASSERT_FAILURE<true> provides a value member
+// rather than type member that could be used directly in the typedef, because
+// a type member would require conditional use of "typename", depending on
+// whether Cond is dependent or not. The use of a value member leads to the
+// use of an array type.
-// Only StaticAssert<true> is defined, so if cond evaluates to false we get
-// a compile time exception when trying to use StaticAssert<false>.
-#define STATIC_ASSERT(cond) \
- do { \
- StaticAssert<(cond)> DUMMY_STATIC_ASSERT; \
- (void)DUMMY_STATIC_ASSERT; /* ignore */ \
- } while (false)
-#else
-#define STATIC_ASSERT(cond)
-#endif
+template<bool x> struct STATIC_ASSERT_FAILURE;
+template<> struct STATIC_ASSERT_FAILURE<true> { enum { value = 1 }; };
+
+#define STATIC_ASSERT(Cond) \
+ typedef char STATIC_ASSERT_FAILURE_ ## __LINE__ [ \
+ STATIC_ASSERT_FAILURE< (Cond) >::value ]
// out of shared space reporting
enum SharedSpaceType {
@@ -251,6 +236,8 @@
void report_out_of_shared_space(SharedSpaceType space_type);
+void report_insufficient_metaspace(size_t required_size);
+
// out of memory reporting
void report_java_out_of_memory(const char* message);
@@ -258,7 +245,7 @@
bool is_error_reported();
void set_error_reported();
-/* Test assert(), fatal(), guarantee(), etc. */
+/* Test vmassert(), fatal(), guarantee(), etc. */
NOT_PRODUCT(void test_error_handler();)
void pd_ps(frame f);
--- a/hotspot/src/share/vm/utilities/defaultStream.hpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/defaultStream.hpp Wed Jul 05 20:15:59 2017 +0200
@@ -41,6 +41,8 @@
void init();
void init_log();
+ fileStream* open_file(const char* log_name);
+ void start_log();
void finish_log();
void finish_log_on_error(char *buf, int buflen);
public:
--- a/hotspot/src/share/vm/utilities/ostream.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/ostream.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -367,7 +367,6 @@
#define EXTRACHARLEN 32
#define CURRENTAPPX ".current"
-#define FILENAMEBUFLEN 1024
// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
char* get_datetime_string(char *buf, size_t len) {
os::local_time_string(buf, len);
@@ -401,7 +400,6 @@
buffer_length = strlen(log_name) + 1;
}
- // const char* star = strchr(basename, '*');
const char* pts = strstr(basename, "%p");
int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
@@ -416,6 +414,11 @@
buffer_length += strlen(tms);
}
+ // File name is too long.
+ if (buffer_length > JVM_MAXPATHLEN) {
+ return NULL;
+ }
+
// Create big enough buffer.
char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
@@ -489,46 +492,88 @@
void test_loggc_filename() {
int pid;
char tms[32];
- char i_result[FILENAMEBUFLEN];
+ char i_result[JVM_MAXPATHLEN];
const char* o_result;
get_datetime_string(tms, sizeof(tms));
pid = os::current_process_id();
// test.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms);
o_result = make_log_name_internal("test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// test-%t-%p.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// test-%t%p.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %p%t.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %p-test.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid);
o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %t.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms);
o_result = make_log_name_internal("%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
+
+ {
+ // longest filename
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', sizeof(longest_name));
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result));
+ FREE_C_HEAP_ARRAY(char, o_result);
+ }
+
+ {
+ // too long file name
+ char too_long_name[JVM_MAXPATHLEN + 100];
+ int too_long_length = sizeof(too_long_name);
+ memset(too_long_name, 'a', too_long_length);
+ too_long_name[too_long_length - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result));
+ }
+
+ {
+ // too long with timestamp
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', JVM_MAXPATHLEN);
+ longest_name[JVM_MAXPATHLEN - 3] = '%';
+ longest_name[JVM_MAXPATHLEN - 2] = 't';
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result));
+ }
+
+ {
+ // too long with pid
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', JVM_MAXPATHLEN);
+ longest_name[JVM_MAXPATHLEN - 3] = '%';
+ longest_name[JVM_MAXPATHLEN - 2] = 'p';
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
+ }
}
#endif // PRODUCT
@@ -637,9 +682,16 @@
_bytes_written = 0L;
_file_name = make_log_name(file_name, NULL);
+ if (_file_name == NULL) {
+ warning("Cannot open file %s: file name is too long.\n", file_name);
+ _need_close = false;
+ UseGCLogFileRotation = false;
+ return;
+ }
+
// gc log file rotation
if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
- char tempbuf[FILENAMEBUFLEN];
+ char tempbuf[JVM_MAXPATHLEN];
jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
_file = fopen(tempbuf, "w");
} else {
@@ -671,10 +723,10 @@
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized.
void gcLogFileStream::rotate_log(bool force, outputStream* out) {
- char time_msg[FILENAMEBUFLEN];
+ char time_msg[O_BUFLEN];
char time_str[EXTRACHARLEN];
- char current_file_name[FILENAMEBUFLEN];
- char renamed_file_name[FILENAMEBUFLEN];
+ char current_file_name[JVM_MAXPATHLEN];
+ char renamed_file_name[JVM_MAXPATHLEN];
if (!should_rotate(force)) {
return;
@@ -713,12 +765,15 @@
// have a form of extended_filename.<i>.current where i is the current rotation
// file number. After it reaches max file size, the file will be saved and renamed
// with .current removed from its tail.
- size_t filename_len = strlen(_file_name);
if (_file != NULL) {
- jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d",
+ jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
_file_name, _cur_file_num);
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
- _file_name, _cur_file_num);
+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
+ "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
+ if (result >= JVM_MAXPATHLEN) {
+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+ return;
+ }
const char* msg = force ? "GC log rotation request has been received."
: "GC log file has reached the maximum size.";
@@ -757,19 +812,23 @@
_cur_file_num++;
if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num);
+ if (result >= JVM_MAXPATHLEN) {
+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+ return;
+ }
+
_file = fopen(current_file_name, "w");
if (_file != NULL) {
_bytes_written = 0L;
_need_close = true;
// reuse current_file_name for time_msg
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN,
+ jio_snprintf(current_file_name, JVM_MAXPATHLEN,
"%s.%d", _file_name, _cur_file_num);
jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
- os::local_time_string((char *)time_str, sizeof(time_str)),
- current_file_name);
+ os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
write(time_msg, strlen(time_msg));
if (out != NULL) {
@@ -817,32 +876,64 @@
return _log_file != NULL;
}
+fileStream* defaultStream::open_file(const char* log_name) {
+ const char* try_name = make_log_name(log_name, NULL);
+ if (try_name == NULL) {
+ warning("Cannot open file %s: file name is too long.\n", log_name);
+ return NULL;
+ }
+
+ fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ FREE_C_HEAP_ARRAY(char, try_name);
+ if (file->is_open()) {
+ return file;
+ }
+
+ // Try again to open the file in the temp directory.
+ delete file;
+ char warnbuf[O_BUFLEN*2];
+ jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Cannot open log file: %s\n", log_name);
+ // Note: This feature is for maintainer use only. No need for L10N.
+ jio_print(warnbuf);
+ try_name = make_log_name(log_name, os::get_temp_directory());
+ if (try_name == NULL) {
+ warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
+ return NULL;
+ }
+
+ jio_snprintf(warnbuf, sizeof(warnbuf),
+ "Warning: Forcing option -XX:LogFile=%s\n", try_name);
+ jio_print(warnbuf);
+
+ file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ FREE_C_HEAP_ARRAY(char, try_name);
+ if (file->is_open()) {
+ return file;
+ }
+
+ delete file;
+ return NULL;
+}
+
void defaultStream::init_log() {
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
- const char* try_name = make_log_name(log_name, NULL);
- fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
- if (!file->is_open()) {
- // Try again to open the file.
- char warnbuf[O_BUFLEN*2];
- jio_snprintf(warnbuf, sizeof(warnbuf),
- "Warning: Cannot open log file: %s\n", try_name);
- // Note: This feature is for maintainer use only. No need for L10N.
- jio_print(warnbuf);
- FREE_C_HEAP_ARRAY(char, try_name);
- try_name = make_log_name(log_name, os::get_temp_directory());
- jio_snprintf(warnbuf, sizeof(warnbuf),
- "Warning: Forcing option -XX:LogFile=%s\n", try_name);
- jio_print(warnbuf);
- delete file;
- file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ fileStream* file = open_file(log_name);
+
+ if (file != NULL) {
+ _log_file = file;
+ _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
+ start_log();
+ } else {
+ // and leave xtty as NULL
+ LogVMOutput = false;
+ DisplayVMOutput = true;
+ LogCompilation = false;
}
- FREE_C_HEAP_ARRAY(char, try_name);
+}
- if (file->is_open()) {
- _log_file = file;
- xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
- _outer_xmlStream = xs;
+void defaultStream::start_log() {
+ xmlStream*xs = _outer_xmlStream;
if (this == tty) xtty = xs;
// Write XML header.
xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
@@ -897,13 +988,6 @@
xs->head("tty");
// All further non-markup text gets copied to the tty:
xs->_text = this; // requires friend declaration!
- } else {
- delete(file);
- // and leave xtty as NULL
- LogVMOutput = false;
- DisplayVMOutput = true;
- LogCompilation = false;
- }
}
// finish_log() is called during normal VM shutdown. finish_log_on_error() is
--- a/hotspot/src/share/vm/utilities/vmError.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -22,6 +22,7 @@
*
*/
+#include <fcntl.h>
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
@@ -807,7 +808,8 @@
static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
int fd = -1;
if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
- fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ // the O_EXCL flag will cause the open to fail if the file exists
+ fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
}
return fd;
}
--- a/hotspot/src/share/vm/utilities/xmlstream.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/src/share/vm/utilities/xmlstream.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, 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
@@ -33,6 +33,10 @@
#include "runtime/vmThread.hpp"
#include "utilities/xmlstream.hpp"
+// Do not assert this condition if there's already another error reported.
+#define assert_if_no_error(cond, msg) \
+ vmassert((cond) || is_error_reported(), msg)
+
void xmlStream::initialize(outputStream* out) {
_out = out;
_last_flush = 0;
--- a/hotspot/test/TEST.groups Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/TEST.groups Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, 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
@@ -69,7 +69,6 @@
gc/metaspace/TestPerfCountersAndMemoryPools.java \
runtime/6819213/TestBootNativeLibraryPath.java \
runtime/7158988/FieldMonitor.java \
- runtime/7194254/Test7194254.java \
runtime/Metaspace/FragmentMetaspace.java \
runtime/NMT/BaselineWithParameter.java \
runtime/NMT/JcmdBaselineDetail.java \
@@ -94,6 +93,7 @@
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
runtime/Thread/TestThreadDumpMonitorContention.java \
+ runtime/Thread/ThreadPriorities.java \
runtime/XCheckJniJsig/XCheckJSig.java \
serviceability/attach/AttachWithStalePidFile.java \
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \
@@ -232,7 +232,8 @@
gc/g1/ \
gc/metaspace/G1AddMetaspaceDependency.java \
gc/metaspace/TestMetaspacePerfCounters.java \
- gc/startup_warnings/TestG1.java
+ gc/startup_warnings/TestG1.java \
+ gc/whitebox/TestConcMarkCycleWB.java
# All tests that explicitly set the serial GC
#
@@ -357,7 +358,8 @@
compiler/inlining/ \
compiler/integerArithmetic/ \
compiler/interpreter/ \
- -compiler/codegen/7184394
+ -compiler/codegen/7184394 \
+ -compiler/codecache/stress
hotspot_compiler_3 = \
compiler/intrinsics/ \
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -37,6 +37,7 @@
/*
* @test PoolsIndependenceTest
+ * @ignore 8068385
* @library /testlibrary /../../test/lib
* @build PoolsIndependenceTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 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 com.oracle.java.testlibrary.TimeLimitedRunner;
+import com.oracle.java.testlibrary.Utils;
+
+public class CodeCacheStressRunner {
+ private final Runnable action;
+ public CodeCacheStressRunner(Runnable action) {
+ this.action = action;
+ }
+
+ protected final void runTest() {
+ Helper.startInfiniteLoopThread(action);
+ try {
+ // adjust timeout and substract vm init and exit time
+ long timeout = Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT);
+ timeout *= 0.9;
+ new TimeLimitedRunner(timeout, 2.0d, this::test).call();
+ } catch (Exception e) {
+ throw new Error("Exception occurred during test execution", e);
+ }
+ }
+
+ private boolean test() {
+ Helper.TestCase obj = Helper.TestCase.get();
+ Helper.callMethod(obj.getCallable(), obj.expectedValue());
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/Helper.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014, 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.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ByteCodeLoader;
+import com.oracle.java.testlibrary.InfiniteLoop;
+import com.oracle.java.testlibrary.Utils;
+import sun.hotspot.WhiteBox;
+
+public final class Helper {
+ public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ public static final Random RNG = Utils.getRandomInstance();
+
+ private static final long THRESHOLD = WHITE_BOX.getIntxVMFlag("CompileThreshold");
+ private static final String TEST_CASE_IMPL_CLASS_NAME = "Helper$TestCaseImpl";
+ private static byte[] CLASS_DATA;
+ static {
+ try {
+ CLASS_DATA = loadClassData(TEST_CASE_IMPL_CLASS_NAME);
+ } catch (IOException e) {
+ throw new Error("TESTBUG: cannot load class byte code", e);
+ }
+ }
+
+ private Helper() {
+ }
+
+ public static void startInfiniteLoopThread(Runnable action) {
+ startInfiniteLoopThread(action, 0L);
+ }
+
+ public static void startInfiniteLoopThread(Runnable action, long millis) {
+ Thread t = new Thread(new InfiniteLoop(action, millis));
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static int callMethod(Callable<Integer> callable, int expected) {
+ int result = 0;
+ for (int i = 0; i < THRESHOLD; ++i) {
+ try {
+ result = callable.call();
+ } catch (Exception e) {
+ throw new AssertionError(
+ "Exception occurred during test method execution", e);
+ }
+ Asserts.assertEQ(result, expected, "Method returns unexpected value");
+ }
+ return result;
+ }
+
+ private static byte[] loadClassData(String name) throws IOException {
+ try (BufferedInputStream in = new BufferedInputStream(
+ ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ + ".class"))) {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1) {
+ result.write(buffer, 0, read);
+ }
+ return result.toByteArray();
+ }
+ }
+
+ public interface TestCase {
+
+ public static TestCase get() {
+ try {
+ Class clazz = ByteCodeLoader.load(
+ TEST_CASE_IMPL_CLASS_NAME, CLASS_DATA);
+ return (TestCase) clazz.newInstance();
+ } catch (ReflectiveOperationException e) {
+ throw new Error(String.format(
+ "TESTBUG: error while creating %s instance from reloaded class",
+ TEST_CASE_IMPL_CLASS_NAME), e);
+ }
+ }
+
+ Callable<Integer> getCallable();
+ int method();
+ int expectedValue();
+ }
+
+ public static class TestCaseImpl implements TestCase {
+ private static final int RETURN_VALUE = 42;
+ private static final int RECURSION_DEPTH = 10;
+ private volatile int i;
+
+ @Override
+ public Callable<Integer> getCallable() {
+ return () -> {
+ i = 0;
+ return method();
+ };
+ }
+
+ @Override
+ public int method() {
+ ++i;
+ int result = RETURN_VALUE;
+ if (i < RECURSION_DEPTH) {
+ return result + method();
+ }
+ return result;
+ }
+
+ @Override
+ public int expectedValue() {
+ return RETURN_VALUE * RECURSION_DEPTH;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 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.lang.reflect.Method;
+import java.util.stream.IntStream;
+
+import com.oracle.java.testlibrary.Platform;
+
+/*
+ * @test OverloadCompileQueueTest
+ * @library /testlibrary /../../test/lib
+ * @build OverloadCompileQueueTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache OverloadCompileQueueTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache OverloadCompileQueueTest
+ * @summary stressing code cache by overloading compile queues
+ */
+public class OverloadCompileQueueTest implements Runnable {
+ private static final int MAX_SLEEP = 10000;
+ private static final String METHOD_TO_ENQUEUE = "method";
+ private static final int LEVEL_SIMPLE = 1;
+ private static final int LEVEL_FULL_OPTIMIZATION = 4;
+ private static final boolean INTERPRETED
+ = System.getProperty("java.vm.info").startsWith("interpreted ");
+ private static final boolean TIERED_COMPILATION
+ = Helper.WHITE_BOX.getBooleanVMFlag("TieredCompilation");
+ private static final int TIERED_STOP_AT_LEVEL
+ = Helper.WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue();
+ private static final int[] AVAILABLE_LEVELS;
+ static {
+ if (TIERED_COMPILATION) {
+ AVAILABLE_LEVELS = IntStream
+ .rangeClosed(LEVEL_SIMPLE, TIERED_STOP_AT_LEVEL)
+ .toArray();
+ } else if (Platform.isServer()) {
+ AVAILABLE_LEVELS = new int[] { LEVEL_FULL_OPTIMIZATION };
+ } else if (Platform.isClient() || Platform.isMinimal()) {
+ AVAILABLE_LEVELS = new int[] { LEVEL_SIMPLE };
+ } else {
+ throw new Error(String.format(
+ "TESTBUG: unknown VM: %s", System.getProperty("java.vm.name")));
+ }
+ }
+
+ public static void main(String[] args) {
+ if (INTERPRETED) {
+ System.err.println("Test isn't applicable for interpreter. Skip test.");
+ return;
+ }
+ new CodeCacheStressRunner(new OverloadCompileQueueTest()).runTest();
+ }
+
+ public OverloadCompileQueueTest() {
+ Helper.startInfiniteLoopThread(this::lockUnlock);
+ }
+
+ @Override
+ public void run() {
+ Helper.TestCase obj = Helper.TestCase.get();
+ Class clazz = obj.getClass();
+ Method mEnqueue;
+ try {
+ mEnqueue = clazz.getMethod(METHOD_TO_ENQUEUE);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new Error(String.format(
+ "TESTBUG: cannot get method '%s' of class %s",
+ METHOD_TO_ENQUEUE, clazz.getName()), e);
+ }
+ for (int compLevel : AVAILABLE_LEVELS) {
+ Helper.WHITE_BOX.enqueueMethodForCompilation(mEnqueue, compLevel);
+ }
+ }
+
+ private void lockUnlock() {
+ try {
+ Helper.WHITE_BOX.lockCompilation();
+ Thread.sleep(Helper.RNG.nextInt(MAX_SLEEP));
+ } catch (InterruptedException e) {
+ throw new Error("TESTBUG: lockUnlocker thread was unexpectedly interrupted", e);
+ } finally {
+ Helper.WHITE_BOX.unlockCompilation();
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 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.util.ArrayList;
+
+import sun.hotspot.code.BlobType;
+
+/*
+ * @test RandomAllocationTest
+ * @library /testlibrary /../../test/lib
+ * @build RandomAllocationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache RandomAllocationTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache RandomAllocationTest
+ * @summary stressing code cache by allocating randomly sized "dummy" code blobs
+ */
+public class RandomAllocationTest implements Runnable {
+ private static final long CODE_CACHE_SIZE
+ = Helper.WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize");
+ private static final int MAX_BLOB_SIZE = (int) (CODE_CACHE_SIZE >> 7);
+ private static final BlobType[] BLOB_TYPES
+ = BlobType.getAvailable().toArray(new BlobType[0]);
+
+ public static void main(String[] args) {
+ new CodeCacheStressRunner(new RandomAllocationTest()).runTest();
+ }
+
+ private final ArrayList<Long> blobs = new ArrayList<>();
+ @Override
+ public void run() {
+ boolean allocate = blobs.isEmpty() || Helper.RNG.nextBoolean();
+ if (allocate) {
+ int type = Helper.RNG.nextInt(BLOB_TYPES.length);
+ long addr = Helper.WHITE_BOX.allocateCodeBlob(
+ Helper.RNG.nextInt(MAX_BLOB_SIZE), BLOB_TYPES[type].id);
+ if (addr != 0) {
+ blobs.add(addr);
+ }
+ } else {
+ int index = Helper.RNG.nextInt(blobs.size());
+ Helper.WHITE_BOX.freeCodeBlob(blobs.remove(index));
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 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 UnexpectedDeoptimizationTest
+ * @library /testlibrary /../../test/lib
+ * @build UnexpectedDeoptimizationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache -XX:-DeoptimizeRandom
+ * UnexpectedDeoptimizationTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom
+ * UnexpectedDeoptimizationTest
+ * @summary stressing code cache by forcing unexpected deoptimizations
+ */
+public class UnexpectedDeoptimizationTest implements Runnable {
+
+ public static void main(String[] args) {
+ new CodeCacheStressRunner(new UnexpectedDeoptimizationTest()).runTest();
+ }
+
+ @Override
+ public void run() {
+ Helper.WHITE_BOX.deoptimizeFrames(Helper.RNG.nextBoolean());
+ }
+
+}
--- a/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java Wed Jul 05 20:15:59 2017 +0200
@@ -25,7 +25,7 @@
* @test
* @bug 8054224
* @summary Recursive method compiled by C1 is unable to catch StackOverflowError
- * @run main/othervm -Xcomp -XX:CompileOnly=Test.run -XX:+TieredCompilation -XX:TieredStopAtLevel=2 -Xss256K TestRecursiveReplacedException
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test.run -XX:+TieredCompilation -XX:TieredStopAtLevel=2 -Xss392K TestRecursiveReplacedException
*
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/floatingpoint/TestPow2.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 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 8063086
+ * @summary X^2 special case for C2 yields different result than interpreter
+ * @library /testlibrary /../../test/lib /compiler/whitebox
+ * @build TestPow2
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestPow2
+ *
+ */
+
+import java.lang.reflect.*;
+import sun.hotspot.WhiteBox;
+
+public class TestPow2 {
+
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ private static final double base = 5350.456329377186;
+ private static final double exp = 2.0;
+
+ static double m() {
+ return Math.pow(base, exp);
+ }
+
+ static public void main(String[] args) throws NoSuchMethodException {
+ Method test_method = TestPow2.class.getDeclaredMethod("m");
+
+ double interpreter_result = m();
+
+ // Compile with C1 if possible
+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
+
+ double c1_result = m();
+
+ WHITE_BOX.deoptimizeMethod(test_method);
+
+ // Compile it with C2 if possible
+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+
+ double c2_result = m();
+
+ if (interpreter_result != c1_result || interpreter_result != c2_result ||
+ c1_result != c2_result) {
+ System.out.println("interpreter = " + interpreter_result + " c1 = " + c1_result + " c2 = " + c2_result);
+ throw new RuntimeException("Test Failed");
+ }
+ }
+}
--- a/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Wed Jul 05 20:15:59 2017 +0200
@@ -26,6 +26,7 @@
* @bug 8042235
* @summary redefining method used by multiple MethodHandles crashes VM
* @compile -XDignore.symbol.file RedefineMethodUsedByMultipleMethodHandles.java
+ * @ignore 7076820
* @run main RedefineMethodUsedByMultipleMethodHandles
*/
--- a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Wed Jul 05 20:15:59 2017 +0200
@@ -172,7 +172,7 @@
out.shouldContain(expected_output);
}
- out.shouldNotContain("CompilerOracle: unrecognized line");
+ out.shouldNotContain("CompileCommand: unrecognized line");
out.shouldHaveExitValue(0);
}
@@ -183,7 +183,7 @@
pb = ProcessTools.createJavaProcessBuilder(arguments);
out = new OutputAnalyzer(pb.start());
- out.shouldContain("CompilerOracle: unrecognized line");
+ out.shouldContain("CompileCommand: unrecognized line");
out.shouldHaveExitValue(0);
}
--- a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Wed Jul 05 20:15:59 2017 +0200
@@ -28,6 +28,7 @@
* @bug 8038636
* @library /testlibrary
* @build Agent
+ * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Wed Jul 05 20:15:59 2017 +0200
@@ -28,6 +28,7 @@
* @bug 8040237
* @library /testlibrary
* @build Agent Test A B
+ * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Wed Jul 05 20:15:59 2017 +0200
@@ -53,6 +53,7 @@
*/
public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
private static final long LOCKING_THRESHOLD = 100L;
+ private static final long ABORT_THRESHOLD = LOCKING_THRESHOLD / 2L;
private TestRTMDeoptOnLowAbortRatio() {
super(new AndPredicate(new SupportedCPU(), new SupportedVM()));
@@ -77,7 +78,8 @@
useStackLock),
CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold",
TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD),
- "-XX:RTMAbortThreshold=1",
+ CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold",
+ TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD),
"-XX:RTMAbortRatio=100",
"-XX:CompileThreshold=1",
"-XX:RTMRetryCount=0",
@@ -107,7 +109,7 @@
for (RTMLockingStatistics s : statistics) {
if (s.getTotalLocks()
- == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD + 1L) {
+ == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD) {
Asserts.assertNull(statisticsBeforeDeopt,
"Only one abort was expected during test run");
statisticsBeforeDeopt = s;
@@ -154,8 +156,7 @@
}
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
- t.forceAbort(
- i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
+ t.forceAbort(i >= TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD);
}
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Wed Jul 05 20:15:59 2017 +0200
@@ -58,7 +58,7 @@
* interrupts, VMM calls, etc. during first lock attempt.
*
*/
- private static final int ABORT_THRESHOLD = 10;
+ private static final int MIN_ABORT_THRESHOLD = 10;
@Override
protected void runTestCases() throws Throwable {
@@ -75,6 +75,9 @@
boolean useStackLock) throws Throwable {
CompilableTest test = new Test();
+ int abortThreshold = Math.max(lockingThreshold / 2,
+ TestRTMLockingThreshold.MIN_ABORT_THRESHOLD);
+
OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(
test,
"-XX:CompileThreshold=1",
@@ -84,7 +87,7 @@
"-XX:RTMTotalCountIncrRate=1",
"-XX:RTMRetryCount=0",
CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold",
- TestRTMLockingThreshold.ABORT_THRESHOLD),
+ abortThreshold),
CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold",
lockingThreshold),
"-XX:RTMAbortRatio=100",
@@ -103,16 +106,12 @@
+ "RTM locking statistics entries.");
/**
- * We force abort on each odd iteration, so if RTMLockingThreshold==0,
- * then we have to make 1 call without abort to avoid rtm state
- * transition to NoRTM (otherwise actual abort ratio will be 100%),
- * and after that make 1 call with abort to force deoptimization.
- * This leads us to two locks for threshold 0.
- * For other threshold values we have to make RTMLockingThreshold + 1
- * locks if locking threshold is even, or + 0 if odd.
+ * If RTMLockingThreshold==0, then we have to make at least 1 call.
*/
- long expectedValue = lockingThreshold +
- (lockingThreshold == 0L ? 2L : lockingThreshold % 2L);
+ long expectedValue = lockingThreshold;
+ if (expectedValue == 0) {
+ expectedValue++;
+ }
RTMLockingStatistics statBeforeDeopt = null;
for (RTMLockingStatistics s : statistics) {
@@ -159,15 +158,16 @@
* Test <inflate monitor>
*/
public static void main(String args[]) throws Throwable {
- Asserts.assertGTE(args.length, 1, "One argument required.");
+ Asserts.assertGTE(args.length, 2, "Two arguments required.");
Test t = new Test();
boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ int lockingThreshold = Integer.valueOf(args[1]);
if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
- t.lock(i % 2 == 1);
+ t.lock(i >= lockingThreshold / 2);
}
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Wed Jul 05 20:15:59 2017 +0200
@@ -35,6 +35,7 @@
* -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate
*/
+import sun.misc.Unsafe;
import java.util.List;
import com.oracle.java.testlibrary.*;
@@ -97,14 +98,12 @@
Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS,
"Total locks should be exactly the same as amount of "
+ "iterations.");
- } else {
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM statistics "
- + "should contain information for at least on lock.");
}
}
public static class Test implements CompilableTest {
private static final long TOTAL_ITERATIONS = 10000L;
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
private final Object monitor = new Object();
// Following field have to be static in order to avoid escape analysis.
@SuppressWarnings("UnsuedDeclaration")
@@ -120,8 +119,17 @@
return new String[] { getMethodWithLockName() };
}
- public void lock() {
+ public void lock(booleab forceAbort) {
synchronized(monitor) {
+ if (forceAbort) {
+ // We're calling native method in order to force
+ // abort. It's done by explicit xabort call emitted
+ // in SharedRuntime::generate_native_wrapper.
+ // If an actuall JNI call will be replaced by
+ // intrinsic - we'll be in trouble, since xabort
+ // will be no longer called and test may fail.
+ UNSAFE.addressSize();
+ }
Test.field++;
}
}
@@ -140,7 +148,11 @@
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(test.monitor,
shouldBeInflated);
- test.lock();
+ // Force abort on first iteration to avoid rare case when
+ // there were no aborts and locks count was not incremented
+ // with RTMTotalCountIncrRate > 1 (in such case JVM won't
+ // print JVM locking statistics).
+ test.lock(i == 0);
}
}
}
--- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Wed Jul 05 20:15:59 2017 +0200
@@ -125,9 +125,6 @@
RTMLockingStatistics lock = statistics.get(0);
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM locking statistics "
- + "should contain non zero total locks count");
-
Asserts.assertGT(lock.getTotalAborts(), 0L,
"RTM locking statistics should contain non zero total aborts "
+ "count");
--- a/hotspot/test/compiler/runtime/6865265/StackOverflowBug.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/runtime/6865265/StackOverflowBug.java Wed Jul 05 20:15:59 2017 +0200
@@ -28,7 +28,7 @@
* @summary JVM crashes with "missing exception handler" error
* @author volker.simonis@sap.com
*
- * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss248k StackOverflowBug
+ * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss392k StackOverflowBug
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/uncommontrap/Verifier.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, 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 uncommontrap;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.Asserts;
+/**
+ * Utility tool aimed to verify presence or absence of specified uncommon trap
+ * in compilation log.
+ */
+public class Verifier {
+ public static final String PROPERTIES_FILE_SUFFIX = ".verify.properties";
+ public static final String VERIFICATION_SHOULD_BE_SKIPPED
+ = "uncommon.trap.verification.skipped";
+ public static final String UNCOMMON_TRAP_NAME = "uncommon.trap.name";
+ public static final String UNCOMMON_TRAP_BCI = "uncommon.trap.bci";
+ public static final String UNCOMMON_TRAP_COMMENT = "uncommon.trap.comment";
+ public static final String UNCOMMON_TRAP_ACTION = "uncommon.trap.action";
+ public static final String UNCOMMON_TRAP_SHOULD_EMITTED
+ = "uncommon.trap.emitted";
+ public static final String UNCOMMON_TRAP_SHOULD_FIRED
+ = "uncommon.trap.fired";
+
+ private static final String EMITTED_TRAP_PATTERN
+ = "<uncommon_trap bci='%s' reason='%s' action='%s' "
+ + "comment='%s'";
+ private static final String FIRED_TRAP_PATTERN
+ = "<uncommon_trap thread='[0-9]*' reason='%s' action='%s'";
+ private static final String JVMS_PATTERN = "<jvms bci='%s'";
+
+ public static void main(String args[]) {
+ if (args.length == 0) {
+ throw new Error("At least one argument containing name of "
+ + "compilation log file is expected");
+ }
+
+ for (String compLogFile : args) {
+ try {
+ verify(Paths.get(compLogFile));
+ } catch (IOException e) {
+ throw new Error("Unable to process compilation log.", e);
+ }
+ }
+ }
+
+ private static void verify(Path compLogFile) throws IOException {
+ Path propertiesFile = Paths.get(compLogFile.toString() +
+ PROPERTIES_FILE_SUFFIX);
+
+ Properties properties = new Properties();
+ properties.load(new FileReader(propertiesFile.toFile()));
+
+ if (Boolean.valueOf(properties.getProperty(
+ VERIFICATION_SHOULD_BE_SKIPPED, "false"))) {
+ System.out.println("Skipping verification for log file: "
+ + compLogFile.toString());
+ return;
+ }
+
+ System.out.println("Verifying log file: " + compLogFile.toString());
+
+ List<String> compLogContent = Files.readAllLines(compLogFile);
+ verifyUncommonTrapEmitted(properties, compLogContent);
+ verifyUncommonTrapFired(properties, compLogContent);
+ }
+
+ private static void verifyUncommonTrapEmitted(Properties properties,
+ List<String> compLogContent) {
+ String emittedTrapRE = String.format(EMITTED_TRAP_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_BCI, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_NAME, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_ACTION, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_COMMENT, ".*"));
+ Pattern pattern = Pattern.compile(emittedTrapRE);
+
+ long trapsCount = compLogContent.stream()
+ .filter(line -> pattern.matcher(line).find())
+ .count();
+
+ boolean shouldBeEmitted = Boolean.valueOf(
+ properties.getProperty(UNCOMMON_TRAP_SHOULD_EMITTED));
+
+ Asserts.assertEQ(shouldBeEmitted, trapsCount > 0, String.format(
+ "Uncommon trap that matches following string in compilation log"
+ + " should %sbe emitted: %s.",
+ (shouldBeEmitted ? " " : "not "), emittedTrapRE));
+ }
+
+ private static void verifyUncommonTrapFired(Properties properties,
+ List<String> compLogContent) {
+ String firedTrapRE = String.format(FIRED_TRAP_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_NAME, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_ACTION, ".*"));
+ String jvmsRE = String.format(JVMS_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_BCI, ".*"));
+
+ boolean trapFired = false;
+ Pattern firedTrapPattern = Pattern.compile(firedTrapRE);
+ Pattern jvmsPattern = Pattern.compile(jvmsRE);
+
+ Iterator<String> iterator = compLogContent.iterator();
+ while (iterator.hasNext() && !trapFired) {
+ trapFired = firedTrapPattern.matcher(iterator.next()).find()
+ && jvmsPattern.matcher(iterator.next()).find();
+ }
+
+ boolean shouldBeFired = Boolean.valueOf(
+ properties.getProperty(UNCOMMON_TRAP_SHOULD_FIRED));
+ Asserts.assertEQ(shouldBeFired, trapFired, String.format(
+ "Uncommon trap that matches following string in compilation log"
+ + " should %sbe fired: %s.",
+ (shouldBeFired ? "" : "not "), firedTrapRE));
+ }
+}
+
--- a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java Wed Jul 05 20:15:59 2017 +0200
@@ -32,7 +32,7 @@
* @build Test8009761
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss392K Test8009761
*/
public class Test8009761 {
--- a/hotspot/test/compiler/uncommontrap/StackOverflowGuardPagesOff.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/StackOverflowGuardPagesOff.java Wed Jul 05 20:15:59 2017 +0200
@@ -25,7 +25,7 @@
* @test
* @bug 8029383
* @summary stack overflow if callee is marked for deoptimization causes crash
- * @run main/othervm -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,StackOverflowGuardPagesOff::m1 -XX:CompileCommand=exclude,StackOverflowGuardPagesOff::m2 -Xss256K -XX:-UseOnStackReplacement StackOverflowGuardPagesOff
+ * @run main/othervm -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,StackOverflowGuardPagesOff::m1 -XX:CompileCommand=exclude,StackOverflowGuardPagesOff::m2 -Xss392K -XX:-UseOnStackReplacement StackOverflowGuardPagesOff
*
*/
--- a/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Wed Jul 05 20:15:59 2017 +0200
@@ -25,7 +25,7 @@
* @test
* @bug 8032410
* @summary Stack overflow at deoptimization doesn't release owned monitors
- * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangMonitorOwned::m1 -XX:CompileCommand=exclude,TestStackBangMonitorOwned::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangMonitorOwned
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangMonitorOwned::m1 -XX:CompileCommand=exclude,TestStackBangMonitorOwned::m2 -Xss392K -XX:-UseOnStackReplacement TestStackBangMonitorOwned
*
*/
public class TestStackBangMonitorOwned {
--- a/hotspot/test/compiler/uncommontrap/TestStackBangRbp.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/TestStackBangRbp.java Wed Jul 05 20:15:59 2017 +0200
@@ -25,7 +25,7 @@
* @test
* @bug 8028308
* @summary rbp not restored when stack overflow is thrown from deopt/uncommon trap blobs
- * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangRbp::m1 -XX:CompileCommand=exclude,TestStackBangRbp::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangRbp
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangRbp::m1 -XX:CompileCommand=exclude,TestStackBangRbp::m2 -Xss392K -XX:-UseOnStackReplacement TestStackBangRbp
*
*/
public class TestStackBangRbp {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2014, 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.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import com.oracle.java.testlibrary.ByteCodeLoader;
+import com.oracle.java.testlibrary.Platform;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+import sun.hotspot.WhiteBox;
+import uncommontrap.Verifier;
+
+/*
+ * @test
+ * @bug 8030976 8059226
+ * @library /testlibrary /compiler/testlibrary /../../test/lib
+ * @build TestUnstableIfTrap com.oracle.java.testlibrary.* uncommontrap.Verifier
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=always_taken_not_fired.xml
+ * TestUnstableIfTrap ALWAYS_TAKEN false
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=always_taken_fired.xml
+ * TestUnstableIfTrap ALWAYS_TAKEN true
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=never_taken_not_fired.xml
+ * TestUnstableIfTrap NEVER_TAKEN false
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=never_taken_fired.xml
+ * TestUnstableIfTrap NEVER_TAKEN true
+ * @run main uncommontrap.Verifier always_taken_not_fired.xml
+ * always_taken_fired.xml
+ * never_taken_not_fired.xml
+ * never_taken_fired.xml
+ */
+public class TestUnstableIfTrap {
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final String CLASS_NAME = "UnstableIfExecutable";
+ private static final String METHOD_NAME = "test";
+ private static final String FIELD_NAME = "field";
+ private static final int ITERATIONS = 1_000_000;
+ // There is no dependency on particular class file version, so it could be
+ // set to any version (if you're updating this test for Java 42).
+ private static final int CLASS_FILE_VERSION = 49;
+ private static final int MAX_TIER = 4;
+ // This test aimed to verify that uncommon trap with reason "unstable_if"
+ // is emitted when method that contain control-flow divergence such that
+ // one of two branches is never taken (and other one is taken always).
+ // C2 will made a decision whether or not the branch was ever taken
+ // depending on method's profile.
+ // If profile was collected for a few method's invocations, then C2 will not
+ // trust in branches' probabilities and the tested trap won't be emitted.
+ // In fact, a method has to be invoked at least 40 time at the day when this
+ // comment was written (see Parse::dynamic_branch_prediction for an actual
+ // value). It would be to implementation dependent to use "40" as
+ // a threshold value in the test, so in order to improve test's robustness
+ // the threshold value is 1000: if the tested method was compiled by C2
+ // before it was invoked 1000 times, then we won't verify that trap was
+ // emitted and fired.
+ private static final int MIN_INVOCATIONS_BEFORE_C2_COMPILATION = 1000;
+ /**
+ * Description of test case parameters and uncommon trap that will
+ * be emitted during tested method compilation.
+ */
+ private static enum TestCaseName {
+ ALWAYS_TAKEN(false, "taken always"),
+ NEVER_TAKEN(true, "taken never");
+ TestCaseName(boolean predicate, String comment) {
+ this.predicate = predicate;
+ this.comment = comment;
+ }
+
+ public final boolean predicate;
+ public final String name = "unstable_if";
+ public final String comment;
+ }
+
+ public static void main(String args[]) {
+ if (args.length != 2) {
+ throw new Error("Expected two arguments: test case name and a "
+ + "boolean determining if uncommon trap should be fired.");
+ }
+ test(TestCaseName.valueOf(args[0]), Boolean.valueOf(args[1]));
+ }
+
+ private static void test(TestCaseName testCase, boolean shouldBeFired) {
+ Method testMethod;
+ Label unstableIfLocation = new Label();
+ boolean shouldBeEmitted;
+ boolean compiledToEarly = false;
+
+ try {
+ Class testClass = ByteCodeLoader.load(CLASS_NAME,
+ generateTest(unstableIfLocation));
+ testMethod = testClass.getDeclaredMethod(METHOD_NAME,
+ boolean.class);
+ for (int i = 0; i < ITERATIONS; i++) {
+ testMethod.invoke(null, testCase.predicate);
+ if (i < MIN_INVOCATIONS_BEFORE_C2_COMPILATION
+ && isMethodCompiledByC2(testMethod)) {
+ compiledToEarly = true;
+ // There is no sense in further invocations: we already
+ // decided to avoid verification.
+ break;
+ }
+ }
+ // We're checking that trap should be emitted (i.e. it was compiled
+ // by C2) before the trap is fired, because otherwise the nmethod
+ // will be deoptimized and isMethodCompiledByC2 will return false.
+ shouldBeEmitted = isMethodCompiledByC2(testMethod)
+ && !compiledToEarly;
+ if (shouldBeFired) {
+ testMethod.invoke(null, !testCase.predicate);
+ }
+ } catch (ReflectiveOperationException e) {
+ throw new Error("Test case should be generated, loaded and executed"
+ + " without any issues.", e);
+ }
+
+ shouldBeFired &= shouldBeEmitted;
+
+ Properties properties = new Properties();
+ properties.setProperty(Verifier.VERIFICATION_SHOULD_BE_SKIPPED,
+ Boolean.toString(compiledToEarly));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_SHOULD_EMITTED,
+ Boolean.toString(shouldBeEmitted));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_SHOULD_FIRED,
+ Boolean.toString(shouldBeFired));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_NAME, testCase.name);
+ properties.setProperty(Verifier.UNCOMMON_TRAP_COMMENT,
+ testCase.comment);
+ properties.setProperty(Verifier.UNCOMMON_TRAP_BCI,
+ Integer.toString(unstableIfLocation.getOffset()));
+
+ properties.list(System.out);
+
+ File f = new File(WB.getStringVMFlag("LogFile") +
+ Verifier.PROPERTIES_FILE_SUFFIX);
+ try (FileWriter wr = new FileWriter(f)) {
+ properties.store(wr, "");
+ } catch (IOException e) {
+ throw new Error("Unable to store test properties.", e);
+ }
+ }
+
+ private static boolean isMethodCompiledByC2(Method m) {
+ boolean isTiered = WB.getBooleanVMFlag("TieredCompilation");
+ boolean isMethodCompiled = WB.isMethodCompiled(m);
+ boolean isMethodCompiledAtMaxTier
+ = WB.getMethodCompilationLevel(m) == MAX_TIER;
+
+ return Platform.isServer() && isMethodCompiled
+ && (!isTiered || isMethodCompiledAtMaxTier);
+ }
+
+ /**
+ * Generates class with name {@code CLASS_NAME}, which will contain a
+ * static method {@code METHOD_NAME}:
+ *
+ * <pre>{@code
+ * public abstract class UnstableIfExecutable {
+ * private static int field = 0;
+ *
+ * public static void test(boolean alwaysTrue) {
+ * if (alwaysTrue) {
+ * field++;
+ * } else {
+ * field--;
+ * }
+ * }
+ * }
+ * }</pre>
+ *
+ * @return generated bytecode.
+ */
+ private static byte[] generateTest(Label unstableIfLocation) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+ cw.visit(CLASS_FILE_VERSION, ACC_PUBLIC | ACC_ABSTRACT, CLASS_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitField(ACC_PUBLIC | ACC_STATIC | ACC_VOLATILE, FIELD_NAME,
+ "I", null, Integer.valueOf(0));
+
+ generateTestMethod(cw, unstableIfLocation);
+
+ return cw.toByteArray();
+ }
+
+ private static void generateTestMethod(ClassVisitor cv,
+ Label unstableIfLocation) {
+ MethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, METHOD_NAME,
+ "(Z)V", null, null);
+ mv.visitCode();
+
+ Label end = new Label();
+ Label falseBranch = new Label();
+
+ // push "field" field's value and 1 to stack
+ mv.visitFieldInsn(GETSTATIC, CLASS_NAME, FIELD_NAME, "I");
+ mv.visitInsn(ICONST_1);
+ // load argument's value
+ mv.visitVarInsn(ILOAD, 0); // alwaysTrue
+ // here is our unstable if
+ mv.visitLabel(unstableIfLocation);
+ mv.visitJumpInsn(IFEQ, falseBranch);
+ // increment on "true"
+ mv.visitInsn(IADD);
+ mv.visitJumpInsn(GOTO, end);
+ // decrement on "false"
+ mv.visitLabel(falseBranch);
+ mv.visitInsn(ISUB);
+ mv.visitLabel(end);
+ // bye bye
+ mv.visitInsn(RETURN);
+
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+}
+
--- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -34,6 +34,7 @@
/*
* @test
* @bug 8059624 8064669
+ * @ignore 8066998
* @library /testlibrary /../../test/lib
* @build ForceNMethodSweepTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
--- a/hotspot/test/gc/TestSmallHeap.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/gc/TestSmallHeap.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -26,34 +26,46 @@
* @bug 8067438
* @requires vm.gc=="null"
* @summary Verify that starting the VM with a small heap works
- * @library /testlibrary
- * @run main/othervm -Xmx4m -XX:+UseParallelGC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseSerialGC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseG1GC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseConcMarkSweepGC -XX:CMSMarkStackSizeMax=1032 TestSmallHeap
+ * @library /testlibrary /../../test/lib
+ * @build TestSmallHeap
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseParallelGC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap
*
- * Note: It would be nice to verify the minimal supported heap size here,
- * but that turns out to be quite tricky since we align the heap size based
- * on the card table size. And the card table size is aligned based on the
- * minimal pages size provided by the os. This means that on most platforms,
- * where the minimal page size is 4k, we get a minimal heap size of 2m but
- * on Solaris/Sparc we have a page size of 8k and get a minimal heap size
- * of 8m.
+ * Note: It would be nice to verify the minimal supported heap size (2m) here,
+ * but we align the heap size based on the card table size. And the card table
+ * size is aligned based on the minimal pages size provided by the os. This
+ * means that on most platforms, where the minimal page size is 4k, we get a
+ * minimal heap size of 2m but on Solaris/Sparc we have a page size of 8k and
+ * get a minimal heap size of 4m. And on platforms where the page size is 64k
+ * we get a minimal heap size of 32m. We never use large pages for the card table.
+ *
* There is also no check in the VM for verifying that the maximum heap size
* is larger than the supported minimal heap size. This means that specifying
- * -Xmx1m on the command line is fine but will give a heap of 2m (or 4m).
- * To work around these rather strange behaviors this test uses 4m for all
- * platforms.
+ * -Xmx1m on the command line is fine but will give a heap of 2m (or 4m or 32m).
+ *
+ * To work around these rather strange behaviors this test uses -Xmx2m but then
+ * calculates what the expected heap size should be. The calculation is a
+ * simplified version of the code in the VM. We assume that the card table will
+ * use one page. Each byte in the card table corresponds to 512 bytes on the heap.
+ * So, the expected heap size is page_size * 512.
*/
+import com.oracle.java.testlibrary.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+import sun.hotspot.WhiteBox;
import sun.management.ManagementFactoryHelper;
-import static com.oracle.java.testlibrary.Asserts.*;
public class TestSmallHeap {
public static void main(String[] args) {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ int pageSize = wb.getVMPageSize();
+ int heapBytesPerCard = 512;
+ long expectedMaxHeap = pageSize * heapBytesPerCard;
String maxHeap = ManagementFactoryHelper.getDiagnosticMXBean().getVMOption("MaxHeapSize").getValue();
- String expectedMaxHeap = "4194304";
- assertEQ(maxHeap, expectedMaxHeap);
+ assertEQ(Long.parseLong(maxHeap), expectedMaxHeap);
}
}
--- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java Wed Jul 05 20:15:59 2017 +0200
@@ -112,7 +112,7 @@
}
private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
- expectError(new String[] { gcflag, "-Xms8M", "-XX:InitialHeapSize=4M", "-version" });
+ expectError(new String[] { gcflag, "-Xms64M", "-XX:InitialHeapSize=32M", "-version" });
}
private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
--- a/hotspot/test/gc/g1/TestGCLogMessages.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java Wed Jul 05 20:15:59 2017 +0200
@@ -107,8 +107,8 @@
private static void testWithToSpaceExhaustionLogs() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
- "-Xmx10M",
- "-Xmn5M",
+ "-Xmx32M",
+ "-Xmn16M",
"-XX:+PrintGCDetails",
GCTestWithToSpaceExhaustion.class.getName());
@@ -120,8 +120,8 @@
output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
- "-Xmx10M",
- "-Xmn5M",
+ "-Xmx32M",
+ "-Xmn16M",
"-XX:+PrintGCDetails",
"-XX:+UnlockExperimentalVMOptions",
"-XX:G1LogLevel=finest",
@@ -151,7 +151,7 @@
private static byte[] garbage;
private static byte[] largeObject;
public static void main(String [] args) {
- largeObject = new byte[5*1024*1024];
+ largeObject = new byte[16*1024*1024];
System.out.println("Creating garbage");
// create 128MB of garbage. This should result in at least one GC,
// some of them with to-space exhaustion.
--- a/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java Wed Jul 05 20:15:59 2017 +0200
@@ -31,7 +31,9 @@
import com.oracle.java.testlibrary.*;
public class TestHumongousAllocInitialMark {
- private static final int heapSize = 200; // MB
+ // Heap sizes < 224 MB are increased to 224 MB if vm_page_size == 64K to
+ // fulfill alignment constraints.
+ private static final int heapSize = 224; // MB
private static final int heapRegionSize = 1; // MB
private static final int initiatingHeapOccupancyPercent = 50; // %
--- a/hotspot/test/runtime/6888954/vmerrors.sh Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/runtime/6888954/vmerrors.sh Wed Jul 05 20:15:59 2017 +0200
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, 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
@@ -71,11 +71,12 @@
# EXCEPTION_ACCESS_VIOLATION - Win-*
# SIGBUS - Solaris SPARC-64
# SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-*
+# SIGILL - Aix
#
# Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-*
# gets its signal at a PC in test_error_handler().
#
-bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
+bad_func_ptr_re='(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc='
guarantee_re='guarantee[(](str|num).*failed: *'
fatal_re='fatal error: *'
tail_1='.*expected null'
--- a/hotspot/test/runtime/7194254/Test7194254.java Sat Jan 24 23:23:06 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * 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 7194254
- * @summary Creates several threads with different java priorities and checks
- * whether jstack reports correct priorities for them.
- *
- * @ignore 8060219
- * @run main Test7194254
- */
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CyclicBarrier;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class Test7194254 {
-
- public static void main(String[] args) throws Exception {
- final int NUMBER_OF_JAVA_PRIORITIES =
- Thread.MAX_PRIORITY - Thread.MIN_PRIORITY + 1;
- final CyclicBarrier barrier =
- new CyclicBarrier(NUMBER_OF_JAVA_PRIORITIES + 1);
-
- for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) {
- final int priority = p;
- new Thread("Priority=" + p) {
- {
- setPriority(priority);
- }
- public void run() {
- try {
- barrier.await(); // 1st
- barrier.await(); // 2nd
- } catch (Exception exc) {
- // ignore
- }
- }
- }.start();
- }
- barrier.await(); // 1st
-
- int matches = 0;
- List<String> failed = new ArrayList<>();
- try {
- String pid = getPid();
- String jstack = System.getProperty("java.home") + "/../bin/jstack";
- Process process = new ProcessBuilder(jstack, pid)
- .redirectErrorStream(true).start();
- Pattern pattern = Pattern.compile(
- "\\\"Priority=(\\d+)\\\".* prio=(\\d+).*");
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(process.getInputStream()))) {
- String line;
- while((line = reader.readLine()) != null) {
- Matcher matcher = pattern.matcher(line);
- if (matcher.matches()) {
- matches += 1;
- String expected = matcher.group(1);
- String actual = matcher.group(2);
- if (!expected.equals(actual)) {
- failed.add(line);
- }
- }
- }
- }
- barrier.await(); // 2nd
- } finally {
- barrier.reset();
- }
-
- if (matches != NUMBER_OF_JAVA_PRIORITIES) {
- throw new AssertionError("matches: expected " +
- NUMBER_OF_JAVA_PRIORITIES + ", but was " + matches);
- }
- if (!failed.isEmpty()) {
- throw new AssertionError(failed.size() + ":" + failed);
- }
- System.out.println("Test passes.");
- }
-
- static String getPid() {
- RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean();
- String vmname = runtimebean.getName();
- int i = vmname.indexOf('@');
- if (i != -1) {
- vmname = vmname.substring(0, i);
- }
- return vmname;
- }
-
-}
-
--- a/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Wed Jul 05 20:15:59 2017 +0200
@@ -43,7 +43,7 @@
pb = ProcessTools.createJavaProcessBuilder("-XX:CompileCommandFile=hs_comp.txt", "-version");
output = new OutputAnalyzer(pb.start());
- output.shouldContain("CompilerOracle: unrecognized line");
+ output.shouldContain("CompileCommand: unrecognized command");
output.shouldContain("aaa aaa");
// Skip on debug builds since we'll always read the file there
--- a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Wed Jul 05 20:15:59 2017 +0200
@@ -27,6 +27,7 @@
* @summary Test that you can decrease NMT tracking level but not increase it.
* @key nmt
* @library /testlibrary /../../test/lib
+ * @ignore 8067167
* @build ChangeTrackingLevel
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java Wed Jul 05 20:15:59 2017 +0200
@@ -27,6 +27,7 @@
* @bug 8005936 8058606
* @summary Verify PrintNMTStatistics on normal JVM exit for detail and summary tracking level
* @library /testlibrary
+ * @ignore 8067167
*/
import com.oracle.java.testlibrary.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/MaxMetaspaceSize.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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 8067187
+ * @summary Testing CDS dumping with the -XX:MaxMetaspaceSize=<size> option
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class MaxMetaspaceSize {
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:MaxMetaspaceSize=20m", "-Xshare:dump");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("is not large enough.\nEither don't specify the -XX:MaxMetaspaceSize=<size>\nor increase the size to at least");
+ output.shouldHaveExitValue(2);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Thread/ThreadPriorities.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2015 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 7194254
+ * @summary Creates several threads with different java priorities and checks
+ * whether jstack reports correct priorities for them.
+ *
+ * @library /testlibrary
+ * @run main ThreadPriorities
+ */
+
+import java.util.ArrayList;
+import java.util.concurrent.CyclicBarrier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class ThreadPriorities {
+
+ public static void main(String[] args) throws Throwable {
+ final int NUMBER_OF_JAVA_PRIORITIES =
+ Thread.MAX_PRIORITY - Thread.MIN_PRIORITY + 1;
+ final CyclicBarrier barrier =
+ new CyclicBarrier(NUMBER_OF_JAVA_PRIORITIES + 1);
+
+ for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) {
+ final int priority = p;
+ new Thread("Priority=" + p) {
+ {
+ setPriority(priority);
+ }
+ public void run() {
+ try {
+ barrier.await(); // 1st
+ barrier.await(); // 2nd
+ } catch (Exception exc) {
+ // ignore
+ }
+ }
+ }.start();
+ }
+ barrier.await(); // 1st
+
+ int matches = 0;
+ ArrayList<String> failed = new ArrayList<>();
+ ProcessBuilder pb = new ProcessBuilder(
+ JDKToolFinder.getJDKTool("jstack"),
+ String.valueOf(ProcessTools.getProcessId()));
+
+ String[] output = new OutputAnalyzer(pb.start()).getOutput().split("\\n+");
+
+ Pattern pattern = Pattern.compile(
+ "\\\"Priority=(\\d+)\\\".* prio=(\\d+).*");
+ for (String line : output) {
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.matches()) {
+ matches += 1;
+ String expected = matcher.group(1);
+ String actual = matcher.group(2);
+ if (!expected.equals(actual)) {
+ failed.add(line);
+ }
+ }
+ }
+ barrier.await(); // 2nd
+ barrier.reset();
+
+ assertEquals(matches, NUMBER_OF_JAVA_PRIORITIES);
+ assertTrue(failed.isEmpty(), failed.size() + ":" + failed);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/Reallocate.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 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 8058897
+ * @library /testlibrary
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:MallocMaxTestWords=100m Reallocate
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class Reallocate {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+
+ long address = unsafe.allocateMemory(1);
+ assertNotEquals(address, 0L);
+
+ // Make sure we reallocate correctly
+ unsafe.putByte(address, Byte.MAX_VALUE);
+ address = unsafe.reallocateMemory(address, 2);
+ assertNotEquals(address, 0L);
+ assertEquals(unsafe.getByte(address), Byte.MAX_VALUE);
+
+ // Reallocating with a 0 size should return a null pointer
+ address = unsafe.reallocateMemory(address, 0);
+ assertEquals(address, 0L);
+
+ // Reallocating with a null pointer should result in a normal allocation
+ address = unsafe.reallocateMemory(0L, 1);
+ assertNotEquals(address, 0L);
+ unsafe.putByte(address, Byte.MAX_VALUE);
+ assertEquals(unsafe.getByte(address), Byte.MAX_VALUE);
+
+ // Make sure we can throw an OOME when we fail to reallocate due to OOM
+ try {
+ unsafe.reallocateMemory(address, 100 * 1024 * 1024 * 8);
+ } catch (OutOfMemoryError e) {
+ // Expected
+ return;
+ }
+ throw new RuntimeException("Did not get expected OOM");
+ }
+}
--- a/hotspot/test/runtime/whitebox/WBStackSize.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/runtime/whitebox/WBStackSize.java Wed Jul 05 20:15:59 2017 +0200
@@ -47,7 +47,7 @@
static final long K = 1024;
static final long MIN_STACK_SIZE = 8 * K;
- static final long MAX_STACK_SIZE_ALLOCATED_IN_MAIN = 200 * K; // current value is about 130k on 64-bit platforms
+ static final long MAX_STACK_SIZE_ALLOCATED_IN_MAIN = 150 * K; // current value is about 130k on 64-bit platforms
static final WhiteBox wb = WhiteBox.getWhiteBox();
@@ -82,8 +82,10 @@
public static void main(String[] args) {
long configStackSize = wb.getIntxVMFlag("ThreadStackSize") * K;
+ System.out.println("ThreadStackSize VM option: " + configStackSize);
- System.out.println("ThreadStackSize VM option: " + configStackSize);
+ long stackProtectionSize = wb.getIntxVMFlag("StackShadowPages") * wb.getVMPageSize();
+ System.out.println("Size of protected shadow pages: " + stackProtectionSize);
long actualStackSize = wb.getThreadStackSize();
System.out.println("Full stack size: " + actualStackSize);
@@ -96,14 +98,16 @@
long remainingStackSize = wb.getThreadRemainingStackSize();
System.out.println("Remaining stack size in main(): " + remainingStackSize);
- // Up to 200k can be already allocated by VM
+ // Up to 150k can be already allocated by VM and some space is used for stack protection.
+ long spaceAlreadyOccupied = MAX_STACK_SIZE_ALLOCATED_IN_MAIN + stackProtectionSize;
+
if (remainingStackSize > configStackSize
- || (configStackSize > MAX_STACK_SIZE_ALLOCATED_IN_MAIN
- && remainingStackSize < configStackSize - MAX_STACK_SIZE_ALLOCATED_IN_MAIN)) {
+ || (configStackSize > spaceAlreadyOccupied
+ && remainingStackSize < configStackSize - spaceAlreadyOccupied)) {
throw new RuntimeException("getThreadRemainingStackSize value [" + remainingStackSize
+ "] should be at least ThreadStackSize value [" + configStackSize + "] minus ["
- + MAX_STACK_SIZE_ALLOCATED_IN_MAIN + "]");
+ + spaceAlreadyOccupied + "]");
}
testStackOverflow();
--- a/hotspot/test/serviceability/dcmd/DynLibDcmdTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/serviceability/dcmd/DynLibDcmdTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -3,7 +3,7 @@
import com.oracle.java.testlibrary.Platform;
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -39,14 +39,16 @@
String result = DcmdUtil.executeDcmd("VM.dynlibs");
String osDependentBaseString = null;
- if (Platform.isSolaris()) {
+ if (Platform.isAix()) {
+ osDependentBaseString = "lib%s.so";
+ } else if (Platform.isLinux()) {
+ osDependentBaseString = "lib%s.so";
+ } else if (Platform.isOSX()) {
+ osDependentBaseString = "lib%s.dylib";
+ } else if (Platform.isSolaris()) {
osDependentBaseString = "lib%s.so";
} else if (Platform.isWindows()) {
osDependentBaseString = "%s.dll";
- } else if (Platform.isOSX()) {
- osDependentBaseString = "lib%s.dylib";
- } else if (Platform.isLinux()) {
- osDependentBaseString = "lib%s.so";
}
if (osDependentBaseString == null) {
--- a/hotspot/test/test_env.sh Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/test_env.sh Wed Jul 05 20:15:59 2017 +0200
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, 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
@@ -56,7 +56,7 @@
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
- SunOS | Linux | Darwin )
+ AIX | Darwin | Linux | SunOS )
NULL=/dev/null
PS=":"
FS="/"
@@ -133,26 +133,31 @@
fi
VM_OS="unknown"
-grep "solaris" vm_version.out > ${NULL}
+grep "aix" vm_version.out > ${NULL}
if [ $? = 0 ]
then
- VM_OS="solaris"
+ VM_OS="aix"
+fi
+grep "bsd" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+ VM_OS="bsd"
fi
grep "linux" vm_version.out > ${NULL}
if [ $? = 0 ]
then
VM_OS="linux"
fi
+grep "solaris" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+ VM_OS="solaris"
+fi
grep "windows" vm_version.out > ${NULL}
if [ $? = 0 ]
then
VM_OS="windows"
fi
-grep "bsd" vm_version.out > ${NULL}
-if [ $? = 0 ]
-then
- VM_OS="bsd"
-fi
VM_CPU="unknown"
grep "sparc" vm_version.out > ${NULL}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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,6 +68,18 @@
return dataModel.equals("64");
}
+ public static boolean isAix() {
+ return isOs("aix");
+ }
+
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
public static boolean isSolaris() {
return isOs("sunos");
}
@@ -76,14 +88,6 @@
return isOs("win");
}
- public static boolean isOSX() {
- return isOs("mac");
- }
-
- public static boolean isLinux() {
- return isOs("linux");
- }
-
private static boolean isOs(String osname) {
return osName.toLowerCase().startsWith(osname.toLowerCase());
}
@@ -140,7 +144,9 @@
*/
public static boolean shouldSAAttach() throws Exception {
- if (isLinux()) {
+ if (isAix()) {
+ return false; // SA not implemented.
+ } else if (isLinux()) {
return canPtraceAttachLinux();
} else if (isOSX()) {
return canAttachOSX();
--- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Sat Jan 24 23:23:06 2015 -0800
+++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Wed Jul 05 20:15:59 2017 +0200
@@ -45,7 +45,7 @@
private static enum MethodGroup {
ARCH("isARM", "isPPC", "isSparc", "isX86", "isX64"),
BITNESS("is32bit", "is64bit"),
- OS("isLinux", "isSolaris", "isWindows", "isOSX"),
+ OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"),
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"),
IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach",
"canPtraceAttachLinux", "canAttachOSX", "isTieredSupported");
--- a/jdk/.hgtags Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/.hgtags Wed Jul 05 20:15:59 2017 +0200
@@ -289,3 +289,4 @@
8cc4dc300041eb70a7a40e4b2431a8f4d4965ea4 jdk9-b44
9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45
efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46
+b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47
--- a/jdk/make/gendata/GendataPolicyJars.gmk Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/make/gendata/GendataPolicyJars.gmk Wed Jul 05 20:15:59 2017 +0200
@@ -35,65 +35,62 @@
US_EXPORT_POLICY_JAR_DST := \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/US_export_policy.jar
-ifneq ($(BUILD_CRYPTO), no)
-
- US_EXPORT_POLICY_JAR_LIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/US_export_policy.jar
- US_EXPORT_POLICY_JAR_UNLIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy.jar
+US_EXPORT_POLICY_JAR_LIMITED := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/limited/US_export_policy.jar
+US_EXPORT_POLICY_JAR_UNLIMITED := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy.jar
- ifndef OPENJDK
- #
- # In past releases, Oracle JDK has had a separately downloadable set of
- # policy files which has been a nightmare for deployment.
- #
- # Now if we're closed and limited (default for Oracle JDK), create
- # an "unlimited_policy" directory that contains the unlimited policy
- # files. It will be up to the user/deployer to make an informed choice
- # as to whether they are legally entitled to use the unlimited policy
- # file in their environment. Users/deployers simply need to overwrite
- # the files. Consult README.txt (below) for more info.
- #
- UNLIMITED_POLICY_DIR := \
- $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/unlimited_policy
- endif
+ifndef OPENJDK
+ #
+ # In past releases, Oracle JDK has had a separately downloadable set of
+ # policy files which has been a nightmare for deployment.
+ #
+ # Now if we're closed and limited (default for Oracle JDK), create
+ # an "unlimited_policy" directory that contains the unlimited policy
+ # files. It will be up to the user/deployer to make an informed choice
+ # as to whether they are legally entitled to use the unlimited policy
+ # file in their environment. Users/deployers simply need to overwrite
+ # the files. Consult README.txt (below) for more info.
+ #
+ UNLIMITED_POLICY_DIR := \
+ $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/unlimited_policy
+endif
- #
- # TODO fix so that SetupArchive does not write files into SRCS
- # then we don't need this extra copying
- #
- # NOTE: We currently do not place restrictions on our limited export
- # policy. This was not a typo. This means we are shipping the same file
- # for both limited and unlimited US_export_policy.jar. Only the local
- # policy file currently has restrictions.
- #
- US_EXPORT_POLICY_JAR_SRC_DIR := \
- $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited
- US_EXPORT_POLICY_JAR_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy_jar.tmp
+#
+# TODO fix so that SetupArchive does not write files into SRCS
+# then we don't need this extra copying
+#
+# NOTE: We currently do not place restrictions on our limited export
+# policy. This was not a typo. This means we are shipping the same file
+# for both limited and unlimited US_export_policy.jar. Only the local
+# policy file currently has restrictions.
+#
+US_EXPORT_POLICY_JAR_SRC_DIR := \
+ $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited
+US_EXPORT_POLICY_JAR_TMP := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy_jar.tmp
- $(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/%
+$(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/%
$(install-file)
- US_EXPORT_POLICY_JAR_DEPS := \
- $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
+US_EXPORT_POLICY_JAR_DEPS := \
+ $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
- $(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, \
- $(US_EXPORT_POLICY_JAR_DEPS), \
- SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
- SUFFIXES := .policy, \
- JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true))
+$(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, \
+ $(US_EXPORT_POLICY_JAR_DEPS), \
+ SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
+ SUFFIXES := .policy, \
+ JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \
+ EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
+ SKIP_METAINF := true))
- $(US_EXPORT_POLICY_JAR_LIMITED): \
- $(US_EXPORT_POLICY_JAR_UNLIMITED)
- $(ECHO) $(LOG_INFO) \
- Copying unlimited $(patsubst $(OUTPUT_ROOT)/%,%,$@)
- $(install-file)
+$(US_EXPORT_POLICY_JAR_LIMITED): \
+ $(US_EXPORT_POLICY_JAR_UNLIMITED)
+ $(ECHO) $(LOG_INFO) \
+ Copying unlimited $(patsubst $(OUTPUT_ROOT)/%,%,$@)
+ $(install-file)
- TARGETS += $(US_EXPORT_POLICY_JAR_LIMITED) $(US_EXPORT_POLICY_JAR_UNLIMITED)
-endif
+TARGETS += $(US_EXPORT_POLICY_JAR_LIMITED) $(US_EXPORT_POLICY_JAR_UNLIMITED)
ifeq ($(UNLIMITED_CRYPTO), true)
$(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_UNLIMITED)
@@ -119,57 +116,54 @@
LOCAL_POLICY_JAR_DST := \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/local_policy.jar
-ifneq ($(BUILD_CRYPTO), no)
+LOCAL_POLICY_JAR_LIMITED := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy.jar
+LOCAL_POLICY_JAR_UNLIMITED := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar
- LOCAL_POLICY_JAR_LIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy.jar
- LOCAL_POLICY_JAR_UNLIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar
+#
+# TODO fix so that SetupArchive does not write files into SRCS
+# then we don't need this extra copying
+#
+LOCAL_POLICY_JAR_LIMITED_TMP := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy_jar.tmp
+LOCAL_POLICY_JAR_UNLIMITED_TMP := \
+ $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy_jar.tmp
+
+$(LOCAL_POLICY_JAR_LIMITED_TMP)/%: \
+ $(JDK_TOPDIR)/make/data/cryptopolicy/limited/%
+ $(install-file)
+
+$(LOCAL_POLICY_JAR_UNLIMITED_TMP)/%: \
+ $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/%
+ $(install-file)
- #
- # TODO fix so that SetupArchive does not write files into SRCS
- # then we don't need this extra copying
- #
- LOCAL_POLICY_JAR_LIMITED_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy_jar.tmp
- LOCAL_POLICY_JAR_UNLIMITED_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy_jar.tmp
+$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_LIMITED, \
+ $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \
+ $(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \
+ SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \
+ SUFFIXES := .policy, \
+ JAR := $(LOCAL_POLICY_JAR_LIMITED), \
+ EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \
+ SKIP_METAINF := true))
- $(LOCAL_POLICY_JAR_LIMITED_TMP)/%: \
- $(JDK_TOPDIR)/make/data/cryptopolicy/limited/%
- $(install-file)
+$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_UNLIMITED, \
+ $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \
+ SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \
+ SUFFIXES := .policy, \
+ JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \
+ EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
+ SKIP_METAINF := true))
- $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/%: \
- $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/%
+TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED)
+
+ifndef OPENJDK
+ ifneq ($(UNLIMITED_CRYPTO), true)
+ $(UNLIMITED_POLICY_DIR)/README.txt: \
+ $(JDK_TOPDIR)/make/closed/data/cryptopolicy/README.txt
$(install-file)
- $(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_LIMITED, \
- $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \
- $(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \
- SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \
- SUFFIXES := .policy, \
- JAR := $(LOCAL_POLICY_JAR_LIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \
- SKIP_METAINF := true))
-
- $(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_UNLIMITED, \
- $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \
- SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \
- SUFFIXES := .policy, \
- JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true))
-
- TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED)
-
- ifndef OPENJDK
- ifneq ($(UNLIMITED_CRYPTO), true)
- $(UNLIMITED_POLICY_DIR)/README.txt: \
- $(JDK_TOPDIR)/make/closed/data/cryptopolicy/README.txt
- $(install-file)
-
- TARGETS += $(UNLIMITED_POLICY_DIR)/README.txt
- endif
+ TARGETS += $(UNLIMITED_POLICY_DIR)/README.txt
endif
endif
--- a/jdk/make/lib/Awt2dLibraries.gmk Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 20:15:59 2017 +0200
@@ -300,7 +300,6 @@
LIBAWT_XAWT_DIRS := \
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt_xawt \
- $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjawt \
$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/utility \
$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
--- a/jdk/make/src/classes/build/tools/module/ext.modules Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/make/src/classes/build/tools/module/ext.modules Wed Jul 05 20:15:59 2017 +0200
@@ -6,4 +6,4 @@
jdk.naming.dns
jdk.scripting.nashorn
jdk.zipfs
-oracle.accessbridge
+jdk.accessbridge
--- a/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 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
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = false;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Wed Jul 05 20:15:59 2017 +0200
@@ -149,7 +149,8 @@
* {@code getName}. If this {@code Class} object represents a
* primitive type, this method returns the name of the primitive type. If
* this {@code Class} object represents void this method returns
- * "void".
+ * "void". If this {@code Class} object represents an array type,
+ * this method returns "class " followed by {@code getName}.
*
* @return a string representation of this class object.
*/
@@ -174,6 +175,12 @@
* occur in canonical order. If there are no type parameters, the
* type parameter list is elided.
*
+ * For an array type, the string starts with the type name,
+ * followed by an angle-bracketed comma-separated list of the
+ * type's type parameters, if any, followed by a sequence of
+ * {@code []} characters, one set of brackets per dimension of
+ * the array.
+ *
* <p>Note that since information about the runtime representation
* of a type is being generated, modifiers not present on the
* originating source code or illegal on the originating source
@@ -189,29 +196,39 @@
return toString();
} else {
StringBuilder sb = new StringBuilder();
-
- // Class modifiers are a superset of interface modifiers
- int modifiers = getModifiers() & Modifier.classModifiers();
- if (modifiers != 0) {
- sb.append(Modifier.toString(modifiers));
+ Class<?> component = this;
+ int arrayDepth = 0;
+
+ if (isArray()) {
+ do {
+ arrayDepth++;
+ component = component.getComponentType();
+ } while (component.isArray());
+ sb.append(component.getName());
+ } else {
+ // Class modifiers are a superset of interface modifiers
+ int modifiers = getModifiers() & Modifier.classModifiers();
+ if (modifiers != 0) {
+ sb.append(Modifier.toString(modifiers));
+ sb.append(' ');
+ }
+
+ if (isAnnotation()) {
+ sb.append('@');
+ }
+ if (isInterface()) { // Note: all annotation types are interfaces
+ sb.append("interface");
+ } else {
+ if (isEnum())
+ sb.append("enum");
+ else
+ sb.append("class");
+ }
sb.append(' ');
- }
-
- if (isAnnotation()) {
- sb.append('@');
+ sb.append(getName());
}
- if (isInterface()) { // Note: all annotation types are interfaces
- sb.append("interface");
- } else {
- if (isEnum())
- sb.append("enum");
- else
- sb.append("class");
- }
- sb.append(' ');
- sb.append(getName());
-
- TypeVariable<?>[] typeparms = getTypeParameters();
+
+ TypeVariable<?>[] typeparms = component.getTypeParameters();
if (typeparms.length > 0) {
boolean first = true;
sb.append('<');
@@ -224,6 +241,9 @@
sb.append('>');
}
+ for (int i = 0; i < arrayDepth; i++)
+ sb.append("[]");
+
return sb.toString();
}
}
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015 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
@@ -1360,7 +1360,10 @@
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkClassLoaderPermission(this, Reflection.getCallerClass());
+ // Check access to the parent class loader
+ // If the caller's class loader is same as this class loader,
+ // permission check is performed.
+ checkClassLoaderPermission(parent, Reflection.getCallerClass());
}
return parent;
}
@@ -1503,6 +1506,11 @@
return caller.getClassLoader0();
}
+ /*
+ * Checks RuntimePermission("getClassLoader") permission
+ * if caller's class loader is not null and caller's class loader
+ * is not the same as or an ancestor of the given cl argument.
+ */
static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -1747,35 +1755,54 @@
private static String usr_paths[];
private static String sys_paths[];
- private static String[] initializePath(String propname) {
- String ldpath = System.getProperty(propname, "");
- String ps = File.pathSeparator;
- int ldlen = ldpath.length();
- int i, j, n;
- // Count the separators in the path
- i = ldpath.indexOf(ps);
- n = 0;
- while (i >= 0) {
- n++;
- i = ldpath.indexOf(ps, i + 1);
+ private static String[] initializePath(String propName) {
+ String ldPath = System.getProperty(propName, "");
+ int ldLen = ldPath.length();
+ char ps = File.pathSeparatorChar;
+ int psCount = 0;
+
+ if (ClassLoaderHelper.allowsQuotedPathElements &&
+ ldPath.indexOf('\"') >= 0) {
+ // First, remove quotes put around quoted parts of paths.
+ // Second, use a quotation mark as a new path separator.
+ // This will preserve any quoted old path separators.
+ char[] buf = new char[ldLen];
+ int bufLen = 0;
+ for (int i = 0; i < ldLen; ++i) {
+ char ch = ldPath.charAt(i);
+ if (ch == '\"') {
+ while (++i < ldLen &&
+ (ch = ldPath.charAt(i)) != '\"') {
+ buf[bufLen++] = ch;
+ }
+ } else {
+ if (ch == ps) {
+ psCount++;
+ ch = '\"';
+ }
+ buf[bufLen++] = ch;
+ }
+ }
+ ldPath = new String(buf, 0, bufLen);
+ ldLen = bufLen;
+ ps = '\"';
+ } else {
+ for (int i = ldPath.indexOf(ps); i >= 0;
+ i = ldPath.indexOf(ps, i + 1)) {
+ psCount++;
+ }
}
- // allocate the array of paths - n :'s = n + 1 path elements
- String[] paths = new String[n + 1];
-
- // Fill the array with paths from the ldpath
- n = i = 0;
- j = ldpath.indexOf(ps);
- while (j >= 0) {
- if (j - i > 0) {
- paths[n++] = ldpath.substring(i, j);
- } else if (j - i == 0) {
- paths[n++] = ".";
- }
- i = j + 1;
- j = ldpath.indexOf(ps, i);
+ String[] paths = new String[psCount + 1];
+ int pathStart = 0;
+ for (int j = 0; j < psCount; ++j) {
+ int pathEnd = ldPath.indexOf(ps, pathStart);
+ paths[j] = (pathStart < pathEnd) ?
+ ldPath.substring(pathStart, pathEnd) : ".";
+ pathStart = pathEnd + 1;
}
- paths[n] = ldpath.substring(i, ldlen);
+ paths[psCount] = (pathStart < ldLen) ?
+ ldPath.substring(pathStart, ldLen) : ".";
return paths;
}
--- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2014, 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
@@ -569,7 +569,7 @@
public NetworkInterface getNetworkInterface() throws SocketException {
NetworkInterface ni
= (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
- if (ni.getIndex() == 0) {
+ if ((ni.getIndex() == 0) || (ni.getIndex() == -1)) {
InetAddress[] addrs = new InetAddress[1];
addrs[0] = InetAddress.anyLocalAddress();
return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
--- a/jdk/src/java.base/share/classes/java/net/URI.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URI.java Wed Jul 05 20:15:59 2017 +0200
@@ -2637,6 +2637,11 @@
private static final long H_URIC_NO_SLASH
= H_UNRESERVED | H_ESCAPED | highMask(";?:@&=+$,");
+ // scope_id = alpha | digit | "_" | "."
+ private static final long L_SCOPE_ID
+ = L_ALPHANUM | lowMask("_.");
+ private static final long H_SCOPE_ID
+ = H_ALPHANUM | highMask("_.");
// -- Escaping and encoding --
@@ -3226,7 +3231,7 @@
if (r+1 == q) {
fail ("scope id expected");
}
- checkChars (r+1, q, L_ALPHANUM, H_ALPHANUM,
+ checkChars (r+1, q, L_SCOPE_ID, H_SCOPE_ID,
"scope id");
} else {
parseIPv6Reference(p, q);
--- a/jdk/src/java.base/share/classes/java/nio/channels/Channels.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/channels/Channels.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -579,12 +579,13 @@
* charset and writes the resulting bytes to the given channel.
*
* <p> An invocation of this method of the form
- * <p>
+ *
* <pre> {@code
* Channels.newWriter(ch, csname)
* } </pre>
+ *
* behaves in exactly the same way as the expression
- * <p>
+ *
* <pre> {@code
* Channels.newWriter(ch, Charset.forName(csName).newEncoder(), -1)
* } </pre>
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Wed Jul 05 20:15:59 2017 +0200
@@ -1835,7 +1835,7 @@
* <p> The maximum number of arguments is limited by the maximum dimension of a
* Java array as defined by
* <cite>The Java™ Virtual Machine Specification</cite>.
- * If the argument index is does not correspond to an
+ * If the argument index does not correspond to an
* available argument, then a {@link MissingFormatArgumentException} is thrown.
*
* <p> If there are more arguments than format specifiers, the extra arguments
--- a/jdk/src/java.base/share/classes/java/util/Hashtable.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Hashtable.java Wed Jul 05 20:15:59 2017 +0200
@@ -1137,10 +1137,10 @@
Entry<Object, Object> entryStack = null;
synchronized (this) {
- // Write out the length, threshold, loadfactor
+ // Write out the threshold and loadFactor
s.defaultWriteObject();
- // Write out length, count of elements
+ // Write out the length and count of elements
s.writeInt(table.length);
s.writeInt(count);
@@ -1169,22 +1169,33 @@
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
- // Read in the length, threshold, and loadfactor
+ // Read in the threshold and loadFactor
s.defaultReadObject();
+ // Validate loadFactor (ignore threshold - it will be re-computed)
+ if (loadFactor <= 0 || Float.isNaN(loadFactor))
+ throw new StreamCorruptedException("Illegal Load: " + loadFactor);
+
// Read the original length of the array and number of elements
int origlength = s.readInt();
int elements = s.readInt();
- // Compute new size with a bit of room 5% to grow but
- // no larger than the original size. Make the length
+ // Validate # of elements
+ if (elements < 0)
+ throw new StreamCorruptedException("Illegal # of Elements: " + elements);
+
+ // Clamp original length to be more than elements / loadFactor
+ // (this is the invariant enforced with auto-growth)
+ origlength = Math.max(origlength, (int)(elements / loadFactor) + 1);
+
+ // Compute new length with a bit of room 5% + 3 to grow but
+ // no larger than the clamped original length. Make the length
// odd if it's large enough, this helps distribute the entries.
// Guard against the length ending up zero, that's not valid.
- int length = (int)(elements * loadFactor) + (elements / 20) + 3;
+ int length = (int)((elements + elements / 20) / loadFactor) + 3;
if (length > elements && (length & 1) == 0)
length--;
- if (origlength > 0 && length > origlength)
- length = origlength;
+ length = Math.min(length, origlength);
table = new Entry<?,?>[length];
threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
count = 0;
@@ -1195,7 +1206,7 @@
K key = (K)s.readObject();
@SuppressWarnings("unchecked")
V value = (V)s.readObject();
- // synch could be eliminated for performance
+ // sync is eliminated for performance
reconstitutionPut(table, key, value);
}
}
@@ -1207,9 +1218,9 @@
*
* <p>This differs from the regular put method in several ways. No
* checking for rehashing is necessary since the number of elements
- * initially in the table is known. The modCount is not incremented
- * because we are creating a new instance. Also, no return value
- * is needed.
+ * initially in the table is known. The modCount is not incremented and
+ * there's no synchronization because we are creating a new instance.
+ * Also, no return value is needed.
*/
private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
throws StreamCorruptedException
--- a/jdk/src/java.base/share/classes/java/util/Spliterator.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Spliterator.java Wed Jul 05 20:15:59 2017 +0200
@@ -125,7 +125,7 @@
* are encountered.
*
* @apiNote
- * <p>Spliterators, like {@code Iterators}s, are for traversing the elements of
+ * <p>Spliterators, like {@code Iterator}s, are for traversing the elements of
* a source. The {@code Spliterator} API was designed to support efficient
* parallel traversal in addition to sequential traversal, by supporting
* decomposition as well as single-element iteration. In addition, the
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Wed Jul 05 20:15:59 2017 +0200
@@ -978,7 +978,15 @@
}
try {
@SuppressWarnings("unchecked") T t = (T) r;
- return f.apply(t).toCompletableFuture();
+ CompletableFuture<V> g = f.apply(t).toCompletableFuture();
+ Object s = g.result;
+ if (s != null)
+ return new CompletableFuture<V>(encodeRelay(s));
+ CompletableFuture<V> d = new CompletableFuture<V>();
+ UniRelay<V> copy = new UniRelay<V>(d, g);
+ g.push(copy);
+ copy.tryFire(SYNC);
+ return d;
} catch (Throwable ex) {
return new CompletableFuture<V>(encodeThrowable(ex));
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Jul 05 20:15:59 2017 +0200
@@ -337,6 +337,7 @@
/* try auth without calling Authenticator. Used for transparent NTLM authentication */
private boolean tryTransparentNTLMServer = true;
private boolean tryTransparentNTLMProxy = true;
+ private boolean useProxyResponseCode = false;
/* Used by Windows specific code */
private Object authObj;
@@ -2239,6 +2240,15 @@
if (tryTransparentNTLMProxy) {
tryTransparentNTLMProxy =
NTLMAuthenticationProxy.supportsTransparentAuth;
+ /* If the platform supports transparent authentication
+ * then normally it's ok to do transparent auth to a proxy
+ * because we generally trust proxies (chosen by the user)
+ * But not in the case of 305 response where the server
+ * chose it. */
+ if (tryTransparentNTLMProxy && useProxyResponseCode) {
+ tryTransparentNTLMProxy = false;
+ }
+
}
a = null;
if (tryTransparentNTLMProxy) {
@@ -2610,6 +2620,10 @@
requests.set(0, method + " " + getRequestURI()+" " +
httpVersion, null);
connected = true;
+ // need to remember this in case NTLM proxy authentication gets
+ // used. We can't use transparent authentication when user
+ // doesn't know about proxy.
+ useProxyResponseCode = true;
} else {
// maintain previous headers, just change the name
// of the file we're getting
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Wed Jul 05 20:15:59 2017 +0200
@@ -192,22 +192,6 @@
return userAgent;
}
- // should remove once HttpClient.newHttpProxy is putback
- private static Proxy newHttpProxy(String proxyHost, int proxyPort) {
- InetSocketAddress saddr = null;
- final String phost = proxyHost;
- final int pport = proxyPort < 0 ? httpsPortNumber : proxyPort;
- try {
- saddr = java.security.AccessController.doPrivileged(new
- java.security.PrivilegedExceptionAction<InetSocketAddress>() {
- public InetSocketAddress run() {
- return new InetSocketAddress(phost, pport);
- }});
- } catch (java.security.PrivilegedActionException pae) {
- }
- return new Proxy(Proxy.Type.HTTP, saddr);
- }
-
// CONSTRUCTOR, FACTORY
@@ -251,7 +235,7 @@
throws IOException {
this(sf, url,
(proxyHost == null? null:
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
+ HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
connectTimeout);
}
@@ -261,6 +245,11 @@
HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy,
int connectTimeout)
throws IOException {
+ PlatformLogger logger = HttpURLConnection.getHttpLogger();
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Creating new HttpsClient with url:" + url + " and proxy:" + proxy +
+ " with connect timeout:" + connectTimeout);
+ }
this.proxy = proxy;
setSSLSocketFactory(sf);
this.proxyDisabled = true;
@@ -317,7 +306,7 @@
return HttpsClient.New(sf, url, hv,
(proxyHost == null? null :
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
+ HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
useCache, connectTimeout, httpuc);
}
@@ -329,6 +318,11 @@
if (p == null) {
p = Proxy.NO_PROXY;
}
+ PlatformLogger logger = HttpURLConnection.getHttpLogger();
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Looking for HttpClient for URL " + url +
+ " and proxy value of " + p);
+ }
HttpsClient ret = null;
if (useCache) {
/* see if one's already around */
@@ -342,14 +336,13 @@
if (ret != null) {
if ((ret.proxy != null && ret.proxy.equals(p)) ||
- (ret.proxy == null && p == null)) {
+ (ret.proxy == null && p == Proxy.NO_PROXY)) {
synchronized (ret) {
ret.cachedHttpClient = true;
assert ret.inCache;
ret.inCache = false;
if (httpuc != null && ret.needsTunneling())
httpuc.setTunnelState(TUNNELING);
- PlatformLogger logger = HttpURLConnection.getHttpLogger();
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
logger.finest("KeepAlive stream retrieved from the cache, " + ret);
}
@@ -360,6 +353,9 @@
// This should be fine as it is very rare that a connection
// to the same host will not use the same proxy.
synchronized(ret) {
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Not returning this connection to cache: " + ret);
+ }
ret.inCache = false;
ret.closeServer();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/FileInputStreamPool.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014, 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.provider;
+
+import java.io.*;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A pool of {@code InputStream}s opened from distinct files. Only a single
+ * instance is ever opened from the same file. This is used to read special
+ * infinite files like {@code /dev/random} where the current file pointer is not
+ * relevant, so multiple readers can share the same file descriptor and
+ * consequently the same {@code InputStream}.
+ */
+class FileInputStreamPool {
+
+ /**
+ * a pool of: StreamRef -> UnclosableInputStream -> FileInputStream(s)
+ */
+ private static final ConcurrentMap<File, StreamRef> pool =
+ new ConcurrentHashMap<>();
+
+ /**
+ * a reference queue of cleared StreamRef(s)
+ */
+ private static final ReferenceQueue<UnclosableInputStream> refQueue =
+ new ReferenceQueue<>();
+
+ /**
+ * This method opens an underlying {@link java.io.FileInputStream} for a
+ * given {@code file} and returns a wrapper over it. The wrapper is shared
+ * among multiple readers of the same {@code file} and ignores
+ * {@link java.io.InputStream#close()} requests. The underlying stream is
+ * closed when all references to the wrapper are relinquished.
+ *
+ * @param file the file to be opened for reading.
+ * @return a shared {@link java.io.InputStream} instance opened from given
+ * file.
+ * @throws FileNotFoundException if the file does not exist, is a directory
+ * rather than a regular file, or for some
+ * other reason cannot be opened for reading.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkRead</code> method denies read
+ * access to the file.
+ */
+ static InputStream getInputStream(File file) throws IOException {
+
+ // expunge any cleared references
+ StreamRef oldRref;
+ while ((oldRref = (StreamRef) refQueue.poll()) != null) {
+ pool.remove(oldRref.file, oldRref);
+ }
+
+ // canonicalize the path
+ // (this also checks the read permission on the file if SecurityManager
+ // is present, so no checking is needed later when we just return the
+ // already opened stream)
+ File cfile = file.getCanonicalFile();
+
+ // check if it exists in pool
+ oldRref = pool.get(cfile);
+ UnclosableInputStream oldStream = (oldRref == null)
+ ? null
+ : oldRref.get();
+ StreamRef newRef = null;
+ UnclosableInputStream newStream = null;
+
+ // retry loop
+ while (true) {
+ if (oldStream != null) {
+ // close our optimistically opened stream 1st (if we opened it)
+ if (newStream != null) {
+ try {
+ newStream.getWrappedStream().close();
+ } catch (IOException ignore) {
+ // can't do anything here
+ }
+ }
+ // return it
+ return oldStream;
+ } else {
+ // we need to open new stream optimistically (if not already)
+ if (newStream == null) {
+ newStream = new UnclosableInputStream(
+ new FileInputStream(cfile));
+ newRef = new StreamRef(cfile, newStream, refQueue);
+ }
+ // either try to install newRef or replace oldRef with newRef
+ if (oldRref == null) {
+ oldRref = pool.putIfAbsent(cfile, newRef);
+ } else {
+ oldRref = pool.replace(cfile, oldRref, newRef)
+ ? null
+ : pool.get(cfile);
+ }
+ if (oldRref == null) {
+ // success
+ return newStream;
+ } else {
+ // lost race
+ oldStream = oldRref.get();
+ // another loop
+ }
+ }
+ }
+ }
+
+ private static class StreamRef extends WeakReference<UnclosableInputStream> {
+ final File file;
+
+ StreamRef(File file,
+ UnclosableInputStream stream,
+ ReferenceQueue<UnclosableInputStream> refQueue) {
+ super(stream, refQueue);
+ this.file = file;
+ }
+ }
+
+ private static final class UnclosableInputStream extends FilterInputStream {
+ UnclosableInputStream(InputStream in) {
+ super(in);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Ignore close attempts since underlying InputStream is shared.
+ }
+
+ InputStream getWrappedStream() {
+ return in;
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java Wed Jul 05 20:15:59 2017 +0200
@@ -504,9 +504,10 @@
@Override
public InputStream run() throws IOException {
/*
- * return a FileInputStream for file URLs and
- * avoid buffering. The openStream() call wraps
- * InputStream in a BufferedInputStream which
+ * return a shared InputStream for file URLs and
+ * avoid buffering.
+ * The URL.openStream() call wraps InputStream in a
+ * BufferedInputStream which
* can buffer up to 8K bytes. This read is a
* performance issue for entropy sources which
* can be slow to replenish.
@@ -514,7 +515,8 @@
if (device.getProtocol().equalsIgnoreCase("file")) {
File deviceFile =
SunEntries.getDeviceFile(device);
- return new FileInputStream(deviceFile);
+ return FileInputStreamPool
+ .getInputStream(deviceFile);
} else {
return device.openStream();
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Wed Jul 05 20:15:59 2017 +0200
@@ -345,6 +345,13 @@
break;
case HandshakeMessage.ht_finished:
+ // A ChangeCipherSpec record must have been received prior to
+ // reception of the Finished message (RFC 5246, 7.4.9).
+ if (!receivedChangeCipherSpec()) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Received Finished message before ChangeCipherSpec");
+ }
+
this.serverFinished(
new Finished(protocolVersion, input, cipherSuite));
break;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -243,6 +243,7 @@
protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
clnt_random = new RandomCookie(s);
sessionId = new SessionId(s.getBytes8());
+ sessionId.checkLength(protocolVersion);
cipherSuites = new CipherSuiteList(s);
compression_methods = s.getBytes8();
if (messageLength() != messageLength) {
@@ -355,6 +356,7 @@
input.getInt8());
svr_random = new RandomCookie(input);
sessionId = new SessionId(input.getBytes8());
+ sessionId.checkLength(protocolVersion);
cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
compression_method = (byte)input.getInt8();
if (messageLength() != messageLength) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Wed Jul 05 20:15:59 2017 +0200
@@ -95,8 +95,6 @@
Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
/*
-
- /*
* List of active protocols
*
* Active protocols is a subset of enabled protocols, and will
@@ -114,10 +112,8 @@
private CipherSuiteList activeCipherSuites;
// The server name indication and matchers
- List<SNIServerName> serverNames =
- Collections.<SNIServerName>emptyList();
- Collection<SNIMatcher> sniMatchers =
- Collections.<SNIMatcher>emptyList();
+ List<SNIServerName> serverNames = Collections.<SNIServerName>emptyList();
+ Collection<SNIMatcher> sniMatchers = Collections.<SNIMatcher>emptyList();
private boolean isClient;
private boolean needCertVerify;
@@ -139,12 +135,16 @@
// current key exchange. Never null, initially K_NULL
KeyExchange keyExchange;
- /* True if this session is being resumed (fast handshake) */
+ // True if this session is being resumed (fast handshake)
boolean resumingSession;
- /* True if it's OK to start a new SSL session */
+ // True if it's OK to start a new SSL session
boolean enableNewSession;
+ // True if session keys have been calculated and the caller may receive
+ // and process a ChangeCipherSpec message
+ private boolean sessKeysCalculated;
+
// Whether local cipher suites preference should be honored during
// handshaking?
//
@@ -253,6 +253,7 @@
this.serverVerifyData = serverVerifyData;
enableNewSession = true;
invalidated = false;
+ sessKeysCalculated = false;
setCipherSuite(CipherSuite.C_NULL);
setEnabledProtocols(enabledProtocols);
@@ -359,6 +360,14 @@
}
}
+ final boolean receivedChangeCipherSpec() {
+ if (conn != null) {
+ return conn.receivedChangeCipherSpec();
+ } else {
+ return engine.receivedChangeCipherSpec();
+ }
+ }
+
String getEndpointIdentificationAlgorithmSE() {
SSLParameters paras;
if (conn != null) {
@@ -491,7 +500,9 @@
if (activeProtocols.collection().isEmpty() ||
activeProtocols.max.v == ProtocolVersion.NONE.v) {
- throw new SSLHandshakeException("No appropriate protocol");
+ throw new SSLHandshakeException(
+ "No appropriate protocol (protocol is disabled or " +
+ "cipher suites are inappropriate)");
}
if (activeCipherSuites == null) {
@@ -676,6 +687,17 @@
continue;
}
+ if (!algorithmConstraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ protocol.name, null)) {
+ if (debug != null && Debug.isOn("verbose")) {
+ System.out.println(
+ "Ignoring disabled protocol: " + protocol);
+ }
+
+ continue;
+ }
+
boolean found = false;
for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.isAvailable() && suite.obsoleted > protocol.v &&
@@ -1081,7 +1103,6 @@
calculateConnectionKeys(master);
}
-
/*
* Calculate the master secret from its various components. This is
* used for key exchange by all cipher suites.
@@ -1226,6 +1247,10 @@
throw new ProviderException(e);
}
+ // Mark a flag that allows outside entities (like SSLSocket/SSLEngine)
+ // determine if a ChangeCipherSpec message could be processed.
+ sessKeysCalculated = true;
+
//
// Dump the connection keys as they're generated.
//
@@ -1280,6 +1305,15 @@
}
}
+ /**
+ * Return whether or not the Handshaker has derived session keys for
+ * this handshake. This is used for determining readiness to process
+ * an incoming ChangeCipherSpec message.
+ */
+ boolean sessionKeysCalculated() {
+ return sessKeysCalculated;
+ }
+
private static void printHex(HexDumpEncoder dump, byte[] bytes) {
if (bytes == null) {
System.out.println("(key bytes not available)");
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java Wed Jul 05 20:15:59 2017 +0200
@@ -25,6 +25,9 @@
package sun.security.ssl;
+import java.util.*;
+import java.security.CryptoPrimitive;
+
/**
* Type safe enum for an SSL/TLS protocol version. Instances are obtained
* using the static factory methods or by referencing the static members
@@ -86,6 +89,11 @@
// Default version for hello messages (SSLv2Hello)
final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
+ // Available protocols
+ //
+ // Including all supported protocols except the disabled ones.
+ final static Set<ProtocolVersion> availableProtocols;
+
// version in 16 bit MSB format as it appears in records and
// messages, i.e. 0x0301 for TLS 1.0
public final int v;
@@ -96,6 +104,25 @@
// name used in JSSE (e.g. TLSv1 for TLS 1.0)
final String name;
+ // Initialize the available protocols.
+ static {
+ Set<ProtocolVersion> protocols = new HashSet<>(5);
+
+ ProtocolVersion[] pvs = new ProtocolVersion[] {
+ SSL20Hello, SSL30, TLS10, TLS11, TLS12};
+ EnumSet<CryptoPrimitive> cryptoPrimitives =
+ EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT);
+ for (ProtocolVersion p : pvs) {
+ if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits(
+ cryptoPrimitives, p.name, null)) {
+ protocols.add(p);
+ }
+ }
+
+ availableProtocols =
+ Collections.<ProtocolVersion>unmodifiableSet(protocols);
+ }
+
// private
private ProtocolVersion(int v, String name) {
this.v = v;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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,6 +55,14 @@
private boolean enabledX509DisabledAlgConstraints = true;
+ // the default algorithm constraints
+ final static AlgorithmConstraints DEFAULT =
+ new SSLAlgorithmConstraints(null);
+
+ // the default SSL only algorithm constraints
+ final static AlgorithmConstraints DEFAULT_SSL_ONLY =
+ new SSLAlgorithmConstraints((SSLSocket)null, false);
+
SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
userAlgConstraints = algorithmConstraints;
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -52,10 +52,6 @@
private X509TrustManager trustManager;
private SecureRandom secureRandom;
- // The default algrithm constraints
- private AlgorithmConstraints defaultAlgorithmConstraints =
- new SSLAlgorithmConstraints(null);
-
// supported and default protocols
private ProtocolList defaultServerProtocolList;
private ProtocolList defaultClientProtocolList;
@@ -350,7 +346,7 @@
if (suite.isAvailable() &&
suite.obsoleted > protocols.min.v &&
suite.supported <= protocols.max.v) {
- if (defaultAlgorithmConstraints.permits(
+ if (SSLAlgorithmConstraints.DEFAULT.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
suite.name, null)) {
suites.add(suite);
@@ -431,11 +427,16 @@
*/
private abstract static class AbstractSSLContext extends SSLContextImpl {
// parameters
- private final static SSLParameters defaultServerSSLParams;
- private final static SSLParameters supportedSSLParams;
+ private static final SSLParameters defaultServerSSLParams;
+ private static final SSLParameters supportedSSLParams;
static {
+ // supported SSL parameters
supportedSSLParams = new SSLParameters();
+
+ // candidates for available protocols
+ ProtocolVersion[] candidates;
+
if (SunJSSE.isFIPS()) {
supportedSSLParams.setProtocols(new String[] {
ProtocolVersion.TLS10.name,
@@ -443,7 +444,11 @@
ProtocolVersion.TLS12.name
});
- defaultServerSSLParams = supportedSSLParams;
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
} else {
supportedSSLParams.setProtocols(new String[] {
ProtocolVersion.SSL20Hello.name,
@@ -453,8 +458,18 @@
ProtocolVersion.TLS12.name
});
- defaultServerSSLParams = supportedSSLParams;
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.SSL20Hello,
+ ProtocolVersion.SSL30,
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
}
+
+ defaultServerSSLParams = new SSLParameters();
+ defaultServerSSLParams.setProtocols(
+ getAvailableProtocols(candidates));
}
@Override
@@ -466,6 +481,22 @@
SSLParameters getSupportedSSLParams() {
return supportedSSLParams;
}
+
+ static String[] getAvailableProtocols(
+ ProtocolVersion[] protocolCandidates) {
+
+ List<String> availableProtocols = Collections.<String>emptyList();
+ if (protocolCandidates != null && protocolCandidates.length != 0) {
+ availableProtocols = new ArrayList<>(protocolCandidates.length);
+ for (ProtocolVersion p : protocolCandidates) {
+ if (ProtocolVersion.availableProtocols.contains(p)) {
+ availableProtocols.add(p.name);
+ }
+ }
+ }
+
+ return availableProtocols.toArray(new String[0]);
+ }
}
/*
@@ -474,21 +505,25 @@
* @see SSLContext
*/
public static final class TLS10Context extends AbstractSSLContext {
- private final static SSLParameters defaultClientSSLParams;
+ private static final SSLParameters defaultClientSSLParams;
static {
- defaultClientSSLParams = new SSLParameters();
+ // candidates for available protocols
+ ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name
- });
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.TLS10
+ };
+ } else {
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.SSL30,
+ ProtocolVersion.TLS10
+ };
+ }
- } else {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name
- });
- }
+ defaultClientSSLParams = new SSLParameters();
+ defaultClientSSLParams.setProtocols(
+ getAvailableProtocols(candidates));
}
@Override
@@ -503,23 +538,27 @@
* @see SSLContext
*/
public static final class TLS11Context extends AbstractSSLContext {
- private final static SSLParameters defaultClientSSLParams;
+ private static final SSLParameters defaultClientSSLParams;
static {
- defaultClientSSLParams = new SSLParameters();
+ // candidates for available protocols
+ ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name
- });
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11
+ };
+ } else {
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.SSL30,
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11
+ };
+ }
- } else {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name
- });
- }
+ defaultClientSSLParams = new SSLParameters();
+ defaultClientSSLParams.setProtocols(
+ getAvailableProtocols(candidates));
}
@Override
@@ -534,25 +573,29 @@
* @see SSLContext
*/
public static final class TLS12Context extends AbstractSSLContext {
- private final static SSLParameters defaultClientSSLParams;
+ private static final SSLParameters defaultClientSSLParams;
static {
- defaultClientSSLParams = new SSLParameters();
+ // candidates for available protocols
+ ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
+ } else {
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.SSL30,
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
+ }
- } else {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
- }
+ defaultClientSSLParams = new SSLParameters();
+ defaultClientSSLParams.setProtocols(
+ getAvailableProtocols(candidates));
}
@Override
@@ -567,8 +610,8 @@
* @see SSLContext
*/
private static class CustomizedSSLContext extends AbstractSSLContext {
- private final static String PROPERTY_NAME = "jdk.tls.client.protocols";
- private final static SSLParameters defaultClientSSLParams;
+ private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
+ private static final SSLParameters defaultClientSSLParams;
private static IllegalArgumentException reservedException = null;
// Don't want a java.lang.LinkageError for illegal system property.
@@ -578,60 +621,74 @@
// the provider service. Instead, let's handle the initialization
// exception in constructor.
static {
+ // candidates for available protocols
+ ProtocolVersion[] candidates;
+
String property = AccessController.doPrivileged(
new GetPropertyAction(PROPERTY_NAME));
- defaultClientSSLParams = new SSLParameters();
if (property == null || property.length() == 0) {
// the default enabled client TLS protocols
if (SunJSSE.isFIPS()) {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
} else {
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
+ candidates = new ProtocolVersion[] {
+ ProtocolVersion.SSL30,
+ ProtocolVersion.TLS10,
+ ProtocolVersion.TLS11,
+ ProtocolVersion.TLS12
+ };
}
} else {
// remove double quote marks from beginning/end of the property
- if (property.charAt(0) == '"' &&
+ if (property.length() > 1 && property.charAt(0) == '"' &&
property.charAt(property.length() - 1) == '"') {
property = property.substring(1, property.length() - 1);
}
- String[] protocols = property.split(",");
+ String[] protocols = null;
+ if (property != null && property.length() != 0) {
+ protocols = property.split(",");
+ } else {
+ reservedException = new IllegalArgumentException(
+ "No protocol specified in " +
+ PROPERTY_NAME + " system property");
+ protocols = new String[0];
+ }
+
+ candidates = new ProtocolVersion[protocols.length];
for (int i = 0; i < protocols.length; i++) {
protocols[i] = protocols[i].trim();
// Is it a supported protocol name?
try {
- ProtocolVersion.valueOf(protocols[i]);
+ candidates[i] = ProtocolVersion.valueOf(protocols[i]);
} catch (IllegalArgumentException iae) {
reservedException = new IllegalArgumentException(
- PROPERTY_NAME + ": " + protocols[i] +
- " is not a standard SSL protocol name", iae);
+ PROPERTY_NAME + ": " + protocols[i] +
+ " is not a standard SSL/TLS protocol name", iae);
+ break;
}
}
if ((reservedException == null) && SunJSSE.isFIPS()) {
- for (String protocol : protocols) {
- if (ProtocolVersion.SSL20Hello.name.equals(protocol) ||
- ProtocolVersion.SSL30.name.equals(protocol)) {
+ for (ProtocolVersion protocolVersion : candidates) {
+ if (ProtocolVersion.SSL20Hello.v == protocolVersion.v ||
+ ProtocolVersion.SSL30.v == protocolVersion.v) {
reservedException = new IllegalArgumentException(
- PROPERTY_NAME + ": " + protocol +
+ PROPERTY_NAME + ": " + protocolVersion +
" is not FIPS compliant");
}
}
}
+ }
- if (reservedException == null) {
- defaultClientSSLParams.setProtocols(protocols);
- }
+ defaultClientSSLParams = new SSLParameters();
+ if (reservedException == null) {
+ defaultClientSSLParams.setProtocols(
+ getAvailableProtocols(candidates));
}
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -212,6 +212,11 @@
static final byte clauth_required = 2;
/*
+ * Flag indicating that the engine has received a ChangeCipherSpec message.
+ */
+ private boolean receivedCCS;
+
+ /*
* Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that
* a change cipher spec message is followed by a finished message.
@@ -372,6 +377,7 @@
*/
roleIsServer = true;
connectionState = cs_START;
+ receivedCCS = false;
// default server name indication
serverNames =
@@ -1021,6 +1027,7 @@
if (handshaker.invalidated) {
handshaker = null;
+ receivedCCS = false;
// if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA;
@@ -1039,6 +1046,7 @@
}
handshaker = null;
connectionState = cs_DATA;
+ receivedCCS = false;
// No handshakeListeners here. That's a
// SSLSocket thing.
@@ -1078,13 +1086,25 @@
case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE)
- || inputRecord.available() != 1
- || inputRecord.read() != 1) {
+ || !handshaker.sessionKeysCalculated()
+ || receivedCCS) {
+ // For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message,
- "illegal change cipher spec msg, state = "
- + connectionState);
+ "illegal change cipher spec msg, conn state = "
+ + connectionState + ", handshake state = "
+ + handshaker.state);
+ } else if (inputRecord.available() != 1
+ || inputRecord.read() != 1) {
+ // For structural/content issues with the CCS
+ fatal(Alerts.alert_unexpected_message,
+ "Malformed change cipher spec msg");
}
+ // Once we've received CCS, update the flag.
+ // If the remote endpoint sends it again in this handshake
+ // we won't process it.
+ receivedCCS = true;
+
//
// The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record,
@@ -2121,6 +2141,14 @@
}
/**
+ * Returns a boolean indicating whether the ChangeCipherSpec message
+ * has been received for this handshake.
+ */
+ boolean receivedChangeCipherSpec() {
+ return receivedCCS;
+ }
+
+ /**
* Returns a printable representation of this end of the connection.
*/
@Override
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -172,6 +172,12 @@
private volatile int connectionState;
/*
+ * Flag indicating that the engine's handshaker has done the necessary
+ * steps so the engine may process a ChangeCipherSpec message.
+ */
+ private boolean receivedCCS;
+
+ /*
* Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that
* a change cipher spec message is followed by a finished message.
@@ -587,6 +593,7 @@
*/
roleIsServer = isServer;
connectionState = cs_START;
+ receivedCCS = false;
/*
* default read and write side cipher and MAC support
@@ -1045,6 +1052,7 @@
if (handshaker.invalidated) {
handshaker = null;
+ receivedCCS = false;
// if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA;
@@ -1060,6 +1068,7 @@
handshakeSession = null;
handshaker = null;
connectionState = cs_DATA;
+ receivedCCS = false;
//
// Tell folk about handshake completion, but do
@@ -1107,13 +1116,24 @@
case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE)
- || r.available() != 1
- || r.read() != 1) {
+ || !handshaker.sessionKeysCalculated()
+ || receivedCCS) {
+ // For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message,
- "illegal change cipher spec msg, state = "
- + connectionState);
+ "illegal change cipher spec msg, conn state = "
+ + connectionState + ", handshake state = "
+ + handshaker.state);
+ } else if (r.available() != 1 || r.read() != 1) {
+ // For structural/content issues with the CCS
+ fatal(Alerts.alert_unexpected_message,
+ "Malformed change cipher spec msg");
}
+ // Once we've received CCS, update the flag.
+ // If the remote endpoint sends it again in this handshake
+ // we won't process it.
+ receivedCCS = true;
+
//
// The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record,
@@ -2590,6 +2610,14 @@
}
/**
+ * Returns a boolean indicating whether the ChangeCipherSpec message
+ * has been received for this handshake.
+ */
+ boolean receivedChangeCipherSpec() {
+ return receivedCCS;
+ }
+
+ /**
* Returns a printable representation of this end of the connection.
*/
@Override
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Wed Jul 05 20:15:59 2017 +0200
@@ -287,6 +287,13 @@
break;
case HandshakeMessage.ht_finished:
+ // A ChangeCipherSpec record must have been received prior to
+ // reception of the Finished message (RFC 5246, 7.4.9).
+ if (!receivedChangeCipherSpec()) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Received Finished message before ChangeCipherSpec");
+ }
+
this.clientFinished(
new Finished(protocolVersion, input, cipherSuite));
break;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java Wed Jul 05 20:15:59 2017 +0200
@@ -27,6 +27,7 @@
package sun.security.ssl;
import java.security.SecureRandom;
+import javax.net.ssl.SSLProtocolException;
/**
* Encapsulates an SSL session ID. SSL Session IDs are not reused by
@@ -41,6 +42,7 @@
final
class SessionId
{
+ static int MAX_LENGTH = 32;
private byte sessionId []; // max 32 bytes
/** Constructs a new session ID ... perhaps for a rejoinable session */
@@ -114,4 +116,19 @@
}
return true;
}
+
+ /**
+ * Checks the length of the session ID to make sure it sits within
+ * the range called out in the specification
+ */
+ void checkLength(ProtocolVersion pv) throws SSLProtocolException {
+ // As of today all versions of TLS have a 32-byte maximum length.
+ // In the future we can do more here to support protocol versions
+ // that may have longer max lengths.
+ if (sessionId.length > MAX_LENGTH) {
+ throw new SSLProtocolException("Invalid session ID length (" +
+ sessionId.length + " bytes)");
+ }
+ }
+
}
--- a/jdk/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerIndefLenConverter.java Wed Jul 05 20:15:59 2017 +0200
@@ -156,12 +156,18 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- if (lenByte > 4)
+ if (lenByte > 4) {
throw new IOException("Too much data");
- if ((dataSize - dataPos) < (lenByte + 1))
+ }
+ if ((dataSize - dataPos) < (lenByte + 1)) {
throw new IOException("Too little data");
- for (int i = 0; i < lenByte; i++)
+ }
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
} else {
curLen = (lenByte & LEN_MASK);
}
@@ -188,10 +194,15 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- for (int i = 0; i < lenByte; i++)
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
- } else
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
+ } else {
curLen = (lenByte & LEN_MASK);
+ }
writeLength(curLen);
writeValue(curLen);
}
--- a/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java Wed Jul 05 20:15:59 2017 +0200
@@ -577,6 +577,10 @@
value <<= 8;
value += 0x0ff & in.read();
}
+ if (value < 0) {
+ throw new IOException("DerInputStream.getLength(): "
+ + "Invalid length bytes");
+ }
}
return value;
}
--- a/jdk/src/java.base/share/conf/security/java.security Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/share/conf/security/java.security Wed Jul 05 20:15:59 2017 +0200
@@ -512,8 +512,12 @@
#
# In some environments, certain algorithms or key lengths may be undesirable
# when using SSL/TLS. This section describes the mechanism for disabling
-# algorithms during SSL/TLS security parameters negotiation, including cipher
-# suites selection, peer authentication and key exchange mechanisms.
+# algorithms during SSL/TLS security parameters negotiation, including
+# protocol version negotiation, cipher suites selection, peer authentication
+# and key exchange mechanisms.
+#
+# Disabled algorithms will not be negotiated for SSL/TLS connections, even
+# if they are enabled explicitly in an application.
#
# For PKI-based peer authentication and key exchange mechanisms, this list
# of disabled algorithms will also be checked during certification path
@@ -528,4 +532,5 @@
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
-# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
+jdk.tls.disabledAlgorithms=SSLv3
--- a/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 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
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = false;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- a/jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java Wed Jul 05 20:15:59 2017 +0200
@@ -371,8 +371,8 @@
// constructor, called only once from initIO()
private RandomIO(File seedFile, File nextFile) throws IOException {
this.seedFile = seedFile;
- seedIn = new FileInputStream(seedFile);
- nextIn = new FileInputStream(nextFile);
+ seedIn = FileInputStreamPool.getInputStream(seedFile);
+ nextIn = FileInputStreamPool.getInputStream(nextFile);
nextBuffer = new byte[BUFFER_SIZE];
}
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, 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
@@ -274,7 +274,6 @@
if (index <= 0) {
return NULL;
}
-
ifs = enumInterfaces(env);
if (ifs == NULL) {
return NULL;
@@ -551,9 +550,14 @@
jboolean isCopy;
int ret = -1;
int sock;
- const char* name_utf;
+ const char* name_utf = NULL;
- name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ if (name != NULL) {
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ } else {
+ JNU_ThrowNullPointerException(env, "network interface name is NULL");
+ return ret;
+ }
if (name_utf == NULL) {
if (!(*env)->ExceptionCheck(env))
JNU_ThrowOutOfMemoryError(env, NULL);
@@ -581,7 +585,13 @@
const char* name_utf;
int flags = 0;
- name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ if (name != NULL) {
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+ } else {
+ JNU_ThrowNullPointerException(env, "network interface name is NULL");
+ return -1;
+ }
+
if (name_utf == NULL) {
if (!(*env)->ExceptionCheck(env))
JNU_ThrowOutOfMemoryError(env, NULL);
@@ -1063,6 +1073,7 @@
*/
#ifdef AF_INET6
+// unused arg ifname and struct if2
static int openSocketWithFallback(JNIEnv *env, const char *ifname){
int sock;
struct ifreq if2;
@@ -1453,9 +1464,14 @@
static int getMTU(JNIEnv *env, int sock, const char *ifname) {
struct ifreq if2;
+ memset((char *) &if2, 0, sizeof(if2));
- memset((char *) &if2, 0, sizeof(if2));
- strcpy(if2.ifr_name, ifname);
+ if (ifname != NULL) {
+ strcpy(if2.ifr_name, ifname);
+ } else {
+ JNU_ThrowNullPointerException(env, "network interface name is NULL");
+ return -1;
+ }
if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -62,7 +62,6 @@
#include "jvm.h"
#include "jni_util.h"
#include "net_util.h"
-
#include "java_net_SocketOptions.h"
#include "java_net_PlainDatagramSocketImpl.h"
#include "java_net_NetworkInterface.h"
@@ -83,6 +82,7 @@
extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
extern int getDefaultScopeID(JNIEnv *env);
+
/*
* Returns a java.lang.Integer based on 'i'
*/
@@ -1447,10 +1447,12 @@
static jmethodID ni_ctrID;
static jfieldID ni_indexID;
static jfieldID ni_addrsID;
+ static jfieldID ni_nameID;
jobjectArray addrArray;
jobject addr;
jobject ni;
+ jobject ni_name;
struct in_addr in;
struct in_addr *inP = ∈
@@ -1500,6 +1502,8 @@
ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
"[Ljava/net/InetAddress;");
CHECK_NULL_RETURN(ni_addrsID, NULL);
+ ni_nameID = (*env)->GetFieldID(env, c,"name", "Ljava/lang/String;");
+ CHECK_NULL_RETURN(ni_nameID, NULL);
ni_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL_RETURN(ni_class, NULL);
}
@@ -1521,6 +1525,10 @@
CHECK_NULL_RETURN(addrArray, NULL);
(*env)->SetObjectArrayElement(env, addrArray, 0, addr);
(*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
+ ni_name = (*env)->NewStringUTF(env, "");
+ if (ni_name != NULL) {
+ (*env)->SetObjectField(env, ni, ni_nameID, ni_name);
+ }
return ni;
}
@@ -1537,14 +1545,16 @@
static jfieldID ni_indexID;
static jfieldID ni_addrsID;
static jclass ia_class;
+ static jfieldID ni_nameID;
static jmethodID ia_anyLocalAddressID;
- int index;
+ int index = 0;
socklen_t len = sizeof(index);
jobjectArray addrArray;
jobject addr;
jobject ni;
+ jobject ni_name;
if (getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
(char*)&index, &len) < 0) {
@@ -1573,6 +1583,8 @@
"anyLocalAddress",
"()Ljava/net/InetAddress;");
CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL);
+ ni_nameID = (*env)->GetFieldID(env, c,"name", "Ljava/lang/String;");
+ CHECK_NULL_RETURN(ni_nameID, NULL);
ni_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL_RETURN(ni_class, NULL);
}
@@ -1633,6 +1645,10 @@
CHECK_NULL_RETURN(addrArray, NULL);
(*env)->SetObjectArrayElement(env, addrArray, 0, addr);
(*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
+ ni_name = (*env)->NewStringUTF(env, "");
+ if (ni_name != NULL) {
+ (*env)->SetObjectField(env, ni, ni_nameID, ni_name);
+ }
return ni;
}
#endif
--- a/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 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
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = true;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- a/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c Wed Jul 05 20:15:59 2017 +0200
@@ -283,14 +283,10 @@
FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE};
- {
- /* Extraction of current process standard IOE handles */
- DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
- int i;
- for (i = 0; i < 3; ++i)
- /* Should not be closed by CloseHandle! */
- stdIOE[i] = GetStdHandle(idsIOE[i]);
- }
+ /* These three should not be closed by CloseHandle! */
+ stdIOE[0] = GetStdHandle(STD_INPUT_HANDLE);
+ stdIOE[1] = GetStdHandle(STD_OUTPUT_HANDLE);
+ stdIOE[2] = GetStdHandle(STD_ERROR_HANDLE);
prepareIOEHandleState(stdIOE, inherit);
{
@@ -319,11 +315,16 @@
if (success) {
PROCESS_INFORMATION pi;
- DWORD processFlag = CREATE_UNICODE_ENVIRONMENT;
+ DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
- /* Suppress popping-up of a console window for non-console applications */
- if (GetConsoleWindow() == NULL)
- processFlag |= CREATE_NO_WINDOW;
+ /* If the standard I/O is inherited, CREATE_NO_WINDOW must not be used. */
+ if (GetConsoleWindow() != NULL &&
+ (si.hStdInput == stdIOE[0] ||
+ si.hStdOutput == stdIOE[1] ||
+ si.hStdError == (redirectErrorStream ? stdIOE[1] : stdIOE[2])))
+ {
+ processFlag &= ~CREATE_NO_WINDOW;
+ }
si.dwFlags = STARTF_USESTDHANDLES;
if (!CreateProcessW(
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Wed Jul 05 20:15:59 2017 +0200
@@ -248,7 +248,8 @@
Part part = getXPButtonType(b);
- if (b.isContentAreaFilled() && xp != null) {
+ if (b.isContentAreaFilled() && b.getBorder() != null
+ && b.isBorderPainted() && xp != null) {
Skin skin = xp.getSkin(b, part);
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Wed Jul 05 20:15:59 2017 +0200
@@ -1081,16 +1081,9 @@
directories.clear();
- File[] baseFolders;
- if (useShellFolder) {
- baseFolders = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
- public File[] run() {
- return (File[]) ShellFolder.get("fileChooserComboBoxFolders");
- }
- });
- } else {
- baseFolders = fsv.getRoots();
- }
+ File[] baseFolders = (useShellFolder)
+ ? (File[]) ShellFolder.get("fileChooserComboBoxFolders")
+ : fsv.getRoots();
directories.addAll(Arrays.asList(baseFolders));
// Get the canonical (full) path. This has the side
--- a/jdk/src/java.desktop/share/classes/java/beans/package.html Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/beans/package.html Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
<!--
- Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2014, 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
@@ -147,8 +147,8 @@
For overview, architecture, and tutorial documentation, please see:
<ul>
- <li><a href="http://java.sun.com/docs/books/tutorial/javabeans/">JavaBeans</a>, a trail in <em>The Java Tutorial</em>.
- <li><a href="http://java.sun.com/products/jfc/tsc/articles/persistence2/">Long-Term Persistence</a>, an article in <em>The Swing Connection</em>.
+ <li><a href="http://docs.oracle.com/javase/tutorial/javabeans/">JavaBeans</a>, a trail in <em>The Java Tutorial</em>.
+ <li><a href="http://www.oracle.com/technetwork/java/persistence2-141443.html">Long-Term Persistence</a>, an article in <em>The Swing Connection</em>.
</ul>
</body>
--- a/jdk/src/java.desktop/share/classes/javax/swing/ToolTipManager.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/ToolTipManager.java Wed Jul 05 20:15:59 2017 +0200
@@ -28,6 +28,7 @@
import java.awt.event.*;
import java.awt.*;
+import java.util.Objects;
/**
* Manages all the <code>ToolTips</code> in the system.
@@ -476,8 +477,8 @@
preferredLocation.equals(newPreferredLocation) :
(newPreferredLocation == null);
- if (!sameComponent || !toolTipText.equals(newToolTipText) ||
- !sameLoc) {
+ if (!sameComponent || !Objects.equals(toolTipText, newToolTipText)
+ || !sameLoc) {
toolTipText = newToolTipText;
preferredLocation = newPreferredLocation;
showTipWindow();
--- a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java Wed Jul 05 20:15:59 2017 +0200
@@ -44,9 +44,7 @@
import java.awt.Color;
import java.awt.Insets;
import java.awt.Dimension;
-import java.lang.reflect.Method;
import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
@@ -76,7 +74,7 @@
@SuppressWarnings("serial") // Same-version serialization only
public class UIDefaults extends Hashtable<Object,Object>
{
- private static final Object PENDING = "Pending";
+ private static final Object PENDING = new Object();
private SwingPropertyChangeSupport changeSupport;
@@ -170,7 +168,7 @@
* Looks up the given key in our Hashtable and resolves LazyValues
* or ActiveValues.
*/
- private Object getFromHashtable(Object key) {
+ private Object getFromHashtable(final Object key) {
/* Quickly handle the common case, without grabbing
* a lock.
*/
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Wed Jul 05 20:15:59 2017 +0200
@@ -1020,16 +1020,9 @@
directories.clear();
- File[] baseFolders;
- if (useShellFolder) {
- baseFolders = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
- public File[] run() {
- return (File[]) ShellFolder.get("fileChooserComboBoxFolders");
- }
- });
- } else {
- baseFolders = fsv.getRoots();
- }
+ File[] baseFolders = (useShellFolder)
+ ? (File[]) ShellFolder.get("fileChooserComboBoxFolders")
+ : fsv.getRoots();
directories.addAll(Arrays.asList(baseFolders));
// Get the canonical (full) path. This has the side
--- a/jdk/src/java.desktop/share/classes/sun/swing/FilePane.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/FilePane.java Wed Jul 05 20:15:59 2017 +0200
@@ -1993,20 +1993,24 @@
return false;
}
- if (f instanceof ShellFolder) {
- return f.canWrite();
- } else {
- if (usesShellFolder(getFileChooser())) {
- try {
- return ShellFolder.getShellFolder(f).canWrite();
- } catch (FileNotFoundException ex) {
- // File doesn't exist
- return false;
+ try {
+ if (f instanceof ShellFolder) {
+ return f.canWrite();
+ } else {
+ if (usesShellFolder(getFileChooser())) {
+ try {
+ return ShellFolder.getShellFolder(f).canWrite();
+ } catch (FileNotFoundException ex) {
+ // File doesn't exist
+ return false;
+ }
+ } else {
+ // Ordinary file
+ return f.canWrite();
}
- } else {
- // Ordinary file
- return f.canWrite();
}
+ } catch (SecurityException e) {
+ return false;
}
}
--- a/jdk/src/java.desktop/share/classes/sun/swing/WindowsPlacesBar.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/WindowsPlacesBar.java Wed Jul 05 20:15:59 2017 +0200
@@ -82,11 +82,7 @@
setBackground(bgColor);
FileSystemView fsv = fc.getFileSystemView();
- files = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
- public File[] run() {
- return (File[]) ShellFolder.get("fileChooserShortcutPanelFolders");
- }
- });
+ files = (File[]) ShellFolder.get("fileChooserShortcutPanelFolders");
buttons = new JToggleButton[files.length];
buttonGroup = new ButtonGroup();
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java Wed Jul 05 20:15:59 2017 +0200
@@ -28,7 +28,6 @@
import java.awt.*;
import java.util.*;
import javax.swing.*;
-import javax.swing.border.Border;
import javax.swing.plaf.*;
/**
@@ -44,7 +43,8 @@
* @author Scott Violet
*/
public class DefaultSynthStyle extends SynthStyle implements Cloneable {
- private static final String PENDING = "Pending";
+
+ private static final Object PENDING = new Object();
/**
* Should the component be opaque?
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java Wed Jul 05 20:15:59 2017 +0200
@@ -771,16 +771,9 @@
fireIntervalRemoved(this, 0, oldSize);
}
- File[] baseFolders;
- if (useShellFolder) {
- baseFolders = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
- public File[] run() {
- return (File[]) ShellFolder.get("fileChooserComboBoxFolders");
- }
- });
- } else {
- baseFolders = fsv.getRoots();
- }
+ File[] baseFolders = (useShellFolder)
+ ? (File[]) ShellFolder.get("fileChooserComboBoxFolders")
+ : fsv.getRoots();
directories.addAll(Arrays.asList(baseFolders));
// Get the canonical (full) path. This has the side
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -583,6 +583,8 @@
LEReferenceTo<ChainSubClassRuleTable>
chainSubClassRuleTable(chainSubClassSetTable, success, chainSubClassRuleTableOffset);
le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
+ LEReferenceToArrayOf<le_uint16> backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
+ if( LE_FAILURE(success) ) { return 0; }
le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
LEReferenceToArrayOf<le_uint16> inputClassArray(base, success, &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1],inputGlyphCount+2); // +2 for the lookaheadGlyphCount count
le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray.getObject(inputGlyphCount, success));
@@ -599,8 +601,6 @@
}
tempIterator.prev();
- LEReferenceToArrayOf<le_uint16> backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
- if( LE_FAILURE(success) ) { return 0; }
if (! matchGlyphClasses(backtrackClassArray, backtrackGlyphCount,
&tempIterator, backtrackClassDefinitionTable, success, TRUE)) {
continue;
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -45,6 +45,9 @@
le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
le_uint16 eeCount = SWAPW(entryExitCount);
+ LEReferenceToArrayOf<EntryExitRecord>
+ entryExitRecordsArrayRef(base, success, entryExitRecords, coverageIndex);
+
if (coverageIndex < 0 || coverageIndex >= eeCount || LE_FAILURE(success)) {
glyphIterator->setCursiveGlyph();
return 0;
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/Features.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/Features.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -40,6 +40,9 @@
LEReferenceTo<FeatureTable> FeatureListTable::getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const
{
+ LEReferenceToArrayOf<FeatureRecord>
+ featureRecordArrayRef(base, success, featureRecordArray, featureIndex);
+
if (featureIndex >= SWAPW(featureCount) || LE_FAILURE(success)) {
return LEReferenceTo<FeatureTable>();
}
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LETableReference.h Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LETableReference.h Wed Jul 05 20:15:59 2017 +0200
@@ -470,7 +470,12 @@
#endif
const T& getObject(le_uint32 i, LEErrorCode &success) const {
- return *getAlias(i,success);
+ const T *ret = getAlias(i, success);
+ if (LE_FAILURE(success) || ret==NULL) {
+ return *(new T(0));
+ } else {
+ return *ret;
+ }
}
/**
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstSubtables.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstSubtables.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -64,6 +64,9 @@
LEReferenceTo<LigatureTable> ligTable(ligSetTable, success, ligTableOffset);
if(LE_FAILURE(success)) { return 0; }
le_uint16 compCount = SWAPW(ligTable->compCount) - 1;
+ LEReferenceToArrayOf<TTGlyphID>
+ componentArrayRef(base, success, ligTable->componentArray, compCount);
+ if (LE_FAILURE(success)) { return 0; }
le_int32 startPosition = glyphIterator->getCurrStreamPosition();
TTGlyphID ligGlyph = SWAPW(ligTable->ligGlyph);
le_uint16 comp;
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/MultipleSubstSubtables.cpp Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/MultipleSubstSubtables.cpp Wed Jul 05 20:15:59 2017 +0200
@@ -61,6 +61,8 @@
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
le_uint16 seqCount = SWAPW(sequenceCount);
+ LEReferenceToArrayOf<Offset>
+ sequenceTableOffsetArrayRef(base, success, sequenceTableOffsetArray, seqCount);
if (LE_FAILURE(success)) {
return 0;
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Jul 05 20:15:59 2017 +0200
@@ -36,6 +36,7 @@
import java.util.*;
import java.util.List;
import java.util.concurrent.*;
+import java.util.stream.Stream;
import static sun.awt.shell.Win32ShellFolder2.*;
import sun.awt.OSInfo;
@@ -251,7 +252,7 @@
if (file == null) {
file = getDesktop();
}
- return file;
+ return checkFile(file);
} else if (key.equals("roots")) {
// Should be "History" and "Desktop" ?
if (roots == null) {
@@ -262,11 +263,11 @@
roots = (File[])super.get(key);
}
}
- return roots;
+ return checkFiles(roots);
} else if (key.equals("fileChooserComboBoxFolders")) {
Win32ShellFolder2 desktop = getDesktop();
- if (desktop != null) {
+ if (desktop != null && checkFile(desktop) != null) {
ArrayList<File> folders = new ArrayList<File>();
Win32ShellFolder2 drives = getDrives();
@@ -277,7 +278,7 @@
folders.add(desktop);
// Add all second level folders
- File[] secondLevelFolders = desktop.listFiles();
+ File[] secondLevelFolders = checkFiles(desktop.listFiles());
Arrays.sort(secondLevelFolders);
for (File secondLevelFolder : secondLevelFolders) {
Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder;
@@ -285,7 +286,7 @@
folders.add(folder);
// Add third level for "My Computer"
if (folder.equals(drives)) {
- File[] thirdLevelFolders = folder.listFiles();
+ File[] thirdLevelFolders = checkFiles(folder.listFiles());
if (thirdLevelFolders != null && thirdLevelFolders.length > 0) {
List<File> thirdLevelFoldersList = Arrays.asList(thirdLevelFolders);
@@ -295,7 +296,7 @@
}
}
}
- return folders.toArray(new File[folders.size()]);
+ return checkFiles(folders);
} else {
return super.get(key);
}
@@ -332,7 +333,7 @@
}
}
}
- return folders.toArray(new File[folders.size()]);
+ return checkFiles(folders);
} else if (key.startsWith("fileChooserIcon ")) {
String name = key.substring(key.indexOf(" ") + 1);
@@ -378,6 +379,41 @@
return null;
}
+ private File checkFile(File file) {
+ SecurityManager sm = System.getSecurityManager();
+ return (sm == null || file == null) ? file : checkFile(file, sm);
+ }
+
+ private File checkFile(File file, SecurityManager sm) {
+ try {
+ sm.checkRead(file.getPath());
+ return file;
+ } catch (SecurityException se) {
+ return null;
+ }
+ }
+
+ private File[] checkFiles(File[] files) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null || files == null || files.length == 0) {
+ return files;
+ }
+ return checkFiles(Arrays.stream(files), sm);
+ }
+
+ private File[] checkFiles(List<File> files) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null || files.isEmpty()) {
+ return files.toArray(new File[files.size()]);
+ }
+ return checkFiles(files.stream(), sm);
+ }
+
+ private File[] checkFiles(Stream<File> filesStream, SecurityManager sm) {
+ return filesStream.filter((file) -> checkFile(file, sm) != null)
+ .toArray(File[]::new);
+ }
+
/**
* Does <code>dir</code> represent a "computer" such as a node on the network, or
* "My Computer" on the desktop.
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java Wed Jul 05 20:15:59 2017 +0200
@@ -95,6 +95,9 @@
for( int i = 0; i < lengthbyte; i++) {
retval = (retval << 8) + (buf[offset++] & 0xff);
}
+ if (retval < 0) {
+ throw new DecodeException("Invalid length bytes");
+ }
return retval;
} else {
return lengthbyte;
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/Transport.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/Transport.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -37,7 +37,10 @@
import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
import sun.rmi.runtime.Log;
import sun.rmi.server.Dispatcher;
import sun.rmi.server.UnicastServerRef;
@@ -69,6 +72,15 @@
/** ObjID for DGCImpl */
private static final ObjID dgcID = new ObjID(ObjID.DGC_ID);
+ /** AccessControlContext for setting context ClassLoader */
+ private static final AccessControlContext SETCCL_ACC;
+ static {
+ Permissions perms = new Permissions();
+ perms.add(new RuntimePermission("setContextClassLoader"));
+ ProtectionDomain[] pd = { new ProtectionDomain(null, perms) };
+ SETCCL_ACC = new AccessControlContext(pd);
+ }
+
/**
* Returns a <I>Channel</I> that generates connections to the
* endpoint <I>ep</I>. A Channel is an object that creates and
@@ -118,6 +130,16 @@
protected abstract void checkAcceptPermission(AccessControlContext acc);
/**
+ * Sets the context class loader for the current thread.
+ */
+ private static void setContextClassLoader(ClassLoader ccl) {
+ AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+ Thread.currentThread().setContextClassLoader(ccl);
+ return null;
+ }, SETCCL_ACC);
+ }
+
+ /**
* Service an incoming remote call. When a message arrives on the
* connection indicating the beginning of a remote call, the
* threads are required to call the <I>serviceCall</I> method of
@@ -165,11 +187,10 @@
target.getAccessControlContext();
ClassLoader ccl = target.getContextClassLoader();
- Thread t = Thread.currentThread();
- ClassLoader savedCcl = t.getContextClassLoader();
+ ClassLoader savedCcl = Thread.currentThread().getContextClassLoader();
try {
- t.setContextClassLoader(ccl);
+ setContextClassLoader(ccl);
currentTransport.set(this);
try {
java.security.AccessController.doPrivileged(
@@ -184,7 +205,7 @@
throw (IOException) pae.getException();
}
} finally {
- t.setContextClassLoader(savedCcl);
+ setContextClassLoader(savedCcl);
currentTransport.set(null);
}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -49,7 +49,9 @@
import java.rmi.server.UID;
import java.security.AccessControlContext;
import java.security.AccessController;
+import java.security.Permissions;
import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -120,6 +122,14 @@
private static final ThreadLocal<ConnectionHandler>
threadConnectionHandler = new ThreadLocal<>();
+ /** an AccessControlContext with no permissions */
+ private static final AccessControlContext NOPERMS_ACC;
+ static {
+ Permissions perms = new Permissions();
+ ProtectionDomain[] pd = { new ProtectionDomain(null, perms) };
+ NOPERMS_ACC = new AccessControlContext(pd);
+ }
+
/** endpoints for this transport */
private final LinkedList<TCPEndpoint> epList;
/** number of objects exported on this transport */
@@ -664,7 +674,10 @@
t.setName("RMI TCP Connection(" +
connectionCount.incrementAndGet() +
")-" + remoteHost);
- run0();
+ AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+ run0();
+ return null;
+ }, NOPERMS_ACC);
} finally {
t.setName(name);
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSHeader.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSHeader.java Wed Jul 05 20:15:59 2017 +0200
@@ -270,6 +270,9 @@
value <<= 8;
value += 0x0ff & in.read();
}
+ if (value < 0) {
+ throw new IOException("Invalid length bytes");
+ }
}
return value;
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java Wed Jul 05 20:15:59 2017 +0200
@@ -257,7 +257,8 @@
((0xFF & bytes[pos++]) << 16) |
((0xFF & bytes[pos++]) << 8) |
(0xFF & bytes[pos++]));
- if (pos > bytes.length - mechPortionLen) {
+
+ if (mechPortionLen < 0 || pos > bytes.length - mechPortionLen) {
throw new GSSExceptionImpl(GSSException.BAD_NAME,
"Exported name mech name is corrupted!");
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Wed Jul 05 20:15:59 2017 +0200
@@ -233,6 +233,9 @@
((0xFF & nameVal[pos++]) << 16) |
((0xFF & nameVal[pos++]) << 8) |
(0xFF & nameVal[pos++]));
+ if (mechPortionLen < 0) {
+ throw new GSSException(GSSException.BAD_NAME);
+ }
byte[] mechPortion = new byte[mechPortionLen];
System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen);
return mechPortion;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Wed Jul 05 20:15:59 2017 +0200
@@ -113,15 +113,17 @@
@SuppressWarnings("unchecked")
private static Hashtable<String, Object> convertNativeConfig(
- Hashtable<String, Object> stanzaTable) {
+ Hashtable<String, Object> stanzaTable) throws IOException {
// convert SCDynamicStore realm structure to Java realm structure
Hashtable<String, ?> realms =
(Hashtable<String, ?>) stanzaTable.get("realms");
- if (realms != null) {
- stanzaTable.remove("realms");
- Hashtable<String, Object> realmsTable = convertRealmConfigs(realms);
- stanzaTable.put("realms", realmsTable);
+ if (realms == null || realms.isEmpty()) {
+ throw new IOException(
+ "SCDynamicStore contains an empty Kerberos setting");
}
+ stanzaTable.remove("realms");
+ Hashtable<String, Object> realmsTable = convertRealmConfigs(realms);
+ stanzaTable.put("realms", realmsTable);
WrapAllStringInVector(stanzaTable);
if (DEBUG) System.out.println("stanzaTable : " + stanzaTable);
return stanzaTable;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java Wed Jul 05 20:15:59 2017 +0200
@@ -118,7 +118,7 @@
} else {
type = read(4);
}
- length = read(4);
+ length = readLength4();
List<String> result = new ArrayList<String>();
/*
* DCE includes the principal's realm in the count; the new format
@@ -127,7 +127,7 @@
if (version == KRB5_FCC_FVNO_1)
length--;
for (int i = 0; i <= length; i++) {
- namelength = read(4);
+ namelength = readLength4();
byte[] bytes = IOUtils.readFully(this, namelength, true);
result.add(new String(bytes));
}
@@ -184,7 +184,7 @@
keyType = read(2);
if (version == KRB5_FCC_FVNO_3)
read(2); /* keytype recorded twice in fvno 3 */
- keyLen = read(4);
+ keyLen = readLength4();
byte[] bytes = IOUtils.readFully(this, keyLen, true);
return new EncryptionKey(bytes, keyType, version);
}
@@ -207,12 +207,12 @@
HostAddress[] readAddr() throws IOException, KrbApErrException {
int numAddrs, addrType, addrLength;
- numAddrs = read(4);
+ numAddrs = readLength4();
if (numAddrs > 0) {
List<HostAddress> addrs = new ArrayList<>();
for (int i = 0; i < numAddrs; i++) {
addrType = read(2);
- addrLength = read(4);
+ addrLength = readLength4();
if (!(addrLength == 4 || addrLength == 16)) {
if (DEBUG) {
System.out.println("Incorrect address format.");
@@ -231,13 +231,13 @@
AuthorizationDataEntry[] readAuth() throws IOException {
int num, adtype, adlength;
- num = read(4);
+ num = readLength4();
if (num > 0) {
List<AuthorizationDataEntry> auData = new ArrayList<>();
byte[] data = null;
for (int i = 0; i < num; i++) {
adtype = read(2);
- adlength = read(4);
+ adlength = readLength4();
data = IOUtils.readFully(this, adlength, true);
auData.add(new AuthorizationDataEntry(adtype, data));
}
@@ -248,7 +248,7 @@
byte[] readData() throws IOException {
int length;
- length = read(4);
+ length = readLength4();
if (length == 0) {
return null;
} else {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Wed Jul 05 20:15:59 2017 +0200
@@ -150,43 +150,43 @@
synchronized void init(PrincipalName principal, String name)
throws IOException, KrbException {
primaryPrincipal = principal;
- CCacheOutputStream cos =
- new CCacheOutputStream(new FileOutputStream(name));
- version = KRB5_FCC_FVNO_3;
- cos.writeHeader(primaryPrincipal, version);
- cos.close();
+ try (FileOutputStream fos = new FileOutputStream(name);
+ CCacheOutputStream cos = new CCacheOutputStream(fos)) {
+ version = KRB5_FCC_FVNO_3;
+ cos.writeHeader(primaryPrincipal, version);
+ }
load(name);
}
synchronized void load(String name) throws IOException, KrbException {
PrincipalName p;
- CCacheInputStream cis =
- new CCacheInputStream(new FileInputStream(name));
- version = cis.readVersion();
- if (version == KRB5_FCC_FVNO_4) {
- tag = cis.readTag();
- } else {
- tag = null;
- if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) {
- cis.setNativeByteOrder();
+ try (FileInputStream fis = new FileInputStream(name);
+ CCacheInputStream cis = new CCacheInputStream(fis)) {
+ version = cis.readVersion();
+ if (version == KRB5_FCC_FVNO_4) {
+ tag = cis.readTag();
+ } else {
+ tag = null;
+ if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) {
+ cis.setNativeByteOrder();
+ }
+ }
+ p = cis.readPrincipal(version);
+
+ if (primaryPrincipal != null) {
+ if (!(primaryPrincipal.match(p))) {
+ throw new IOException("Primary principals don't match.");
+ }
+ } else
+ primaryPrincipal = p;
+ credentialsList = new Vector<Credentials>();
+ while (cis.available() > 0) {
+ Credentials cred = cis.readCred(version);
+ if (cred != null) {
+ credentialsList.addElement(cred);
+ }
}
}
- p = cis.readPrincipal(version);
-
- if (primaryPrincipal != null) {
- if (!(primaryPrincipal.match(p))) {
- throw new IOException("Primary principals don't match.");
- }
- } else
- primaryPrincipal = p;
- credentialsList = new Vector<Credentials> ();
- while (cis.available() > 0) {
- Credentials cred = cis.readCred(version);
- if (cred != null) {
- credentialsList.addElement(cred);
- }
- }
- cis.close();
}
@@ -245,16 +245,16 @@
* Saves the credentials cache file to the disk.
*/
public synchronized void save() throws IOException, Asn1Exception {
- CCacheOutputStream cos
- = new CCacheOutputStream(new FileOutputStream(cacheName));
- cos.writeHeader(primaryPrincipal, version);
- Credentials[] tmp = null;
- if ((tmp = getCredsList()) != null) {
- for (int i = 0; i < tmp.length; i++) {
- cos.addCreds(tmp[i]);
+ try (FileOutputStream fos = new FileOutputStream(cacheName);
+ CCacheOutputStream cos = new CCacheOutputStream(fos)) {
+ cos.writeHeader(primaryPrincipal, version);
+ Credentials[] tmp = null;
+ if ((tmp = getCredsList()) != null) {
+ for (int i = 0; i < tmp.length; i++) {
+ cos.addCreds(tmp[i]);
+ }
}
}
- cos.close();
}
boolean match(String[] s1, String[] s2) {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java Wed Jul 05 20:15:59 2017 +0200
@@ -56,15 +56,33 @@
public KrbDataInputStream(InputStream is){
super(is);
}
+
+ /**
+ * Reads a length value which is represented in 4 bytes from
+ * this input stream. The value must be positive.
+ * @return the length value represented by this byte array.
+ * @throws IOException if there are not enough bytes or it represents
+ * a negative value
+ */
+ final public int readLength4() throws IOException {
+ int len = read(4);
+ if (len < 0) {
+ throw new IOException("Invalid encoding");
+ }
+ return len;
+ }
+
/**
* Reads up to the specific number of bytes from this input stream.
* @param num the number of bytes to be read.
* @return the int value of this byte array.
- * @exception IOException.
+ * @throws IOException if there are not enough bytes
*/
- public int read(int num) throws IOException{
+ public int read(int num) throws IOException {
byte[] bytes = new byte[num];
- read(bytes, 0, num);
+ if (read(bytes, 0, num) != num) {
+ throw new IOException("Premature end of stream reached");
+ }
int result = 0;
for (int i = 0; i < num; i++) {
if (bigEndian) {
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java Wed Jul 05 20:15:59 2017 +0200
@@ -103,7 +103,7 @@
case HTTP_UNAVAILABLE: return " Service Unavailable";
case HTTP_GATEWAY_TIMEOUT: return " Gateway Timeout";
case HTTP_VERSION: return " HTTP Version Not Supported";
- default: return "";
+ default: return " ";
}
}
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 201, 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
@@ -53,7 +53,6 @@
import java.util.zip.InflaterInputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.ZipException;
-import java.util.zip.ZipError;
import static java.lang.Boolean.*;
import static jdk.nio.zipfs.ZipConstants.*;
import static jdk.nio.zipfs.ZipUtils.*;
@@ -119,7 +118,16 @@
this.zc = ZipCoder.get(nameEncoding);
this.defaultdir = new ZipPath(this, getBytes(defaultDir));
this.ch = Files.newByteChannel(zfpath, READ);
- this.cen = initCEN();
+ try {
+ this.cen = initCEN();
+ } catch (IOException x) {
+ try {
+ this.ch.close();
+ } catch (IOException xx) {
+ x.addSuppressed(xx);
+ }
+ throw x;
+ }
}
@Override
@@ -1058,12 +1066,15 @@
int nlen = CENNAM(cen, pos);
int elen = CENEXT(cen, pos);
int clen = CENCOM(cen, pos);
- if ((CENFLG(cen, pos) & 1) != 0)
+ if ((CENFLG(cen, pos) & 1) != 0) {
zerror("invalid CEN header (encrypted entry)");
- if (method != METHOD_STORED && method != METHOD_DEFLATED)
+ }
+ if (method != METHOD_STORED && method != METHOD_DEFLATED) {
zerror("invalid CEN header (unsupported compression method: " + method + ")");
- if (pos + CENHDR + nlen > limit)
+ }
+ if (pos + CENHDR + nlen > limit) {
zerror("invalid CEN header (bad header size)");
+ }
byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen);
IndexNode inode = new IndexNode(name, pos);
inodes.put(inode, inode);
@@ -1533,6 +1544,7 @@
private CRC32 crc;
private Entry e;
private long written;
+ private boolean isClosed = false;
EntryOutputStream(Entry e, OutputStream os)
throws IOException
@@ -1545,9 +1557,14 @@
}
@Override
- public void write(byte b[], int off, int len) throws IOException {
+ public synchronized void write(byte b[], int off, int len)
+ throws IOException
+ {
if (e.type != Entry.FILECH) // only from sync
ensureOpen();
+ if (isClosed) {
+ throw new IOException("Stream closed");
+ }
if (off < 0 || len < 0 || off > b.length - len) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
@@ -1568,7 +1585,11 @@
}
@Override
- public void close() throws IOException {
+ public synchronized void close() throws IOException {
+ if (isClosed) {
+ return;
+ }
+ isClosed = true;
// TBD ensureOpen();
switch (e.method) {
case METHOD_DEFLATED:
@@ -1599,8 +1620,8 @@
}
}
- static void zerror(String msg) {
- throw new ZipError(msg);
+ static void zerror(String msg) throws ZipException {
+ throw new ZipException(msg);
}
// Maxmum number of de/inflater we cache
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Wed Jul 05 20:15:59 2017 +0200
@@ -36,7 +36,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import java.util.zip.ZipError;
+import java.util.zip.ZipException;
import java.util.concurrent.ExecutorService;
/*
@@ -100,7 +100,7 @@
ZipFileSystem zipfs = null;
try {
zipfs = new ZipFileSystem(this, path, env);
- } catch (ZipError ze) {
+ } catch (ZipException ze) {
String pname = path.toString();
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
throw ze;
@@ -122,7 +122,7 @@
ensureFile(path);
try {
return new ZipFileSystem(this, path, env);
- } catch (ZipError ze) {
+ } catch (ZipException ze) {
String pname = path.toString();
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
throw ze;
--- a/jdk/test/ProblemList.txt Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/ProblemList.txt Wed Jul 05 20:15:59 2017 +0200
@@ -296,6 +296,9 @@
# 8058616
com/sun/jdi/RedefinePop.sh generic-all
+# 8068645
+com/sun/jdi/CatchPatternTest.sh generic-all
+
############################################################################
# jdk_util
@@ -332,6 +335,9 @@
# 8057732
sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java generic-all
+# 8064572 8060736 8062938
+sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
+
# 8060088
com/sun/tracing/BasicWithSecurityMgr.java generic-all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/net/httpserver/MissingTrailingSpace.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015, 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 8068795
+ * @summary HttpServer missing tailing space for some response codes
+ * @author lev.priima@oracle.com
+ */
+
+import java.net.InetSocketAddress;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+public class MissingTrailingSpace {
+
+ private static final int noMsgCode = 207;
+ private static final String someContext = "/context";
+
+ public static void main(String[] args) throws Exception {
+ HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
+ try {
+ server.setExecutor(Executors.newFixedThreadPool(1));
+ server.createContext(someContext, new HttpHandler() {
+ @Override
+ public void handle(HttpExchange msg) {
+ try {
+ try {
+ msg.sendResponseHeaders(noMsgCode, -1);
+ } catch(IOException ioe) {
+ ioe.printStackTrace();
+ }
+ } finally {
+ msg.close();
+ }
+ }
+ });
+ server.start();
+ System.out.println("Server started at port "
+ + server.getAddress().getPort());
+
+ runRawSocketHttpClient("localhost", server.getAddress().getPort());
+ } finally {
+ ((ExecutorService)server.getExecutor()).shutdown();
+ server.stop(0);
+ }
+ System.out.println("Server finished.");
+ }
+
+ static void runRawSocketHttpClient(String hostname, int port)
+ throws Exception
+ {
+ Socket socket = null;
+ PrintWriter writer = null;
+ BufferedReader reader = null;
+ final String CRLF = "\r\n";
+ try {
+ socket = new Socket(hostname, port);
+ writer = new PrintWriter(new OutputStreamWriter(
+ socket.getOutputStream()));
+ System.out.println("Client connected by socket: " + socket);
+
+ writer.print("GET " + someContext + "/ HTTP/1.1" + CRLF);
+ writer.print("User-Agent: Java/"
+ + System.getProperty("java.version")
+ + CRLF);
+ writer.print("Host: " + hostname + CRLF);
+ writer.print("Accept: */*" + CRLF);
+ writer.print("Connection: keep-alive" + CRLF);
+ writer.print(CRLF); // Important, else the server will expect that
+ // there's more into the request.
+ writer.flush();
+ System.out.println("Client wrote rquest to socket: " + socket);
+
+ reader = new BufferedReader(new InputStreamReader(
+ socket.getInputStream()));
+ System.out.println("Client start reading from server:" );
+ String line = reader.readLine();
+ if ( !line.endsWith(" ") ) {
+ throw new RuntimeException("respond to unknown code "
+ + noMsgCode
+ + " doesn't return space at the end of the first header.\n"
+ + "Should be: " + "\"" + line + " \""
+ + ", but returns: " + "\"" + line + "\".");
+ }
+ for (; line != null; line = reader.readLine()) {
+ if (line.isEmpty()) {
+ break;
+ }
+ System.out.println("\"" + line + "\"");
+ }
+ System.out.println("Client finished reading from server" );
+ } finally {
+ if (reader != null)
+ try {
+ reader.close();
+ } catch (IOException logOrIgnore) {
+ logOrIgnore.printStackTrace();
+ }
+ if (writer != null) {
+ writer.close();
+ }
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (IOException logOrIgnore) {
+ logOrIgnore.printStackTrace();
+ }
+ }
+ }
+ System.out.println("Client finished." );
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2007, 2014, 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 8054358
+ * @summary Check whether a set of dialogs created with a toolkit excluded Frame
+ * parent has a proper modal blocking behavior. Also show a document modal
+ * dialog and check if it blocks the document properly.
+ *
+ * @library ../helpers ../../../../lib/testlibrary/
+ * @build ExtendedRobot
+ * @build Flag
+ * @build TestDialog
+ * @build TestFrame
+ * @run main/timeout=500 MultipleDialogs1Test
+ */
+
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Iterator;
+
+public class MultipleDialogs1Test {
+
+ private volatile CustomFrame frame;
+ private List<CustomDialog> dialogList;
+
+ private static int delay = 500;
+ private int dialogCount = -1;
+
+ public void createGUI() {
+
+ final int n = 8;
+ dialogList = new ArrayList<>();
+
+ frame = new CustomFrame();
+ frame.setLocation(50, 50);
+ frame.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
+ frame.setVisible(true);
+
+ int x = 250, y = 50;
+
+ CustomDialog dlg;
+
+ for (int i = 0; i < n - 1; ++i) {
+
+ dlg = new CustomDialog(frame);
+ dlg.setLocation(x, y);
+ x += 200;
+
+ if (x > 600) {
+ x = 50;
+ y += 200;
+ }
+
+ Dialog.ModalityType type;
+
+ if (i % 3 == 0) {
+ type = Dialog.ModalityType.MODELESS;
+ } else if (i % 3 == 1) {
+ type = Dialog.ModalityType.APPLICATION_MODAL;
+ } else {
+ type = Dialog.ModalityType.TOOLKIT_MODAL;
+ }
+
+ dlg.setModalityType(type);
+ dialogList.add(dlg);
+ }
+
+ dlg = new CustomDialog(frame);
+ dlg.setLocation(x, y);
+ dlg.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
+ dialogList.add(dlg);
+ }
+
+ public void doTest() throws Exception {
+
+ try {
+ EventQueue.invokeAndWait(this::createGUI);
+
+ ExtendedRobot robot = new ExtendedRobot();
+ robot.waitForIdle(delay);
+
+ List<CustomDialog> dialogs = Collections.synchronizedList(dialogList);
+
+ final int n = dialogs.size();
+
+ synchronized(dialogs) {
+ for (int i = 0; i < n - 1; ++i) {
+
+ frame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ dialogs.get(i).checkUnblockedDialog(
+ robot, i + ": This is " + getType(i) + ".");
+
+ frame.checkUnblockedFrame(robot, i + ": Other dialogs are visible.");
+
+ if (i > 0) {
+ for (int j = 0; j < i; j++) {
+ dialogs.get(j).checkUnblockedDialog(robot, j + ": A toolkit modality " +
+ "excluded frame is a parent of this dialog.");
+ }
+ }
+ } // i
+
+ frame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ dialogs.get(n - 1).checkUnblockedDialog(
+ robot, (n - 1) + ": This is " + getType(n - 1) + ".");
+
+ frame.checkBlockedFrame(robot,
+ "A document modal dialog with Frame parent is visible.");
+
+ for (int i = 0; i < n - 1; ++i) {
+ dialogs.get(i).checkUnblockedDialog(robot,
+ i + ": A document modal dialog should not block " +
+ "this dialog. The parent is modality excluded.");
+ }
+
+ dialogs.get(n - 1).clickCloseButton(robot);
+ robot.waitForIdle(delay);
+
+ for (int i = 0; i < n - 1; ++i) {
+ dialogs.get(i).checkUnblockedDialog(robot, i + ": A document modal " +
+ "dialog which blocked this dialog was closed.");
+ }
+ frame.checkUnblockedFrame(robot,
+ "A blocking document modal dialog was closed.");
+ robot.waitForIdle(delay);
+ } // synchronized
+
+ } finally {
+ EventQueue.invokeAndWait(this::closeAll);
+ }
+ }
+
+ private String getType(int i) {
+
+ switch (dialogList.get(i).getModalityType()) {
+ case APPLICATION_MODAL:
+ return "an application modal dialog";
+ case DOCUMENT_MODAL:
+ return "a document modal dialog";
+ case TOOLKIT_MODAL:
+ return "a toolkit modal dialog";
+ }
+ return "a modeless dialog";
+ }
+
+ private void closeAll() {
+
+ if (frame != null) { frame.dispose(); }
+ if (dialogList != null) {
+ Iterator<CustomDialog> it = dialogList.iterator();
+ while (it.hasNext()) { it.next().dispose(); }
+ }
+ }
+
+ class CustomFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() {
+ if ((dialogList != null) && (dialogList.size() > dialogCount)) {
+ dialogCount++;
+ CustomDialog d = dialogList.get(dialogCount);
+ if (d != null) { d.setVisible(true); }
+ }
+ }
+ }
+
+ class CustomDialog extends TestDialog {
+
+ public CustomDialog(Frame f) { super(f); }
+ public CustomDialog(Dialog d) { super(d); }
+
+ @Override
+ public void doCloseAction() { this.dispose(); }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ (new MultipleDialogs1Test()).doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2007, 2014, 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 8054358
+ * @summary Check whether a set of dialogs created with an application excluded Frame
+ * parent has a proper modal blocking behavior. Also show a document modal
+ * dialog and check if it blocks the document properly.
+ *
+ * @library ../helpers ../../../../lib/testlibrary/
+ * @build ExtendedRobot
+ * @build Flag
+ * @build TestDialog
+ * @build TestFrame
+ * @run main/timeout=500 MultipleDialogs2Test
+ */
+
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Iterator;
+
+public class MultipleDialogs2Test {
+
+ private volatile CustomFrame frame;
+ private List<CustomDialog> dialogList;
+ private static final int delay = 500;
+
+ private int dialogCount = -1;
+
+ private void createGUI() {
+
+ final int n = 8;
+ dialogList = new ArrayList<>();
+
+ frame = new CustomFrame();
+ frame.setLocation(50, 50);
+ frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
+ frame.setVisible(true);
+
+ CustomDialog dlg;
+
+ int x = 250, y = 50;
+ for (int i = 0; i < n - 1; ++i) {
+
+ dlg = new CustomDialog(frame);
+ dlg.setLocation(x, y);
+ x += 200;
+ if (x > 600) {
+ x = 50;
+ y += 200;
+ }
+
+ Dialog.ModalityType type;
+ if (i % 3 == 0) {
+ type = Dialog.ModalityType.MODELESS;
+ } else if (i % 3 == 1) {
+ type = Dialog.ModalityType.APPLICATION_MODAL;
+ } else {
+ type = Dialog.ModalityType.TOOLKIT_MODAL;
+ }
+ dlg.setModalityType(type);
+ dialogList.add(dlg);
+ }
+
+ dlg = new CustomDialog(frame);
+ dlg.setLocation(x, y);
+ dlg.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
+ dialogList.add(dlg);
+ }
+
+ public void doTest() throws Exception {
+
+ try {
+ EventQueue.invokeAndWait(this::createGUI);
+
+ ExtendedRobot robot = new ExtendedRobot();
+ robot.waitForIdle(delay);
+
+ List<CustomDialog> dialogs = Collections.synchronizedList(dialogList);
+ final int n = dialogs.size();
+
+ synchronized(dialogs) {
+ for (int i = 0; i < n - 1; ++i) {
+
+ frame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ dialogs.get(i).checkUnblockedDialog(
+ robot, i + ": This is " + getType(i) + ".");
+
+ if (isToolkitModal(i)) {
+
+ for (int j = 0; j < i; ++j) {
+ dialogs.get(j).checkBlockedDialog(robot, j + ": This dialog " +
+ "should be blocked by a toolkit modal dialog.");
+ }
+
+ frame.checkBlockedFrame(robot, i + ": A toolkit modal dialog " +
+ "should block this application modality excluded frame.");
+
+ break;
+
+ } else {
+ for (int j = 0; j < i; ++j) {
+ dialogs.get(j).checkUnblockedDialog(robot,
+ j + ": An application modality excluded frame " +
+ "is the parent of this dialog.");
+ }
+
+ frame.checkUnblockedFrame(robot, i + ": The frame is " +
+ "application modality excluded, but it is blocked.");
+ }
+ }
+
+ int tkIndex = dialogCount; // continue testing
+ final int tk0 = tkIndex;
+
+ for (int i = tk0 + 1; i < n - 1; ++i) {
+
+ dialogs.get(tkIndex).clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ frame.checkBlockedFrame(robot, i + ": A toolkit modal dialog " +
+ "should block this application modality excluded frame.");
+
+ if (isToolkitModal(i)) {
+ dialogs.get(i).checkUnblockedDialog(robot, i + ": This is " +
+ "a toolkit modal dialog with blocked frame parent. " +
+ "Another toolkit modal dialog is visible.");
+
+ for (int j = 0; j < i; ++j) {
+ dialogs.get(j).checkBlockedDialog(robot, j + ": " +
+ "A toolkit modal dialog should block this child " +
+ "dialog of application modality excluded frame.");
+ }
+ tkIndex = i;
+ } else {
+ dialogs.get(i).checkBlockedDialog(
+ robot, i + ": This is " + getType(i) + " with blocked " +
+ "Frame parent. Also, a toolkit modal dialog is visible.");
+
+ for (int j = 0; j < i; ++j) {
+ if (j != tkIndex) {
+ dialogs.get(j).checkBlockedDialog(robot, j +
+ ": A toolkit modal dialog should block this " +
+ "child dialog of an application modality excluded frame.");
+ }
+ }
+ }
+ }
+
+ // show a document modal dialog; the toolkit modal dialog should block it
+ dialogs.get(tkIndex).clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ frame.checkBlockedFrame(robot, "A toolkit modal dialog is visible.");
+
+ for (int i = 0; i < n; ++i) {
+ if (i == tkIndex) {
+ dialogs.get(tkIndex).checkUnblockedDialog(robot,
+ tkIndex + ": This is a toolkit modal dialog. " +
+ "A document modal dialog is visible.");
+ } else {
+ dialogs.get(i).checkBlockedDialog(robot,
+ i + ": A toolkit modal dialog should block this dialog.");
+ }
+ }
+
+ dialogs.get(tk0 + 3).clickCloseButton(robot); // close 2nd toolkit dialog
+ robot.waitForIdle(delay);
+
+ for (int i = 0; i < n; ++i) {
+
+ if (i == tk0 + 3) { continue; }
+ if (i == tk0) {
+ dialogs.get(i).checkUnblockedDialog(robot,
+ i + ": This is a toolkit modal dialog. A blocking " +
+ "toolkit modal dialog was opened and then closed.");
+ } else {
+ dialogs.get(i).checkBlockedDialog(robot,
+ i + ": This dialog should be blocked by a toolkit modal dialog. " +
+ "Another blocking toolkit modal dialog was closed.");
+ }
+ }
+
+ dialogs.get(tk0).clickCloseButton(robot);
+ robot.waitForIdle(delay);
+
+ frame.checkBlockedFrame(
+ robot, "A document modal dialog should block this Frame.");
+
+ for (int i = 0; i < n - 1; ++i) {
+ if (!isToolkitModal(i)) {
+ dialogs.get(i).checkUnblockedDialog(robot, i + ": The parent " +
+ "of the dialog is an app modality excluded Frame.");
+ }
+ }
+
+ dialogs.get(n - 1).clickCloseButton(robot);
+ robot.waitForIdle(delay);
+
+ frame.checkUnblockedFrame(robot, "A document modal dialog " +
+ "blocking this Frame was closed.");
+
+ for (int i = 0; i < n - 1; ++i) {
+ if (!isToolkitModal(i)) {
+ dialogs.get(i).checkUnblockedDialog(robot, i + ": A document modal " +
+ "dialog blocking the parent frame was closed.");
+ }
+ }
+ } // synchronized
+
+ } finally {
+ EventQueue.invokeAndWait(this::closeAll);
+ }
+ }
+
+ private boolean isToolkitModal(int i) { return (i % 3 == 2); }
+
+ private String getType(int i) {
+
+ switch (dialogList.get(i).getModalityType()) {
+ case APPLICATION_MODAL:
+ return "an application modal dialog";
+ case DOCUMENT_MODAL:
+ return "a document modal dialog";
+ case TOOLKIT_MODAL:
+ return "a toolkit modal dialog";
+ }
+ return "a modeless dialog";
+ }
+
+ public void closeAll() {
+
+ if (frame != null) { frame.dispose(); }
+ if (dialogList != null) {
+ Iterator<CustomDialog> it = dialogList.iterator();
+ while (it.hasNext()) { it.next().dispose(); }
+ }
+ }
+
+ class CustomFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() {
+ if ((dialogList != null) && (dialogList.size() > dialogCount)) {
+ dialogCount++;
+ CustomDialog d = dialogList.get(dialogCount);
+ if (d != null) { d.setVisible(true); }
+ }
+ }
+ }
+
+ class CustomDialog extends TestDialog {
+
+ public CustomDialog(Frame frame) { super(frame); }
+
+ @Override
+ public void doCloseAction() { this.dispose(); }
+
+ @Override
+ public void doOpenAction() {
+ if ((dialogList != null) && (dialogList.size() > dialogCount)) {
+ dialogCount++;
+ if (dialogList.get(dialogCount) != null) {
+ dialogList.get(dialogCount).setVisible(true);
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ (new MultipleDialogs2Test()).doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2007, 2014, 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 8054358
+ * @summary Check correctness of modal blocking behavior for a chain of Dialogs
+ * having different modality types with a Frame as a document root.
+ *
+ * @library ../helpers ../../../../lib/testlibrary/
+ * @build ExtendedRobot
+ * @build Flag
+ * @build TestDialog
+ * @build TestFrame
+ * @run main/timeout=500 MultipleDialogs3Test
+ */
+
+
+import java.awt.*;
+import static jdk.testlibrary.Asserts.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Iterator;
+
+
+public class MultipleDialogs3Test {
+
+ private volatile CustomFrame frame;
+ private List<CustomDialog> dialogList;
+ private static int delay = 500;
+
+ private int dialogCount = -1;
+
+ public void createGUI() {
+
+ final int n = 8;
+ dialogList = new ArrayList<>();
+
+ frame = new CustomFrame();
+ frame.setLocation(50, 50);
+ frame.setVisible(true);
+
+ int x = 250;
+ int y = 50;
+ for (int i = 0; i < n; ++i) {
+
+ CustomDialog dlg;
+ if (i == 0) {
+ dlg = new CustomDialog(frame);
+ } else {
+ dlg = new CustomDialog(dialogList.get(i - 1));
+ }
+ dlg.setLocation(x, y);
+ x += 200;
+ if (x > 600) {
+ x = 50;
+ y += 200;
+ }
+
+ Dialog.ModalityType type;
+
+ if (i % 4 == 0) {
+ type = Dialog.ModalityType.MODELESS;
+ } else if (i % 4 == 1) {
+ type = Dialog.ModalityType.DOCUMENT_MODAL;
+ } else if (i % 4 == 2) {
+ type = Dialog.ModalityType.APPLICATION_MODAL;
+ } else {
+ type = Dialog.ModalityType.TOOLKIT_MODAL;
+ }
+
+ dlg.setModalityType(type);
+ dialogList.add(dlg);
+ }
+ }
+
+ public void doTest() throws Exception {
+
+ try {
+ EventQueue.invokeAndWait(this::createGUI);
+
+ ExtendedRobot robot = new ExtendedRobot();
+ robot.waitForIdle(delay);
+
+ frame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ List<CustomDialog> dialogs = Collections.synchronizedList(dialogList);
+ final int n = dialogs.size();
+
+ synchronized(dialogs) {
+ for (int i = 0; i < n; ++i) {
+ dialogs.get(i).activated.waitForFlagTriggered();
+ assertTrue(dialogs.get(i).activated.flag(), i + ": Dialog did not " +
+ "trigger windowActivated event when it became visible.");
+
+ dialogs.get(i).closeGained.waitForFlagTriggered();
+ assertTrue(dialogs.get(i).closeGained.flag(), i + ": Close button " +
+ "did not gain focus when Dialog became visible.");
+
+ assertTrue(dialogs.get(i).closeButton.hasFocus(), i +
+ ": Close button gained focus but then lost it.");
+
+ dialogs.get(i).checkUnblockedDialog(robot,
+ i + ": The dialog shouldn't be blocked.");
+
+ if (i == 0) {
+ assertTrue(dialogs.get(0).getModalityType() ==
+ Dialog.ModalityType.MODELESS, "0: invalid modality type.");
+
+ frame.checkUnblockedFrame(robot, i + ": A modeless dialog was " +
+ "shown, but the parent frame became blocked.");
+
+ } else {
+ if (i % 4 == 0) { // modeless dialog
+ assertTrue(dialogs.get(i).getModalityType() ==
+ Dialog.ModalityType.MODELESS, i +
+ ": incorrect dialog modality type.");
+
+ dialogs.get(i - 1).checkUnblockedDialog(robot, i + ": A modeless " +
+ "dialog was shown, but the parent dialog became blocked.");
+
+ if (i > 0) {
+ for (int j = 0; j < i - 1; ++j) {
+
+ dialogs.get(j).checkBlockedDialog(robot, i + ", " + j +
+ ": Showing a modeless dialog as a child of a " +
+ "modal dialog unblocked some dialog in its hierarchy.");
+ }
+ }
+ } else {
+
+ for (int j = 0; j < i; ++j) {
+
+ dialogs.get(j).checkBlockedDialog(robot, i + ", " + j +
+ ": A modal dialog was shown, but some dialog " +
+ "in its hierarchy became unblocked.");
+ }
+ }
+
+ frame.checkBlockedFrame(robot, i + ": A modal was dialog shown, " +
+ "but the document root frame became unblocked.");
+ }
+
+ if (i != n - 1) {
+ dialogs.get(i).clickOpenButton(robot);
+ robot.waitForIdle(delay);
+ }
+ }
+
+ for (int i = n - 1; i >= 0; --i) {
+
+ resetAll();
+ dialogs.get(i).clickCloseButton(robot);
+ robot.waitForIdle(delay);
+
+ if (i > 0) {
+
+ dialogs.get(i - 1).activated.waitForFlagTriggered();
+ assertTrue(dialogs.get(i - 1).activated.flag(), i + ": Dialog " +
+ "was not activated when a child dialog was closed.");
+
+ if (i == 1) {
+
+ frame.checkUnblockedFrame(robot, "1: Frame having " +
+ "a child modeless dialog was blocked.");
+
+ dialogs.get(0).checkUnblockedDialog(robot,
+ "0: A modeless dialog at the bottom " +
+ "of the hierarchy was blocked.");
+
+ } else if ((i - 1) % 4 == 0) { // dialog[i - 1] is modeless
+
+ for (int j = 0; j < i - 2; ++j) {
+
+ dialogs.get(j).checkBlockedDialog(robot, i + ", " + j +
+ ": A dialog in the hierarchy was not blocked. " +
+ "A dialog blocking a modeless dialog was closed.");
+ }
+
+ dialogs.get(i - 2).checkUnblockedDialog(robot, i + ": A modal " +
+ "dialog having a child modeless dialog was blocked.");
+
+ dialogs.get(i - 1).checkUnblockedDialog(robot, i + ": A modeless " +
+ "dialog at the bottom of the hierarchy was blocked.");
+
+ frame.checkBlockedFrame(robot, i +
+ ": Frame having a child modal dialog was not blocked.");
+
+ } else {
+ for (int j = 0; j <= i - 2; ++j) {
+ dialogs.get(j).checkBlockedDialog(robot, i + ", " + j +
+ ": A dialog in the hierarchy was not blocked. " +
+ "A child dialog was closed.");
+ }
+
+ dialogs.get(i - 1).checkUnblockedDialog(robot, (i - 1) +
+ ": A dialog was not unblocked when the modal dialog was closed.");
+
+ frame.checkBlockedFrame(robot, i + ": Frame having " +
+ "a child modal dialog was not blocked. " +
+ "Another child dialog was closed.");
+ }
+ } else {
+ frame.activated.waitForFlagTriggered();
+ assertTrue(frame.activated.flag(), i + ": Frame was not " +
+ "activated when a child dialog was closed.");
+ }
+ }
+ } // synchronized
+
+ } finally {
+ EventQueue.invokeAndWait(this::closeAll);
+ }
+ }
+
+ private void resetAll() {
+ frame.resetStatus();
+ Iterator<CustomDialog> it = dialogList.iterator();
+ while (it.hasNext()) { it.next().resetStatus(); }
+ }
+
+ public void closeAll() {
+ if (frame != null) { frame.dispose(); }
+ if (dialogList != null) {
+ Iterator<CustomDialog> it = dialogList.iterator();
+ while (it.hasNext()) { it.next().dispose(); }
+ }
+ }
+
+ class CustomFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() {
+ if ((dialogList != null) && (dialogList.size() > dialogCount)) {
+ dialogCount++;
+ CustomDialog d = dialogList.get(dialogCount);
+ if (d != null) { d.setVisible(true); }
+ }
+ }
+ }
+
+ class CustomDialog extends TestDialog {
+
+ public CustomDialog(Frame frame) { super(frame); }
+ public CustomDialog(Dialog dialog) { super(dialog); }
+
+ @Override
+ public void doCloseAction() { this.dispose(); }
+
+ @Override
+ public void doOpenAction() {
+ if ((dialogList != null) && (dialogList.size() > dialogCount)) {
+ dialogCount++;
+ CustomDialog d = dialogList.get(dialogCount);
+ if (d != null) { d.setVisible(true); }
+ }
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ (new MultipleDialogs3Test()).doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2007, 2014, 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 8054358 8055003
+ * @summary Check whether application and document modality levels for Dialog
+ * work properly. Also check whether the blocking dialogs are
+ * opening on top of the windows they block.
+ *
+ * @library ../helpers ../../../../lib/testlibrary/
+ * @build ExtendedRobot
+ * @build Flag
+ * @build TestDialog
+ * @build TestFrame
+ * @run main MultipleDialogs4Test
+ */
+
+
+import java.awt.*;
+import static jdk.testlibrary.Asserts.*;
+
+
+public class MultipleDialogs4Test {
+
+ private volatile TopLevelFrame frame;
+ private volatile CustomFrame secondFrame;
+ private volatile TestFrame thirdFrame;
+ private volatile TestDialog dialog, secondDialog, docChildDialog, appChildDialog;
+
+ private static final int delay = 500;
+
+
+ private void createGUI() {
+
+ frame = new TopLevelFrame();
+ frame.setLocation(50, 50);
+ frame.setVisible(true);
+
+ dialog = new TestDialog((Dialog) null);
+ dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
+ dialog.setLocation(150, 50);
+
+ appChildDialog = new TestDialog(dialog);
+ appChildDialog.setLocation(150, 90);
+
+ secondFrame = new CustomFrame();
+ secondFrame.setLocation(50, 250);
+
+ secondDialog = new TestDialog(secondFrame);
+ secondDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
+ secondDialog.setLocation(150, 250);
+
+ docChildDialog = new TestDialog(secondFrame);
+ docChildDialog.setBackground(Color.black);
+ docChildDialog.setLocation(250, 250);
+
+ thirdFrame = new TestFrame();
+ thirdFrame.setLocation(250, 50);
+ }
+
+ public void doTest() throws Exception {
+
+ try {
+ EventQueue.invokeAndWait(this::createGUI);
+
+ final int nAttempts = 3;
+ ExtendedRobot robot = new ExtendedRobot();
+ robot.waitForIdle(delay);
+
+ frame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ secondFrame.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ secondFrame.checkBlockedFrame(robot,
+ "A document modal dialog should block this Frame.");
+
+ secondDialog.checkUnblockedDialog(robot, "This is a document " +
+ "modal dialog. No window blocks it.");
+
+ frame.checkUnblockedFrame(robot,
+ "There are no dialogs blocking this Frame.");
+
+ frame.clickCloseButton(robot);
+ robot.waitForIdle(delay);
+
+ frame.clickDummyButton(robot, nAttempts, false,
+ "The frame still on top even after showing a modal dialog.");
+ robot.waitForIdle(delay);
+
+ EventQueue.invokeAndWait(() -> { thirdFrame.setVisible(true); });
+ robot.waitForIdle(delay);
+
+ dialog.clickDummyButton(robot);
+ robot.waitForIdle(delay);
+
+ secondDialog.clickDummyButton(
+ robot, nAttempts, false, "The document modal dialog " +
+ "was not blocked by an application modal dialog.");
+ robot.waitForIdle(delay);
+
+ EventQueue.invokeLater(() -> { docChildDialog.setVisible(true); });
+ robot.waitForIdle(delay);
+
+ Color c = robot.getPixelColor(
+ (int) secondDialog.getLocationOnScreen().x + secondDialog.getSize().width - 25,
+ (int) secondDialog.getLocationOnScreen().y + secondDialog.getSize().height - 25);
+ assertFalse(c.equals(Color.black), "A dialog which should be blocked " +
+ "by document modal dialog overlapping it.");
+
+ EventQueue.invokeLater(() -> { appChildDialog.setVisible(true); });
+ robot.waitForIdle(delay);
+
+ appChildDialog.activated.waitForFlagTriggered();
+ assertTrue(appChildDialog.activated.flag(), "The child dialog of the " +
+ "application modal dialog still not visible.");
+ robot.waitForIdle(delay);
+
+ dialog.clickDummyButton(robot, nAttempts, false, "The child dialog of " +
+ "the application modal dialog did not overlap it.");
+ robot.waitForIdle(delay);
+
+ } finally {
+ EventQueue.invokeAndWait(this::closeAll);
+ }
+ }
+
+ public void closeAll() {
+
+ if (frame != null) { frame.dispose(); }
+ if (dialog != null) { dialog.dispose(); }
+ if (appChildDialog != null) { appChildDialog.dispose(); }
+ if (secondFrame != null) { secondFrame.dispose(); }
+ if (secondDialog != null) { secondDialog.dispose(); }
+ if (docChildDialog != null) { docChildDialog.dispose(); }
+ if (thirdFrame != null) { thirdFrame.dispose(); }
+ }
+
+ class TopLevelFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() { secondFrame.setVisible(true); }
+ @Override
+ public void doCloseAction() { dialog.setVisible(true); }
+ }
+
+ class CustomFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() { secondDialog.setVisible(true); }
+ }
+
+ public static void main(String[] args) throws Exception {
+ (new MultipleDialogs4Test()).doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2007, 2014, 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 8054358
+ * @summary This is a simple check if a chain of dialogs having different
+ * modality types block each other properly.
+ *
+ * @library ../helpers ../../../../lib/testlibrary/
+ * @build ExtendedRobot
+ * @build Flag
+ * @build TestDialog
+ * @build TestFrame
+ * @build TestWindow
+ * @run main MultipleDialogs5Test
+ */
+
+
+import java.awt.*;
+import static jdk.testlibrary.Asserts.*;
+
+
+public class MultipleDialogs5Test {
+
+ private volatile ParentFrame parent;
+ private volatile ModalDialog appDialog, docDialog, tkDialog;
+ private volatile CustomWindow window;
+
+ private static int delay = 500;
+
+ private void createGUI() {
+
+ parent = new ParentFrame();
+ parent.setLocation(50, 50);
+ parent.setVisible(true);
+
+ appDialog = new ModalDialog(parent);
+ appDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
+ appDialog.setLocation(250, 50);
+
+ docDialog = new ModalDialog(appDialog);
+ docDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
+ docDialog.setLocation(450, 50);
+
+ window = new CustomWindow(docDialog);
+ window.setLocation(50, 250);
+
+ tkDialog = new ModalDialog(docDialog);
+ tkDialog.setLocation(250, 250);
+ tkDialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
+
+ appDialog.setWindowToOpen(docDialog);
+ docDialog.setWindowToOpen(window);
+ }
+
+ public void doTest() throws Exception {
+
+ try {
+ EventQueue.invokeAndWait(this::createGUI);
+
+ ExtendedRobot robot = new ExtendedRobot();
+ robot.waitForIdle(delay);
+
+ parent.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ parent.checkBlockedFrame(robot,
+ "This Frame is blocked by an application modal dialog.");
+
+ appDialog.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ appDialog.checkBlockedDialog(robot,
+ "This Dialog is blocked by a document modal dialog.");
+
+ docDialog.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ docDialog.checkUnblockedDialog(robot,
+ "This Dialog is not blocked by any modal dialog.");
+
+ window.clickOpenButton(robot);
+ robot.waitForIdle(delay);
+
+ window.checkBlockedWindow(robot,
+ "This Window is blocked by a toolkit modal dialog.");
+
+ tkDialog.clickCloseButton(robot);
+ robot.waitForIdle(delay);
+ assertFalse(tkDialog.isVisible(),
+ "The toolkit modal dialog was not disposed.");
+
+ window.clickCloseButton(robot);
+ robot.waitForIdle(delay);
+ assertFalse(window.isVisible(),
+ "The window was not disposed.");
+
+ docDialog.clickCloseButton(robot);
+ robot.waitForIdle(delay);
+ assertFalse(docDialog.isVisible(),
+ "The document modal dialog was not disposed.");
+
+ appDialog.clickCloseButton(robot);
+ robot.waitForIdle(delay);
+ assertFalse(appDialog.isVisible(),
+ "The application modal dialog was not disposed.");
+ } finally {
+ EventQueue.invokeAndWait(this::closeAll); // if something wasn't closed
+ }
+ }
+
+ private void closeAll() {
+
+ if (appDialog != null) { appDialog.dispose(); }
+ if (tkDialog != null) { tkDialog.dispose(); }
+ if (docDialog != null) { docDialog.dispose(); }
+ if (parent != null) { parent.dispose(); }
+ if (window != null) { window.dispose(); }
+ }
+
+ private class ParentFrame extends TestFrame {
+
+ @Override
+ public void doOpenAction() {
+ if (appDialog != null) { appDialog.setVisible(true); }
+ }
+ }
+
+ private class CustomWindow extends TestWindow {
+
+ public CustomWindow(Dialog d) { super(d); }
+
+ @Override
+ public void doOpenAction() {
+ if (tkDialog != null) { tkDialog.setVisible(true); }
+ }
+
+ @Override
+ public void doCloseAction() { this.dispose(); }
+ }
+
+ private class ModalDialog extends TestDialog {
+
+ private Window w;
+
+ public ModalDialog(Frame f) { super(f); }
+ public ModalDialog(Dialog d) { super(d); }
+
+ public void setWindowToOpen(Window w) { this.w = w; }
+
+ @Override
+ public void doCloseAction() { this.dispose(); }
+
+ @Override
+ public void doOpenAction() {
+ if (w != null) { w.setVisible(true); }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ (new MultipleDialogs5Test()).doTest();
+ }
+}
--- a/jdk/test/java/awt/regtesthelpers/Util.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/java/awt/regtesthelpers/Util.java Wed Jul 05 20:15:59 2017 +0200
@@ -76,12 +76,17 @@
public final class Util {
private Util() {} // this is a helper class with static methods :)
+ private volatile static Robot robot;
+
/*
* @throws RuntimeException when creation failed
*/
public static Robot createRobot() {
try {
- return new Robot();
+ if (robot == null) {
+ robot = new Robot();
+ }
+ return robot;
} catch (AWTException e) {
throw new RuntimeException("Error: unable to create robot", e);
}
@@ -200,7 +205,10 @@
return false;
}
- public static void waitForIdle(final Robot robot) {
+ public static void waitForIdle(Robot robot) {
+ if (robot == null) {
+ robot = createRobot();
+ }
robot.waitForIdle();
}
--- a/jdk/test/java/lang/Class/GenericStringTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/java/lang/Class/GenericStringTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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,10 +34,29 @@
@ExpectedGenericString("public class GenericStringTest")
public class GenericStringTest {
- public static void main(String... args){
+ public Map<String, Integer>[] mixed = null;
+ public Map<String, Integer>[][] mixed2 = null;
+
+ public static void main(String... args) throws ReflectiveOperationException {
int failures = 0;
+ String[][] nested = {{""}};
+ int[][] intArray = {{1}};
+
failures += checkToGenericString(int.class, "int");
+ failures += checkToGenericString(void.class, "void");
+ failures += checkToGenericString(args.getClass(), "java.lang.String[]");
+ failures += checkToGenericString(nested.getClass(), "java.lang.String[][]");
+ failures += checkToGenericString(intArray.getClass(), "int[][]");
+ failures += checkToGenericString(java.util.Map.class, "public abstract interface java.util.Map<K,V>");
+
+ Field f = GenericStringTest.class.getDeclaredField("mixed");
+ // The expected value includes "<K,V>" rather than
+ // "<...String,...Integer>" since the Class object rather than
+ // Type objects is being queried.
+ failures += checkToGenericString(f.getType(), "java.util.Map<K,V>[]");
+ f = GenericStringTest.class.getDeclaredField("mixed2");
+ failures += checkToGenericString(f.getType(), "java.util.Map<K,V>[][]");
Class<?>[] types = {
GenericStringTest.class,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, 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 8067951
+ * @summary Unit test for internal ClassLoader#initializePath().
+ * Quoted entries should get unquoted on Windows.
+ * Empty entries should be replaced with dot.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Platform
+ * @run main LibraryPathProperty
+ */
+
+import java.lang.reflect.Method;
+import java.io.File;
+import java.util.Arrays;
+import jdk.testlibrary.Platform;
+
+public class LibraryPathProperty {
+
+ static final String propName = "test.property.name";
+ static final String SP = File.pathSeparator;
+ static Method method;
+
+ public static void main(String[] args) throws Throwable {
+ method = ClassLoader.class
+ .getDeclaredMethod("initializePath",
+ String.class);
+ method.setAccessible(true);
+
+ test("", ".");
+ test(SP, ".", ".");
+ test("a" + SP, "a", ".");
+ test(SP + "b", ".", "b");
+ test("a" + SP + SP + "b", "a", ".", "b");
+
+ if (Platform.isWindows()) {
+ // on Windows parts of paths may be quoted
+ test("\"\"", ".");
+ test("\"\"" + SP, ".", ".");
+ test(SP + "\"\"", ".", ".");
+ test("a" + SP + "\"b\"" + SP, "a", "b", ".");
+ test(SP + "\"a\"" + SP + SP + "b", ".", "a", ".", "b");
+ test("\"a\"" + SP + "\"b\"", "a", "b");
+ test("\"/a/\"b" + SP + "c", "/a/b", "c");
+ test("\"/a;b\"" + SP + "c", "/a;b", "c");
+ test("\"/a:b\"" + SP + "c", "/a:b", "c");
+ test("\"/a" + SP + "b\"" + SP + "c", "/a" + SP + "b", "c");
+ test("/\"a\"\";\"\"b\"" + SP + "\"c\"", "/a;b", "c");
+ test("/\"a:\"b" + SP + "c", "/a:b", "c");
+ }
+ }
+
+ static void test(String s, String... expected) throws Throwable {
+ System.setProperty(propName, s);
+ String[] res = (String[])method.invoke(null, propName);
+ if (!Arrays.asList(res).equals(Arrays.asList(expected))) {
+ throw new RuntimeException("Parsing [" + s + "] " +
+ " result " + Arrays.asList(res) +
+ " doesn't match " + Arrays.asList(expected));
+ }
+ }
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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,15 +34,16 @@
* @build jdk.testlibrary.* LowMemoryTest MemoryUtil RunUtil
* @requires vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null"
* @run main/timeout=600 LowMemoryTest
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
+ * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
+ * @requires vm.opt.DisableExplicitGC != "true"
*/
-import com.sun.management.DiagnosticCommandMBean;
import java.lang.management.*;
import java.util.*;
import java.util.concurrent.Phaser;
import javax.management.*;
import javax.management.openmbean.CompositeData;
-import sun.management.ManagementFactoryHelper;
public class LowMemoryTest {
private static final MemoryMXBean mm = ManagementFactory.getMemoryMXBean();
--- a/jdk/test/java/net/URI/Test.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/java/net/URI/Test.java Wed Jul 05 20:15:59 2017 +0200
@@ -24,7 +24,7 @@
/* @test
* @summary Unit test for java.net.URI
* @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800
- * 7171415
+ * 7171415 6933879
* @author Mark Reinhold
*/
@@ -1600,6 +1600,7 @@
static void bugs() {
b6339649();
+ b6933879();
b8037396();
}
@@ -1614,6 +1615,18 @@
}
}
+ // 6933879 - check that "." and "_" characters are allowed in IPv6 scope_id.
+ private static void b6933879() {
+ final String HOST = "fe80::c00:16fe:cebe:3214%eth1.12_55";
+ URI uri;
+ try {
+ uri = new URI("http", null, HOST, 10, "/", null, null);
+ } catch (URISyntaxException ex) {
+ throw new AssertionError("Should not happen", ex);
+ }
+ eq("[" + HOST + "]", uri.getHost());
+ }
+
private static void b8037396() {
// primary checks:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Hashtable/DeserializedLength.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, 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.io.*;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
+
+/**
+ * @test
+ * @bug 8068427
+ * @summary Hashtable deserialization reconstitutes table with wrong capacity
+ */
+public class DeserializedLength {
+
+ static boolean testDeserializedLength(int elements, float loadFactor) throws Exception {
+
+ // construct Hashtable with minimal initial capacity and given loadFactor
+ Hashtable<Integer, Integer> ht1 = new Hashtable<>(1, loadFactor);
+
+ // add given number of unique elements
+ for (int i = 0; i < elements; i++) {
+ ht1.put(i, i);
+ }
+
+ // serialize and deserialize into a deep clone
+ Hashtable<Integer, Integer> ht2 = serialClone(ht1);
+
+ // compare lengths of internal tables
+ Object[] table1 = (Object[]) hashtableTableField.get(ht1);
+ Object[] table2 = (Object[]) hashtableTableField.get(ht2);
+ assert table1 != null;
+ assert table2 != null;
+
+ int minLength = (int) (ht1.size() / loadFactor) + 1;
+ int maxLength = minLength * 2;
+
+ boolean ok = (table2.length >= minLength && table2.length <= maxLength);
+
+ System.out.printf(
+ "%7d %5.2f %7d %7d %7d...%7d %s\n",
+ ht1.size(), loadFactor,
+ table1.length, table2.length,
+ minLength, maxLength,
+ (ok ? "OK" : "NOT-OK")
+ );
+
+ return ok;
+ }
+
+ static <T> T serialClone(T o) throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(o);
+ }
+ @SuppressWarnings("unchecked")
+ T clone = (T) new ObjectInputStream(
+ new ByteArrayInputStream(bos.toByteArray())).readObject();
+ return clone;
+ }
+
+ private static final Field hashtableTableField;
+
+ static {
+ try {
+ hashtableTableField = Hashtable.class.getDeclaredField("table");
+ hashtableTableField.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new Error(e);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+
+ System.out.printf("Results:\n" +
+ " ser. deser.\n" +
+ " size load lentgh length valid range ok?\n" +
+ "------- ----- ------- ------- ----------------- ------\n"
+ );
+
+ for (int elements : new int[]{10, 50, 500, 5000}) {
+ for (float loadFactor : new float[]{0.15f, 0.5f, 0.75f, 1.0f, 2.5f}) {
+ ok &= testDeserializedLength(elements, loadFactor);
+ }
+ }
+ if (!ok) {
+ throw new AssertionError("Test failed.");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, 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 org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+
+
+/**
+ * @test
+ * @bug 8068432
+ * @run testng ThenComposeExceptionTest
+ * @summary Test that CompletableFuture.thenCompose works correctly if the
+ * composing future completes exceptionally
+ */
+@Test
+public class ThenComposeExceptionTest {
+
+ static final BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>>
+ THEN_COMPOSE = (f, fe) -> f.thenCompose(s -> fe);
+
+ static final BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>>
+ THEN_COMPOSE_ASYNC = (f, fe) -> f.thenComposeAsync(s -> fe);
+
+ static final Consumer<CompletableFuture<String>>
+ COMPLETE_EXCEPTIONALLY = f -> f.completeExceptionally(new RuntimeException());
+
+ static final Consumer<CompletableFuture<String>>
+ NOP = f -> { };
+
+ static Object[][] actionsDataProvider;
+
+ @DataProvider(name = "actions")
+ static Object[][] actionsDataProvider() {
+ if (actionsDataProvider != null) {
+ return actionsDataProvider;
+ }
+
+ List<Object[]> data = new ArrayList<>();
+ data.add(new Object[]{"thenCompose and completeExceptionally", NOP, THEN_COMPOSE, COMPLETE_EXCEPTIONALLY});
+ data.add(new Object[]{"thenComposeAsync and completeExceptionally", NOP, THEN_COMPOSE_ASYNC, COMPLETE_EXCEPTIONALLY});
+ data.add(new Object[]{"completeExceptionally and thenCompose", COMPLETE_EXCEPTIONALLY, THEN_COMPOSE, NOP});
+ data.add(new Object[]{"completeExceptionally and thenComposeAsync", COMPLETE_EXCEPTIONALLY, THEN_COMPOSE_ASYNC, NOP});
+
+ return actionsDataProvider = data.toArray(new Object[0][]);
+ }
+
+ @Test(dataProvider = "actions")
+ public void testThenCompose(
+ String description,
+ Consumer<CompletableFuture<String>> beforeAction,
+ BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>> composeFunction,
+ Consumer<CompletableFuture<String>> afterAction) throws Exception {
+ CompletableFuture<String> f = new CompletableFuture<>();
+ CompletableFuture<String> fe = new CompletableFuture<>();
+
+ // Ensure pre-composed stage is completed to trigger
+ // processing the composing future
+ f.complete("");
+
+ beforeAction.accept(fe);
+
+ CompletableFuture<String> f_thenCompose = composeFunction.apply(f, fe);
+ Assert.assertNotSame(f_thenCompose, fe, "Composed CompletableFuture returned directly");
+
+ AtomicReference<Throwable> eOnWhenComplete = new AtomicReference<>();
+ f_thenCompose.whenComplete((r, e) -> eOnWhenComplete.set(e));
+
+ afterAction.accept(fe);
+
+ Throwable eOnJoined = null;
+ try {
+ f_thenCompose.join();
+ }
+ catch (Throwable t) {
+ eOnJoined = t;
+ }
+
+ Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException,
+ "Incorrect exception reported on whenComplete");
+ Assert.assertTrue(eOnJoined instanceof CompletionException,
+ "Incorrect exception reported when joined");
+ }
+}
--- a/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java Wed Jul 05 20:15:59 2017 +0200
@@ -120,6 +120,10 @@
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
String keyFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + keyStoreFile;
--- a/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorer.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorer.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -44,6 +44,7 @@
import java.net.*;
import java.util.*;
import java.nio.channels.*;
+import java.security.Security;
public class SSLEngineExplorer extends SSLEngineService {
@@ -231,6 +232,10 @@
volatile int serverPort = 0;
public static void main(String args[]) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
if (debug)
System.setProperty("javax.net.debug", "all");
--- a/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorer.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorer.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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,6 +45,7 @@
import java.util.*;
import java.net.*;
import javax.net.ssl.*;
+import java.security.Security;
public class SSLSocketExplorer {
@@ -224,6 +225,10 @@
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
String keyFilename =
System.getProperty("test.src", ".") + "/" + pathToStores +
"/" + keyStoreFile;
--- a/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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,8 +29,10 @@
/*
* @test
- * @bug 8049432
+ * @bug 8049432 8069038
* @summary New tests for TLS property jdk.tls.client.protocols
+ * @summary javax/net/ssl/TLS/TLSClientPropertyTest.java needs to be
+ * updated for JDK-8061210
* @run main/othervm TLSClientPropertyTest NoProperty
* @run main/othervm TLSClientPropertyTest SSLv3
* @run main/othervm TLSClientPropertyTest TLSv1
@@ -46,7 +48,7 @@
* protocols in the SSLContext.
*/
public class TLSClientPropertyTest {
- private final String[] expecteSupportedProtos = new String[] {
+ private final String[] expectedSupportedProtos = new String[] {
"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
};
@@ -67,31 +69,30 @@
}
contextProtocol = null;
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
+ "TLSv1", "TLSv1.1", "TLSv1.2"
};
break;
case "SSLv3":
contextProtocol = "SSLv3";
expectedDefaultProtos = new String[] {
- "SSLv3"
};
break;
case "TLSv1":
contextProtocol = "TLSv1";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1"
+ "TLSv1"
};
break;
case "TLSv11":
contextProtocol = "TLSv1.1";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1"
+ "TLSv1", "TLSv1.1"
};
break;
case "TLSv12":
contextProtocol = "TLSv1.2";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
+ "TLSv1", "TLSv1.1", "TLSv1.2"
};
break;
case "WrongProperty":
@@ -182,12 +183,12 @@
expectedProto = "Default";
}
if (!context.getProtocol().equals(expectedProto)) {
- error("Invalid current protocol:" + context.getProtocol()
+ error("Invalid current protocol: " + context.getProtocol()
+ ", Expected:" + expectedProto, null);
}
List<String> actualDefaultProtos = Arrays.asList(context
.getDefaultSSLParameters().getProtocols());
- for (String p: expectedDefaultProtos) {
+ for (String p : expectedDefaultProtos) {
if (!actualDefaultProtos.contains(p)) {
error("Default protocol " + p + "missing", null);
}
@@ -195,7 +196,7 @@
List<String> actualSupportedProtos = Arrays.asList(context
.getSupportedSSLParameters().getProtocols());
- for (String p: expecteSupportedProtos) {
+ for (String p : expectedSupportedProtos) {
if (!actualSupportedProtos.contains(p)) {
error("Expected to support protocol:" + p, null);
}
--- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java Wed Jul 05 20:15:59 2017 +0200
@@ -78,6 +78,10 @@
private static final String LOCAL_IP = "127.0.0.1";
public static void main(String... args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
String serverProtocol = System.getProperty("SERVER_PROTOCOL");
String clientProtocol = System.getProperty("CLIENT_PROTOCOL");
int port = jdk.testlibrary.Utils.getFreePort();
--- a/jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java Wed Jul 05 20:15:59 2017 +0200
@@ -33,6 +33,10 @@
public class ClientJSSEServerJSSE {
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
// MD5 is used in this test case, don't disable MD5 algorithm.
Security.setProperty(
"jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
--- a/jdk/test/javax/sql/testng/test/rowset/BaseRowSetTests.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/sql/testng/test/rowset/BaseRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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,13 +30,9 @@
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
import java.sql.Date;
import java.sql.Ref;
-import java.sql.RowId;
-import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
@@ -44,407 +40,74 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import javax.sql.RowSet;
import javax.sql.rowset.serial.SerialArray;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialClob;
import javax.sql.rowset.serial.SerialRef;
import static org.testng.Assert.*;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
-import util.BaseTest;
import util.StubArray;
import util.StubBaseRowSet;
import util.StubBlob;
import util.StubClob;
-import util.StubNClob;
import util.StubRef;
-import util.StubRowId;
-import util.StubSQLXML;
import util.TestRowSetListener;
-public class BaseRowSetTests extends BaseTest {
+public class BaseRowSetTests extends CommonRowSetTests {
private StubBaseRowSet brs;
- private StubBaseRowSet brs1;
- private final String query = "SELECT * FROM SUPERHEROS";
- private final String url = "jdbc:derby://localhost:1527/myDB";
- private final String dsName = "jdbc/myDB";
- private final String user = "Bruce Wayne";
- private final String password = "The Dark Knight";
- private final Date aDate = Date.valueOf(LocalDate.now());
- private final Time aTime = Time.valueOf(LocalTime.now());
- private final Timestamp ts = Timestamp.valueOf(LocalDateTime.now());
- private final Calendar cal = Calendar.getInstance();
- private final byte[] bytes = new byte[10];
- private RowId aRowid;
- private Ref aRef;
- private Blob aBlob;
- private Clob aClob;
- private Array aArray;
- private InputStream is;
- private Reader rdr;
- private Map<String, Class<?>> map = new HashMap<>();
- public BaseRowSetTests() {
- brs1 = new StubBaseRowSet();
- is = new StringBufferInputStream(query);
- rdr = new StringReader(query);
- aRowid = new StubRowId();
- try {
- aBlob = new SerialBlob(new StubBlob());
- aClob = new SerialClob(new StubClob());
- aRef = new SerialRef(new StubRef("INTEGER", query));
- aArray = new SerialArray(new StubArray("INTEGER", new Object[1]));
- map.put("SUPERHERO", Class.forName("util.SuperHero"));
- } catch (SQLException | ClassNotFoundException ex) {
- Logger.getLogger(BaseRowSetTests.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- @BeforeMethod
@Override
- public void setUpMethod() throws Exception {
- brs = new StubBaseRowSet();
- }
-
- /*
- * Validate that getCommand() returns null by default
- */
- @Test
- public void test() {
- assertTrue(brs.getCommand() == null);
- }
-
- /*
- * Validate that getCommand() returns command specified to setCommand
- */
- @Test
- public void test01() throws Exception {
- brs.setCommand(query);
- assertTrue(brs.getCommand().equals(query));
- }
-
- /*
- * Validate that getCurrency() returns the correct default value
- */
- @Test
- public void test02() throws Exception {
- assertTrue(brs.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
- }
-
- /*
- * Validate that getCurrency() returns the correct value
- * after a call to setConcurrency())
- */
- @Test(dataProvider = "concurTypes")
- public void test03(int concurType) throws Exception {
- brs.setConcurrency(concurType);
- assertTrue(brs.getConcurrency() == concurType);
- }
-
- /*
- * Validate that getCurrency() throws a SQLException for an invalid value
- */
- @Test(expectedExceptions = SQLException.class)
- public void test04() throws Exception {
- brs.setConcurrency(ResultSet.CLOSE_CURSORS_AT_COMMIT);
- }
-
- /*
- * Validate that getDataSourceName() returns null by default
- */
- @Test
- public void test05() throws Exception {
- assertTrue(brs.getDataSourceName() == null);
- }
-
- /*
- * Validate that getDataSourceName() returns the value specified
- * by setDataSourceName() and getUrl() returns null
- */
- @Test
- public void test06() throws Exception {
- brs.setUrl(url);
- brs.setDataSourceName(dsName);
- assertTrue(brs.getDataSourceName().equals(dsName));
- assertTrue(brs.getUrl() == null);
- }
-
- /*
- * Validate that setDataSourceName() throws a SQLException for an empty
- * String specified for the data source name
- */
- @Test(expectedExceptions = SQLException.class)
- public void test07() throws Exception {
- String dsname = "";
- brs.setDataSourceName(dsname);
- }
-
- /*
- * Validate that getEscapeProcessing() returns true by default
- */
- @Test
- public void test08() throws Exception {
- assertTrue(brs.getEscapeProcessing());
- }
-
- /*
- * Validate that getEscapeProcessing() returns value set by
- * setEscapeProcessing()
- */
- @Test(dataProvider = "trueFalse")
- public void test09(boolean val) throws Exception {
- brs.setEscapeProcessing(val);
- assertTrue(brs.getEscapeProcessing() == val);
- }
-
- /*
- * Validate that getFetchDirection() returns the correct default value
- */
- @Test
- public void test10() throws Exception {
- assertTrue(brs.getFetchDirection() == ResultSet.FETCH_FORWARD);
- }
-
- /*
- * Validate that getFetchDirection() returns the value set by
- * setFetchDirection()
- */
- @Test(dataProvider = "fetchDirection")
- public void test11(int direction) throws Exception {
- brs.setFetchDirection(direction);
- assertTrue(brs.getFetchDirection() == direction);
+ protected RowSet newInstance() throws SQLException {
+ return new StubBaseRowSet();
}
/*
- * Validate that setConcurrency() throws a SQLException for an invalid value
- */
- @Test(expectedExceptions = SQLException.class)
- public void test12() throws Exception {
- brs.setConcurrency(ResultSet.CLOSE_CURSORS_AT_COMMIT);
- }
-
- /*
- * Validate that setFetchSize() throws a SQLException for an invalid value
- */
- @Test(expectedExceptions = SQLException.class)
- public void test13() throws Exception {
- brs.setFetchSize(-1);
- }
-
- /*
- * Validate that setFetchSize() throws a SQLException for a
- * value greater than getMaxRows()
- */
- @Test(expectedExceptions = SQLException.class)
- public void test14() throws Exception {
- brs.setMaxRows(5);
- brs.setFetchSize(brs.getMaxRows() + 1);
- }
-
- /*
- * Validate that getFetchSize() returns the correct value after
- * setFetchSize() has been called
+ * Create a RowSetListener and validate that notifyCursorMoved is called
*/
- @Test
- public void test15() throws Exception {
- int maxRows = 150;
- brs.setFetchSize(0);
- assertTrue(brs.getFetchSize() == 0);
- brs.setFetchSize(100);
- assertTrue(brs.getFetchSize() == 100);
- brs.setMaxRows(maxRows);
- brs.setFetchSize(maxRows);
- assertTrue(brs.getFetchSize() == maxRows);
- }
-
- /*
- * Validate that setMaxFieldSize() throws a SQLException for an invalid value
- */
- @Test(expectedExceptions = SQLException.class)
- public void test16() throws Exception {
- brs.setMaxFieldSize(-1);
- }
-
- /*
- * Validate that getMaxFieldSize() returns the value set by
- * setMaxFieldSize()
- */
- @Test
- public void test17() throws Exception {
- brs.setMaxFieldSize(0);
- assertTrue(brs.getMaxFieldSize() == 0);
- brs.setMaxFieldSize(100);
- assertTrue(brs.getMaxFieldSize() == 100);
- brs.setMaxFieldSize(50);
- assertTrue(brs.getMaxFieldSize() == 50);
- }
-
- /*
- * Validate that isReadOnly() returns value set by
- * setReadOnly()
- */
- @Test(dataProvider = "trueFalse")
- public void test18(boolean val) throws Exception {
- brs.setReadOnly(val);
- assertTrue(brs.isReadOnly() == val);
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0000(StubBaseRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.notifyCursorMoved();
+ assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
}
/*
- * Validate that getTransactionIsolation() returns value set by
- * setTransactionIsolation()
- */
- @Test(dataProvider = "isolationTypes")
- public void test19(int val) throws Exception {
- brs.setTransactionIsolation(val);
- assertTrue(brs.getTransactionIsolation() == val);
- }
-
- /*
- * Validate that getType() returns value set by setType()
- */
- @Test(dataProvider = "scrollTypes")
- public void test20(int val) throws Exception {
- brs.setType(val);
- assertTrue(brs.getType() == val);
- }
-
- /*
- * Validate that getEscapeProcessing() returns value set by
- * setEscapeProcessing()
- */
- @Test(dataProvider = "trueFalse")
- public void test21(boolean val) throws Exception {
- brs.setShowDeleted(val);
- assertTrue(brs.getShowDeleted() == val);
- }
-
- /*
- * Validate that getTypeMap() returns same value set by
- * setTypeMap()
- */
- @Test()
- public void test22() throws Exception {
- brs.setTypeMap(map);
- assertTrue(brs.getTypeMap().equals(map));
- }
-
- /*
- * Validate that getUsername() returns same value set by
- * setUsername()
+ * Create a RowSetListener and validate that notifyRowChanged is called
*/
- @Test()
- public void test23() throws Exception {
- brs.setUsername(user);
- assertTrue(brs.getUsername().equals(user));
- }
-
- /*
- * Validate that getPassword() returns same password set by
- * setPassword()
- */
- @Test()
- public void test24() throws Exception {
- brs.setPassword(password);
- assertTrue(brs.getPassword().equals(password));
- }
-
- /*
- * Validate that getQueryTimeout() returns same value set by
- * setQueryTimeout() and that 0 is a valid timeout value
- */
- @Test()
- public void test25() throws Exception {
- int timeout = 0;
- brs.setQueryTimeout(timeout);
- assertTrue(brs.getQueryTimeout() == timeout);
- }
-
- /*
- * Validate that getQueryTimeout() returns same value set by
- * setQueryTimeout() and that 0 is a valid timeout value
- */
- @Test()
- public void test26() throws Exception {
- int timeout = 10000;
- brs.setQueryTimeout(timeout);
- assertTrue(brs.getQueryTimeout() == timeout);
- }
-
- /*
- * Validate that setQueryTimeout() throws a SQLException for a timeout
- * value < 0
- */
- @Test(expectedExceptions = SQLException.class)
- public void test27() throws Exception {
- brs.setQueryTimeout(-1);
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0001(StubBaseRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.notifyRowChanged();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
}
/*
* Create a RowSetListener and validate that notifyRowSetChanged is called
*/
- @Test()
- public void test28() throws Exception {
- TestRowSetListener rsl = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.notifyRowSetChanged();
- assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
- }
-
- /*
- * Create a RowSetListener and validate that notifyRowChanged is called
- */
- @Test()
- public void test29() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0002(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.notifyRowChanged();
- assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
- }
-
- /*
- * Create a RowSetListener and validate that notifyCursorMoved is called
- */
- @Test()
- public void test30() throws Exception {
- TestRowSetListener rsl = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.notifyCursorMoved();
- assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
- }
-
- /*
- * Create a RowSetListener and validate that notifyRowSetChanged,
- * notifyRowChanged() and notifyCursorMoved are called
- */
- @Test()
- public void test31() throws Exception {
- TestRowSetListener rsl = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.notifyRowSetChanged();
- brs.notifyRowChanged();
- brs.notifyCursorMoved();
- assertTrue(rsl.isNotified(
- TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
- | TestRowSetListener.ROW_CHANGED));
+ rs.addRowSetListener(rsl);
+ rs.notifyRowSetChanged();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
}
/*
* Create multiple RowSetListeners and validate that notifyRowSetChanged
* is called on all listeners
*/
- @Test()
- public void test32() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0003(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
TestRowSetListener rsl2 = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.addRowSetListener(rsl2);
- brs.notifyRowSetChanged();
+ rs.addRowSetListener(rsl);
+ rs.addRowSetListener(rsl2);
+ rs.notifyRowSetChanged();
assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
assertTrue(rsl2.isNotified(TestRowSetListener.ROWSET_CHANGED));
}
@@ -453,13 +116,13 @@
* Create multiple RowSetListeners and validate that notifyRowChanged
* is called on all listeners
*/
- @Test()
- public void test33() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0004(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
TestRowSetListener rsl2 = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.addRowSetListener(rsl2);
- brs.notifyRowChanged();
+ rs.addRowSetListener(rsl);
+ rs.addRowSetListener(rsl2);
+ rs.notifyRowChanged();
assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
assertTrue(rsl2.isNotified(TestRowSetListener.ROW_CHANGED));
}
@@ -468,30 +131,47 @@
* Create multiple RowSetListeners and validate that notifyCursorMoved
* is called on all listeners
*/
- @Test()
- public void test34() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0005(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
TestRowSetListener rsl2 = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.addRowSetListener(rsl2);
- brs.notifyCursorMoved();
+ rs.addRowSetListener(rsl);
+ rs.addRowSetListener(rsl2);
+ rs.notifyCursorMoved();
assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
assertTrue(rsl2.isNotified(TestRowSetListener.CURSOR_MOVED));
}
/*
+ * Create a RowSetListener and validate that notifyRowSetChanged,
+ * notifyRowChanged() and notifyCursorMoved are called
+ */
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0006(StubBaseRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.notifyRowSetChanged();
+ rs.notifyRowChanged();
+ rs.notifyCursorMoved();
+ assertTrue(rsl.isNotified(
+ TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
+ | TestRowSetListener.ROW_CHANGED));
+ }
+
+
+ /*
* Create multiple RowSetListeners and validate that notifyRowSetChanged,
* notifyRowChanged() and notifyCursorMoved are called on all listeners
*/
- @Test()
- public void test35() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0007(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
TestRowSetListener rsl2 = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.addRowSetListener(rsl2);
- brs.notifyRowSetChanged();
- brs.notifyRowChanged();
- brs.notifyCursorMoved();
+ rs.addRowSetListener(rsl);
+ rs.addRowSetListener(rsl2);
+ rs.notifyRowSetChanged();
+ rs.notifyRowChanged();
+ rs.notifyCursorMoved();
assertTrue(rsl.isNotified(
TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
| TestRowSetListener.ROW_CHANGED));
@@ -505,55 +185,25 @@
* remove the listener, invoke notifyRowSetChanged again and verify the
* listner is not called
*/
- @Test()
- public void test36() throws Exception {
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0008(StubBaseRowSet rs) throws Exception {
TestRowSetListener rsl = new TestRowSetListener();
- brs.addRowSetListener(rsl);
- brs.notifyRowSetChanged();
+ rs.addRowSetListener(rsl);
+ rs.notifyRowSetChanged();
assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
// Clear the flag indicating the listener has been called
rsl.resetFlag();
- brs.removeRowSetListener(rsl);
- brs.notifyRowSetChanged();
+ rs.removeRowSetListener(rsl);
+ rs.notifyRowSetChanged();
assertFalse(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
}
/*
- * Validate addRowSetListener does not throw an Exception when null is
- * passed as the parameter
- */
- @Test()
- public void test37() throws Exception {
- brs.addRowSetListener(null);
- }
-
- /*
- * Validate removeRowSetListener does not throw an Exception when null is
- * passed as the parameter
- */
- @Test()
- public void test38() throws Exception {
- brs.removeRowSetListener(null);
- }
-
- /*
- * Set two parameters and then validate clearParameters() will clear them
- */
- @Test()
- public void test39() throws Exception {
- brs.setInt(1, 1);
- brs.setString(2, query);
- assertTrue(brs.getParams().length == 2);
- brs.clearParameters();
- assertTrue(brs.getParams().length == 0);
- }
-
- /*
* Set the base parameters and validate that the value set is
* the correct type and value
*/
@Test(dataProvider = "testBaseParameters")
- public void test40(int pos, Object o) throws Exception {
+ public void baseRowSetTest0009(int pos, Object o) throws Exception {
assertTrue(getParam(pos, o).getClass().isInstance(o));
assertTrue(o.equals(getParam(pos, o)));
}
@@ -563,7 +213,7 @@
* the correct type
*/
@Test(dataProvider = "testAdvancedParameters")
- public void test41(int pos, Object o) throws Exception {
+ public void baseRowSetTest0010(int pos, Object o) throws Exception {
assertTrue(getParam(pos, o).getClass().isInstance(o));
}
@@ -571,7 +221,8 @@
* Validate setNull specifying the supported type values
*/
@Test(dataProvider = "jdbcTypes")
- public void test42(Integer type) throws Exception {
+ public void baseRowSetTest0011(Integer type) throws Exception {
+ brs = new StubBaseRowSet();
brs.setNull(1, type);
assertTrue(checkNullParam(1, type, null));
}
@@ -581,7 +232,8 @@
* typeName is set internally
*/
@Test(dataProvider = "jdbcTypes")
- public void test43(Integer type) throws Exception {
+ public void baseRowSetTest0012(Integer type) throws Exception {
+ brs = new StubBaseRowSet();
brs.setNull(1, type, "SUPERHERO");
assertTrue(checkNullParam(1, type, "SUPERHERO"));
}
@@ -590,8 +242,10 @@
* Validate that setDate sets the specified Calendar internally
*/
@Test()
- public void test44() throws Exception {
- brs.setDate(1, aDate, cal);
+ public void baseRowSetTest0013() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ brs = new StubBaseRowSet();
+ brs.setDate(1, Date.valueOf(LocalDate.now()), cal);
assertTrue(checkCalendarParam(1, cal));
}
@@ -599,8 +253,10 @@
* Validate that setTime sets the specified Calendar internally
*/
@Test()
- public void test45() throws Exception {
- brs.setTime(1, aTime, cal);
+ public void baseRowSetTest0014() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ brs = new StubBaseRowSet();
+ brs.setTime(1, Time.valueOf(LocalTime.now()), cal);
assertTrue(checkCalendarParam(1, cal));
}
@@ -608,564 +264,23 @@
* Validate that setTimestamp sets the specified Calendar internally
*/
@Test()
- public void test46() throws Exception {
- brs.setTimestamp(1, ts, cal);
+ public void baseRowSetTest0015() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ brs = new StubBaseRowSet();
+ brs.setTimestamp(1, Timestamp.valueOf(LocalDateTime.now()), cal);
assertTrue(checkCalendarParam(1, cal));
}
/*
- * Validate that getURL() returns same value set by
- * setURL()
- */
- @Test()
- public void test47() throws Exception {
- brs.setUrl(url);
- assertTrue(brs.getUrl().equals(url));
- }
-
- /*
* Validate that initParams() initializes the parameters
*/
- @Test()
- public void test48() throws Exception {
- brs.setInt(1, 1);
- brs.initParams();
- assertTrue(brs.getParams().length == 0);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
-
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test100() throws Exception {
- brs1.setAsciiStream(1, is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test101() throws Exception {
- brs1.setAsciiStream("one", is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test102() throws Exception {
- brs1.setAsciiStream("one", is, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test103() throws Exception {
- brs1.setBinaryStream(1, is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test104() throws Exception {
- brs1.setBinaryStream("one", is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test105() throws Exception {
- brs1.setBinaryStream("one", is, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test106() throws Exception {
- brs1.setBigDecimal("one", BigDecimal.ONE);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test107() throws Exception {
- brs1.setBlob(1, is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test108() throws Exception {
- brs1.setBlob("one", is);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test109() throws Exception {
- brs1.setBlob("one", is, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test110() throws Exception {
- brs1.setBlob("one", aBlob);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test111() throws Exception {
- brs1.setBoolean("one", true);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test112() throws Exception {
- byte b = 1;
- brs1.setByte("one", b);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test113() throws Exception {
- byte b = 1;
- brs1.setBytes("one", bytes);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test114() throws Exception {
- brs1.setCharacterStream("one", rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test115() throws Exception {
- brs1.setCharacterStream("one", rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test116() throws Exception {
- brs1.setCharacterStream(1, rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test117() throws Exception {
- brs1.setClob(1, rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test118() throws Exception {
- brs1.setClob("one", rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test119() throws Exception {
- brs1.setClob("one", rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test120() throws Exception {
- brs1.setClob("one", aClob);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test121() throws Exception {
- brs1.setDate("one", aDate);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test122() throws Exception {
- brs1.setDate("one", aDate, cal);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test123() throws Exception {
- brs1.setTime("one", aTime);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test124() throws Exception {
- brs1.setTime("one", aTime, cal);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test125() throws Exception {
- brs1.setTimestamp("one", ts);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test126() throws Exception {
- brs1.setTimestamp("one", ts, cal);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test127() throws Exception {
- brs1.setDouble("one", 2.0d);
+ @Test(dataProvider = "rowSetType")
+ public void baseRowSetTest0016(StubBaseRowSet rs) throws Exception {
+ rs.setInt(1, 1);
+ rs.initParams();
+ assertTrue(rs.getParams().length == 0);
}
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test128() throws Exception {
- brs1.setFloat("one", 2.0f);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test129() throws Exception {
- brs1.setInt("one", 21);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test130() throws Exception {
- brs1.setLong("one", 21l);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test131() throws Exception {
- brs1.setNCharacterStream("one", rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test132() throws Exception {
- brs1.setNCharacterStream("one", rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test133() throws Exception {
- brs1.setNCharacterStream(1, rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test134() throws Exception {
- brs1.setNCharacterStream(1, rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test135() throws Exception {
- brs1.setClob("one", rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test136() throws Exception {
- brs1.setClob("one", rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test137() throws Exception {
- brs1.setNClob("one", new StubNClob());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test138() throws Exception {
- brs1.setNClob(1, rdr);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test139() throws Exception {
- brs1.setNClob(1, rdr, query.length());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test140() throws Exception {
- brs1.setNClob(1, new StubNClob());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test141() throws Exception {
- brs1.setNString(1, query);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test142() throws Exception {
- brs1.setNull("one", Types.INTEGER);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test143() throws Exception {
- brs1.setNull("one", Types.INTEGER, "my.type");
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test144() throws Exception {
- brs1.setObject("one", query, Types.VARCHAR);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test145() throws Exception {
- brs1.setObject("one", query, Types.VARCHAR, 0);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test146() throws Exception {
- brs1.setObject("one", query);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test147() throws Exception {
- brs1.setRowId("one", aRowid);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test148() throws Exception {
- brs1.setSQLXML("one", new StubSQLXML());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test149() throws Exception {
- brs1.setSQLXML(1, new StubSQLXML());
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test150() throws Exception {
- brs1.setNString(1, query);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test151() throws Exception {
- brs1.setNString("one", query);
- }
-
- /*
- * This method is currently not implemented in BaseRowSet and will
- * throw a SQLFeatureNotSupportedException
- */
- @Test(expectedExceptions = SQLFeatureNotSupportedException.class)
- public void test152() throws Exception {
- short val = 21;
- brs1.setShort("one", val);
- }
-
- /*
- * DataProvider used to specify the value to set and check for
- * methods using transaction isolation types
- */
- @DataProvider(name = "isolationTypes")
- private Object[][] isolationTypes() {
- return new Object[][]{
- {Connection.TRANSACTION_NONE},
- {Connection.TRANSACTION_READ_COMMITTED},
- {Connection.TRANSACTION_READ_UNCOMMITTED},
- {Connection.TRANSACTION_REPEATABLE_READ},
- {Connection.TRANSACTION_SERIALIZABLE}
- };
- }
-
- /*
- * DataProvider used to specify the value to set and check for the
- * methods for fetch direction
- */
- @DataProvider(name = "fetchDirection")
- private Object[][] fetchDirection() {
- return new Object[][]{
- {ResultSet.FETCH_FORWARD},
- {ResultSet.FETCH_REVERSE},
- {ResultSet.FETCH_UNKNOWN}
- };
- }
-
- /*
- * DataProvider used to specify the value to set and check for the
- * methods for Concurrency
- */
- @DataProvider(name = "concurTypes")
- private Object[][] concurTypes() {
- return new Object[][]{
- {ResultSet.CONCUR_READ_ONLY},
- {ResultSet.CONCUR_UPDATABLE}
- };
- }
-
- /*
- * DataProvider used to specify the value to set and check for the
- * methods for Cursor Scroll Type
- */
- @DataProvider(name = "scrollTypes")
- private Object[][] scrollTypes() {
- return new Object[][]{
- {ResultSet.TYPE_FORWARD_ONLY},
- {ResultSet.TYPE_SCROLL_INSENSITIVE},
- {ResultSet.TYPE_SCROLL_SENSITIVE}
- };
- }
/*
* DataProvider used to set parameters for basic types that are supported
@@ -1177,29 +292,33 @@
Short aShort = Short.MIN_VALUE;
BigDecimal bd = BigDecimal.ONE;
Double aDouble = Double.MAX_VALUE;
+ Date aDate = Date.valueOf(LocalDate.now());
+ Time aTime = Time.valueOf(LocalTime.now());
+ Timestamp aTimeStamp = Timestamp.valueOf(LocalDateTime.now());
+ Calendar cal = Calendar.getInstance();
Boolean aBoolean = true;
Float aFloat = 1.5f;
Byte aByte = 1;
+ brs = new StubBaseRowSet();
- brs1.clearParameters();
- brs1.setInt(1, aInt);
- brs1.setString(2, query);
- brs1.setLong(3, aLong);
- brs1.setBoolean(4, aBoolean);
- brs1.setShort(5, aShort);
- brs1.setDouble(6, aDouble);
- brs1.setBigDecimal(7, bd);
- brs1.setFloat(8, aFloat);
- brs1.setByte(9, aByte);
- brs1.setDate(10, aDate);
- brs1.setTime(11, aTime);
- brs1.setTimestamp(12, ts);
- brs1.setDate(13, aDate, cal);
- brs1.setTime(14, aTime, cal);
- brs1.setTimestamp(15, ts);
- brs1.setObject(16, query);
- brs1.setObject(17, query, Types.CHAR);
- brs1.setObject(18, query, Types.CHAR, 0);
+ brs.setInt(1, aInt);
+ brs.setString(2, query);
+ brs.setLong(3, aLong);
+ brs.setBoolean(4, aBoolean);
+ brs.setShort(5, aShort);
+ brs.setDouble(6, aDouble);
+ brs.setBigDecimal(7, bd);
+ brs.setFloat(8, aFloat);
+ brs.setByte(9, aByte);
+ brs.setDate(10, aDate);
+ brs.setTime(11, aTime);
+ brs.setTimestamp(12, aTimeStamp);
+ brs.setDate(13, aDate, cal);
+ brs.setTime(14, aTime, cal);
+ brs.setTimestamp(15, aTimeStamp);
+ brs.setObject(16, query);
+ brs.setObject(17, query, Types.CHAR);
+ brs.setObject(18, query, Types.CHAR, 0);
return new Object[][]{
{1, aInt},
@@ -1213,10 +332,10 @@
{9, aByte},
{10, aDate},
{11, aTime},
- {12, ts},
+ {12, aTimeStamp},
{13, aDate},
{14, aTime},
- {15, ts},
+ {15, aTimeStamp},
{16, query},
{17, query},
{18, query}
@@ -1230,16 +349,23 @@
@DataProvider(name = "testAdvancedParameters")
private Object[][] testAdvancedParameters() throws SQLException {
- brs1.clearParameters();
- brs1.setBytes(1, bytes);
- brs1.setAsciiStream(2, is, query.length());
- brs1.setRef(3, aRef);
- brs1.setArray(4, aArray);
- brs1.setBlob(5, aBlob);
- brs1.setClob(6, aClob);
- brs1.setBinaryStream(7, is, query.length());
- brs1.setUnicodeStream(8, is, query.length());
- brs1.setCharacterStream(9, rdr, query.length());
+ byte[] bytes = new byte[10];
+ Ref aRef = new SerialRef(new StubRef("INTEGER", query));
+ Array aArray = new SerialArray(new StubArray("INTEGER", new Object[1]));
+ Blob aBlob = new SerialBlob(new StubBlob());
+ Clob aClob = new SerialClob(new StubClob());
+ Reader rdr = new StringReader(query);
+ InputStream is = new StringBufferInputStream(query);;
+ brs = new StubBaseRowSet();
+ brs.setBytes(1, bytes);
+ brs.setAsciiStream(2, is, query.length());
+ brs.setRef(3, aRef);
+ brs.setArray(4, aArray);
+ brs.setBlob(5, aBlob);
+ brs.setClob(6, aClob);
+ brs.setBinaryStream(7, is, query.length());
+ brs.setUnicodeStream(8, is, query.length());
+ brs.setCharacterStream(9, rdr, query.length());
return new Object[][]{
{1, bytes},
@@ -1261,7 +387,7 @@
*/
@SuppressWarnings("unchecked")
private <T> T getParam(int pos, T o) throws SQLException {
- Object[] params = brs1.getParams();
+ Object[] params = brs.getParams();
if (params[pos - 1] instanceof Object[]) {
Object[] param = (Object[]) params[pos - 1];
return (T) param[0];
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/CommonRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,1372 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.sql.RowSet;
+import javax.sql.rowset.BaseRowSet;
+import javax.sql.rowset.CachedRowSet;
+import javax.sql.rowset.RowSetFactory;
+import javax.sql.rowset.RowSetMetaDataImpl;
+import javax.sql.rowset.RowSetProvider;
+import org.testng.Assert;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import util.BaseTest;
+import util.StubBlob;
+import util.StubClob;
+import util.StubNClob;
+import util.StubSQLXML;
+
+public abstract class CommonRowSetTests extends BaseTest {
+
+ protected final String stubProvider = "util.StubSyncProvider";
+ protected final String query = "SELECT * FROM SUPERHEROS";
+ private final String url = "jdbc:derby://localhost:1527/myDB";
+ private final String dsName = "jdbc/myDB";
+ private final String user = "Bruce Wayne";
+ private final String password = "The Dark Knight";
+ protected final String COFFEE_HOUSES_TABLE = "COFFEE_HOUSES";
+ protected final String COFFEES_TABLE = "COFFEES";
+ protected final int COFFEE_HOUSES_ROWS = 14;
+ protected final int COFFEES_ROWS = 5;
+ protected final Object[] COFFEES_PRIMARY_KEYS = {1, 2, 3, 4, 5};
+ protected final Object[] COFFEE_HOUSES_PRIMARY_KEYS = {
+ 10023, 33002, 10040, 32001, 10042, 10024, 10039, 10041,
+ 33005, 33010, 10035, 10037, 10034, 32004
+ };
+
+ /*
+ * COFFEES_HOUSES Table column names
+ */
+ protected final String[] COFFEE_HOUSES_COLUMN_NAMES = {
+ "STORE_ID", "CITY", "COFFEE", "MERCH", "TOTAL"
+ };
+
+ /*
+ * COFFEES Table column names
+ */
+ protected final String[] COFFEES_COLUMN_NAMES = {
+ "COF_ID", "COF_NAME", "SUP_ID", "PRICE", "SALES", "TOTAL"
+ };
+
+ protected RowSetFactory rsf;
+
+ public CommonRowSetTests() {
+ try {
+ rsf = RowSetProvider.newFactory();
+ } catch (SQLException ex) {
+ Assert.fail(ex.getMessage());
+ }
+ }
+
+ // Create an instance of the RowSet we are using
+ protected abstract <T extends RowSet> T newInstance() throws SQLException;
+
+ //DataProvider to use for common tests
+
+ /*
+ * DataProvider used to specify the value to set and check for the
+ * methods for fetch direction
+ */
+ @DataProvider(name = "rowSetFetchDirection")
+ protected Object[][] rowSetFetchDirection() throws Exception {
+ RowSet rs = newInstance();
+ return new Object[][]{
+ {rs, ResultSet.FETCH_FORWARD},
+ {rs, ResultSet.FETCH_REVERSE},
+ {rs, ResultSet.FETCH_UNKNOWN}
+ };
+ }
+
+ /*
+ * DataProvider used to specify the value to set and check for the
+ * methods for Cursor Scroll Type
+ */
+ @DataProvider(name = "rowSetScrollTypes")
+ protected Object[][] rowSetScrollTypes() throws Exception {
+ RowSet rs = newInstance();
+
+ return new Object[][]{
+ {rs, ResultSet.TYPE_FORWARD_ONLY},
+ {rs, ResultSet.TYPE_SCROLL_INSENSITIVE},
+ {rs, ResultSet.TYPE_SCROLL_SENSITIVE}
+ };
+ }
+
+ /*
+ * DataProvider used to specify the value to set and check for
+ * methods using transaction isolation types
+ */
+ @DataProvider(name = "rowSetIsolationTypes")
+ protected Object[][] rowSetIsolationTypes() throws Exception {
+ RowSet rs = newInstance();
+
+ return new Object[][]{
+ {rs, Connection.TRANSACTION_NONE},
+ {rs, Connection.TRANSACTION_READ_COMMITTED},
+ {rs, Connection.TRANSACTION_READ_UNCOMMITTED},
+ {rs, Connection.TRANSACTION_REPEATABLE_READ},
+ {rs, Connection.TRANSACTION_SERIALIZABLE}
+ };
+ }
+
+ /*
+ * DataProvider used to specify the value to set and check for the
+ * methods for Concurrency
+ */
+ @DataProvider(name = "rowSetConcurrencyTypes")
+ protected Object[][] rowSetConcurrencyTypes() throws Exception {
+ RowSet rs = newInstance();
+ return new Object[][]{
+ {rs, ResultSet.CONCUR_READ_ONLY},
+ {rs, ResultSet.CONCUR_UPDATABLE}
+ };
+ }
+
+ /*
+ * DataProvider used to specify the value to set and check for
+ * methods using boolean values
+ */
+ @DataProvider(name = "rowSetTrueFalse")
+ protected Object[][] rowSetTrueFalse() throws Exception {
+ RowSet rs = newInstance();
+ return new Object[][]{
+ {rs, true},
+ {rs, false}
+ };
+ }
+ /*
+ * DataProvider used to specify the type of RowSet to use. We also must
+ * initialize the RowSet
+ */
+ @DataProvider(name = "rowSetType")
+ protected Object[][] rowSetType() throws Exception {
+
+ RowSet rs = newInstance();
+ return new Object[][]{
+ {rs}
+ };
+ }
+
+ /*
+ * Initializes a RowSet containing the COFFEE_HOUSES data
+ */
+ protected <T extends RowSet> T createCoffeeHousesRowSet() throws SQLException {
+ T rs = (T) newInstance();
+ initCoffeeHousesMetaData((CachedRowSet) rs);
+ createCoffeeHouseRows(rs);
+ // Make sure you are not on the insertRow
+ rs.moveToCurrentRow();
+ return rs;
+ }
+
+ /*
+ * Initializes a RowSet containing the COFFEE_HOUSES data
+ */
+ protected <T extends RowSet> T createCoffeesRowSet() throws SQLException {
+ T rs = (T) newInstance();
+ initCoffeesMetaData((CachedRowSet) rs);
+ createCoffeesRows(rs);
+ // Make sure you are not on the insertRow
+ rs.moveToCurrentRow();
+ return rs;
+ }
+
+ /*
+ * Initializes the COFFEE_HOUSES metadata
+ */
+ private void initCoffeeHousesMetaData(CachedRowSet crs) throws SQLException {
+ RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();
+ crs.setType(RowSet.TYPE_SCROLL_INSENSITIVE);
+
+ /*
+ * CREATE TABLE COFFEE_HOUSES(
+ * STORE_ID Integer NOT NULL,
+ * CITY VARCHAR(32),
+ * COFFEE INTEGER NOT NULL,
+ * MERCH INTEGER NOT NULL,
+ * TOTAL INTEGER NOT NULL,
+ * PRIMARY KEY (STORE_ID))
+ */
+ rsmd.setColumnCount(COFFEE_HOUSES_COLUMN_NAMES.length);
+ for(int i = 1; i <= COFFEE_HOUSES_COLUMN_NAMES.length; i++){
+ rsmd.setColumnName(i, COFFEE_HOUSES_COLUMN_NAMES[i-1]);
+ rsmd.setColumnLabel(i, rsmd.getColumnName(i));
+ }
+
+ rsmd.setColumnType(1, Types.INTEGER);
+ rsmd.setColumnType(2, Types.VARCHAR);
+ rsmd.setColumnType(3, Types.INTEGER);
+ rsmd.setColumnType(4, Types.INTEGER);
+ rsmd.setColumnType(5, Types.INTEGER);
+ crs.setMetaData(rsmd);
+ crs.setTableName(COFFEE_HOUSES_TABLE);
+
+ }
+
+ /*
+ * Add rows to COFFEE_HOUSES table
+ */
+ protected void createCoffeeHouseRows(RowSet rs) throws SQLException {
+
+ // insert into COFFEE_HOUSES values(10023, 'Mendocino', 3450, 2005, 5455)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10023);
+ rs.updateString(2, "Mendocino");
+ rs.updateInt(3, 3450);
+ rs.updateInt(4, 2005);
+ rs.updateInt(5, 5455);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(33002, 'Seattle', 4699, 3109, 7808)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 33002);
+ rs.updateString(2, "Seattle");
+ rs.updateInt(3, 4699);
+ rs.updateInt(4, 3109);
+ rs.updateInt(5, 7808);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10040, 'SF', 5386, 2841, 8227)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10040);
+ rs.updateString(2, "SF");
+ rs.updateInt(3, 5386);
+ rs.updateInt(4, 2841);
+ rs.updateInt(5, 8227);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(32001, 'Portland', 3147, 3579, 6726)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 32001);
+ rs.updateString(2, "Portland");
+ rs.updateInt(3, 3147);
+ rs.updateInt(4, 3579);
+ rs.updateInt(5, 6726);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10042, 'SF', 2863, 1874, 4710)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10042);
+ rs.updateString(2, "SF");
+ rs.updateInt(3, 2863);
+ rs.updateInt(4, 1874);
+ rs.updateInt(5, 4710);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10024, 'Sacramento', 1987, 2341, 4328)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10024);
+ rs.updateString(2, "Sacramento");
+ rs.updateInt(3, 1987);
+ rs.updateInt(4, 2341);
+ rs.updateInt(5, 4328);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10039, 'Carmel', 2691, 1121, 3812)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10039);
+ rs.updateString(2, "Carmel");
+ rs.updateInt(3, 2691);
+ rs.updateInt(4, 1121);
+ rs.updateInt(5, 3812);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10041, 'LA', 1533, 1007, 2540)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10041);
+ rs.updateString(2, "LA");
+ rs.updateInt(3, 1533);
+ rs.updateInt(4, 1007);
+ rs.updateInt(5, 2540);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(33005, 'Olympia', 2733, 1550, 1550)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 33005);
+ rs.updateString(2, "Olympia");
+ rs.updateInt(3, 2733);
+ rs.updateInt(4, 1550);
+ rs.updateInt(5, 1550);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(33010, 'Seattle', 3210, 2177, 5387)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 33010);
+ rs.updateString(2, "Seattle");
+ rs.updateInt(3, 3210);
+ rs.updateInt(4, 2177);
+ rs.updateInt(5, 5387);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10035, 'SF', 1922, 1056, 2978)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10035);
+ rs.updateString(2, "SF");
+ rs.updateInt(3, 1922);
+ rs.updateInt(4, 1056);
+ rs.updateInt(5, 2978);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10037, 'LA', 2143, 1876, 4019)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10037);
+ rs.updateString(2, "LA");
+ rs.updateInt(3, 2143);
+ rs.updateInt(4, 1876);
+ rs.updateInt(5, 4019);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(10034, 'San_Jose', 1234, 1032, 2266)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10034);
+ rs.updateString(2, "San Jose");
+ rs.updateInt(3, 1234);
+ rs.updateInt(4, 1032);
+ rs.updateInt(5, 2266);
+ rs.insertRow();
+ // insert into COFFEE_HOUSES values(32004, 'Eugene', 1356, 1112, 2468)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 32004);
+ rs.updateString(2, "Eugene");
+ rs.updateInt(3, 1356);
+ rs.updateInt(4, 1112);
+ rs.updateInt(5, 2468);
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ }
+
+ /*
+ * Initializes the COFFEES metadata
+ */
+ protected void initCoffeesMetaData(CachedRowSet crs) throws SQLException {
+ RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();
+ crs.setType(RowSet.TYPE_SCROLL_INSENSITIVE);
+
+ /*
+ * CREATE TABLE COFFEES (
+ * COF_ID INTEGER NOT NULL,
+ * COF_NAME VARCHAR(32) NOT NULL,
+ * SUP_ID INTEGER NOT NULL,
+ * PRICE NUMBERIC(10,2 NOT NULL,
+ * SALES INTEGER NOT NULL,
+ * TOTAL INTEGER NOT NULL,
+ * PRIMARY KEY (COF_ID),
+ * FOREIGN KEY (SUP_ID) REFERENCES SUPPLIERS (SUP_ID) )
+ */
+ rsmd.setColumnCount(COFFEES_COLUMN_NAMES.length);
+ for(int i = 1; i <= COFFEES_COLUMN_NAMES.length; i++){
+ rsmd.setColumnName(i, COFFEES_COLUMN_NAMES[i-1]);
+ rsmd.setColumnLabel(i, rsmd.getColumnName(i));
+ }
+
+ rsmd.setColumnType(1, Types.INTEGER);
+ rsmd.setColumnType(2, Types.VARCHAR);
+ rsmd.setColumnType(3, Types.INTEGER);
+ rsmd.setColumnType(4, Types.NUMERIC);
+ rsmd.setPrecision(4, 10);
+ rsmd.setScale(4, 2);
+ rsmd.setColumnType(5, Types.INTEGER);
+ rsmd.setColumnType(6, Types.INTEGER);
+ crs.setMetaData(rsmd);
+ crs.setTableName(COFFEES_TABLE);
+
+ }
+
+ /*
+ * Add rows to COFFEES table
+ */
+ protected void createCoffeesRows(RowSet rs) throws SQLException {
+
+ // insert into COFFEES values(1, 'Colombian', 101, 7.99, 0, 0)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 1);
+ rs.updateString(2, "Colombian");
+ rs.updateInt(3, 101);
+ rs.updateBigDecimal(4, BigDecimal.valueOf(7.99));
+ rs.updateInt(5, 0);
+ rs.updateInt(6, 0);
+ rs.insertRow();
+ // insert into COFFEES values(2, 'French_Roast', 49, 8.99, 0, 0)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 2);
+ rs.updateString(2, "French_Roast");
+ rs.updateInt(3, 49);
+ rs.updateBigDecimal(4, BigDecimal.valueOf(8.99));
+ rs.updateInt(5, 0);
+ rs.updateInt(6, 0);
+ rs.insertRow();
+ // insert into COFFEES values(3, 'Espresso', 150, 9.99, 0, 0)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 3);
+ rs.updateString(2, "Espresso");
+ rs.updateInt(3, 150);
+ rs.updateBigDecimal(4, BigDecimal.valueOf(9.99));
+ rs.updateInt(5, 0);
+ rs.updateInt(6, 0);
+ rs.insertRow();
+ // insert into COFFEES values(4, 'Colombian_Decaf', 101, 8.99, 0, 0)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 4);
+ rs.updateString(2, "Colombian_Decaf");
+ rs.updateInt(3, 101);
+ rs.updateBigDecimal(4, BigDecimal.valueOf(8.99));
+ rs.updateInt(5, 0);
+ rs.updateInt(6, 0);
+ rs.insertRow();
+ // insert into COFFEES values(5, 'French_Roast_Decaf', 049, 9.99, 0, 0)
+ rs.moveToInsertRow();
+ rs.updateInt(1, 5);
+ rs.updateString(2, "French_Roast_Decaf");
+ rs.updateInt(3, 49);
+ rs.updateBigDecimal(4, BigDecimal.valueOf(9.99));
+ rs.updateInt(5, 0);
+ rs.updateInt(6, 0);
+ rs.insertRow();
+
+ }
+
+
+ /*
+ * Utility method to return the Primary Keys for a RowSet. The Primary
+ * keys are assumed to be in the first column of the RowSet
+ */
+ protected Object[] getPrimaryKeys(ResultSet rs) throws SQLException {
+ List<? super Object> result = new ArrayList<>();
+ if (rs == null) {
+ return null;
+ }
+ rs.beforeFirst();
+ while (rs.next()) {
+ result.add(rs.getInt(1));
+ }
+ return result.toArray();
+ }
+
+ /*
+ * Utility method to display the RowSet and will return the row count
+ * it found
+ */
+ protected int displayResults(ResultSet rs) throws SQLException {
+ int rows = 0;
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int cols = rsmd.getColumnCount();
+ if (rs != null) {
+ rs.beforeFirst();
+ while (rs.next()) {
+ rows++;
+
+ for (int i = 0; i < cols; i++) {
+ System.out.print(rs.getString(i + 1) + " ");
+ }
+ System.out.println();
+ }
+ }
+
+ return rows;
+ }
+
+
+ // Insert common tests here
+
+ /*
+ * Validate that getCommand() returns null by default
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0000(RowSet rs) {
+ assertNull(rs.getCommand());
+ }
+
+ /*
+ * Validate that getCommand() returns command specified to setCommand
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0001(RowSet rs) throws Exception {
+ rs.setCommand(query);
+ assertTrue(rs.getCommand().equals(query));
+ }
+
+
+ /*
+ * Validate that getCurrency() returns the correct default value
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0002(RowSet rs) throws Exception {
+ assertTrue(rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
+ }
+
+ /*
+ * Validate that getCurrency() returns the correct value
+ * after a call to setConcurrency())
+ */
+ @Test(dataProvider = "rowSetConcurrencyTypes")
+ public void commonRowSetTest0003(RowSet rs, int concurType) throws Exception {
+ rs.setConcurrency(concurType);
+ assertTrue(rs.getConcurrency() == concurType);
+ }
+
+ /*
+ * Validate that getCurrency() throws a SQLException for an invalid value
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0004(RowSet rs) throws Exception {
+ rs.setConcurrency(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ }
+
+ /*
+ * Validate that getDataSourceName() returns null by default
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0005(RowSet rs) throws Exception {
+ assertTrue(rs.getDataSourceName() == null);
+ }
+
+ /*
+ * Validate that getDataSourceName() returns the value specified
+ * by setDataSourceName() and getUrl() returns null
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0006(RowSet rs) throws Exception {
+ rs.setUrl(url);
+ rs.setDataSourceName(dsName);
+ assertTrue(rs.getDataSourceName().equals(dsName));
+ assertNull(rs.getUrl());
+ }
+
+ /*
+ * Validate that setDataSourceName() throws a SQLException for an empty
+ * String specified for the data source name
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0007(RowSet rs) throws Exception {
+ String dsname = "";
+ rs.setDataSourceName(dsname);
+ }
+
+ /*
+ * Validate that getEscapeProcessing() returns false by default
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0008(RowSet rs) throws Exception {
+ assertTrue(rs.getEscapeProcessing());
+ }
+
+ /*
+ * Validate that getEscapeProcessing() returns value set by
+ * setEscapeProcessing()
+ */
+ @Test(dataProvider = "rowSetTrueFalse")
+ public void commonRowSetTest0009(RowSet rs, boolean val) throws Exception {
+ rs.setEscapeProcessing(val);
+ assertTrue(rs.getEscapeProcessing() == val);
+ }
+
+ /*
+ * Validate that getFetchDirection() returns the correct default value
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0010(RowSet rs) throws Exception {
+ assertTrue(rs.getFetchDirection() == ResultSet.FETCH_FORWARD);
+ }
+
+ /*
+ * Validate that getFetchDirection() returns the value set by
+ * setFetchDirection()
+ */
+ @Test(dataProvider = "rowSetFetchDirection")
+ public void commonRowSetTest0011(RowSet rs, int direction) throws Exception {
+ rs.setFetchDirection(direction);
+ assertTrue(rs.getFetchDirection() == direction);
+ }
+
+ /*
+ * Validate that setFetchSize() throws a SQLException for an invalid value
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0013(RowSet rs) throws Exception {
+ rs.setFetchSize(-1);
+ }
+
+ /*
+ * Validate that setFetchSize() throws a SQLException for a
+ * value greater than getMaxRows()
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0014(RowSet rs) throws Exception {
+ rs.setMaxRows(5);
+ rs.setFetchSize(rs.getMaxRows() + 1);
+ }
+
+ /*
+ * Validate that getFetchSize() returns the correct value after
+ * setFetchSize() has been called
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0015(RowSet rs) throws Exception {
+ int maxRows = 150;
+ rs.setFetchSize(0);
+ assertTrue(rs.getFetchSize() == 0);
+ rs.setFetchSize(100);
+ assertTrue(rs.getFetchSize() == 100);
+ rs.setMaxRows(maxRows);
+ rs.setFetchSize(maxRows);
+ assertTrue(rs.getFetchSize() == maxRows);
+ }
+
+ /*
+ * Validate that setMaxFieldSize() throws a SQLException for an invalid value
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0016(RowSet rs) throws Exception {
+ rs.setMaxFieldSize(-1);
+ }
+
+ /*
+ * Validate that getMaxFieldSize() returns the value set by
+ * setMaxFieldSize()
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0017(RowSet rs) throws Exception {
+ rs.setMaxFieldSize(0);
+ assertTrue(rs.getMaxFieldSize() == 0);
+ rs.setMaxFieldSize(100);
+ assertTrue(rs.getMaxFieldSize() == 100);
+ rs.setMaxFieldSize(50);
+ assertTrue(rs.getMaxFieldSize() == 50);
+ }
+
+ /*
+ * Validate that isReadOnly() returns value set by
+ * setReadOnly()
+ */
+ @Test(dataProvider = "rowSetTrueFalse")
+ public void commonRowSetTest0018(RowSet rs, boolean val) throws Exception {
+ rs.setReadOnly(val);
+ assertTrue(rs.isReadOnly() == val);
+ }
+
+ /*
+ * Validate that getTransactionIsolation() returns value set by
+ * setTransactionIsolation()
+ */
+ @Test(dataProvider = "rowSetIsolationTypes")
+ public void commonRowSetTest0019(RowSet rs, int val) throws Exception {
+ rs.setTransactionIsolation(val);
+ assertTrue(rs.getTransactionIsolation() == val);
+ }
+
+ /*
+ * Validate that getType() returns value set by setType()
+ */
+ @Test(dataProvider = "rowSetScrollTypes")
+ public void commonRowSetTest0020(RowSet rs, int val) throws Exception {
+ rs.setType(val);
+ assertTrue(rs.getType() == val);
+ }
+
+ /*
+ * Validate that getEscapeProcessing() returns value set by
+ * setEscapeProcessing()
+ */
+ @Test(dataProvider = "rowSetTrueFalse")
+ public void commonRowSetTest0021(BaseRowSet rs, boolean val) throws Exception {
+ rs.setShowDeleted(val);
+ assertTrue(rs.getShowDeleted() == val);
+ }
+
+ /*
+ * Validate that getTypeMap() returns same value set by
+ * setTypeMap()
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0022(RowSet rs) throws Exception {
+ Map<String, Class<?>> map = new HashMap<>();
+ map.put("SUPERHERO", Class.forName("util.SuperHero"));
+ rs.setTypeMap(map);
+ assertTrue(rs.getTypeMap().equals(map));
+ }
+
+ /*
+ * Validate that getUsername() returns same value set by
+ * setUsername()
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0023(RowSet rs) throws Exception {
+ rs.setUsername(user);
+ assertTrue(rs.getUsername().equals(user));
+ }
+
+ /*
+ * Validate that getPassword() returns same password set by
+ * setPassword()
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0024(RowSet rs) throws Exception {
+ rs.setPassword(password);
+ assertTrue(rs.getPassword().equals(password));
+ }
+
+ /*
+ * Validate that getQueryTimeout() returns same value set by
+ * setQueryTimeout() and that 0 is a valid timeout value
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0025(RowSet rs) throws Exception {
+ int timeout = 0;
+ rs.setQueryTimeout(timeout);
+ assertTrue(rs.getQueryTimeout() == timeout);
+ }
+
+ /*
+ * Validate that getQueryTimeout() returns same value set by
+ * setQueryTimeout() and that 0 is a valid timeout value
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0026(RowSet rs) throws Exception {
+ int timeout = 10000;
+ rs.setQueryTimeout(timeout);
+ assertTrue(rs.getQueryTimeout() == timeout);
+ }
+
+ /*
+ * Validate that setQueryTimeout() throws a SQLException for a timeout
+ * value < 0
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonRowSetTest0027(RowSet rs) throws Exception {
+ rs.setQueryTimeout(-1);
+ }
+
+
+ /*
+ * Validate addRowSetListener does not throw an Exception when null is
+ * passed as the parameter
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0028(RowSet rs) throws Exception {
+ rs.addRowSetListener(null);
+ }
+
+ /*
+ * Validate removeRowSetListener does not throw an Exception when null is
+ * passed as the parameter
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0029(RowSet rs) throws Exception {
+ rs.removeRowSetListener(null);
+ }
+
+ /*
+ * Set two parameters and then validate clearParameters() will clear them
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0030(BaseRowSet rs) throws Exception {
+ rs.setInt(1, 1);
+ rs.setString(2, query);
+ assertTrue(rs.getParams().length == 2);
+ rs.clearParameters();
+ assertTrue(rs.getParams().length == 0);
+ }
+
+ /*
+ * Validate that getURL() returns same value set by
+ * setURL()
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonRowSetTest0031(RowSet rs) throws Exception {
+ rs.setUrl(url);
+ assertTrue(rs.getUrl().equals(url));
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0100(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setAsciiStream(1, is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0101(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setAsciiStream("one", is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0102(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setAsciiStream("one", is, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0103(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBinaryStream(1, is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0104(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBinaryStream("one", is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0105(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBinaryStream("one", is, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0106(RowSet rs) throws Exception {
+ rs.setBigDecimal("one", BigDecimal.ONE);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0107(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBlob(1, is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0108(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBlob("one", is);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0109(RowSet rs) throws Exception {
+ InputStream is = null;
+ rs.setBlob("one", is, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0110(RowSet rs) throws Exception {
+ rs.setBlob("one", new StubBlob());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0111(RowSet rs) throws Exception {
+ rs.setBoolean("one", true);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0112(RowSet rs) throws Exception {
+ byte b = 1;
+ rs.setByte("one", b);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0113(RowSet rs) throws Exception {
+ byte b = 1;
+ rs.setBytes("one", new byte[10]);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0114(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setCharacterStream("one", rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0115(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setCharacterStream("one", rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0116(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setCharacterStream(1, rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0117(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setClob(1, rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0118(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setClob("one", rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0119(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setClob("one", rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0120(RowSet rs) throws Exception {
+ rs.setClob("one", new StubClob());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0121(RowSet rs) throws Exception {
+ rs.setDate("one", Date.valueOf(LocalDate.now()));
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0122(RowSet rs) throws Exception {
+ rs.setDate("one", Date.valueOf(LocalDate.now()),
+ Calendar.getInstance());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0123(RowSet rs) throws Exception {
+ rs.setTime("one", Time.valueOf(LocalTime.now()));
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0124(RowSet rs) throws Exception {
+ rs.setTime("one", Time.valueOf(LocalTime.now()),
+ Calendar.getInstance());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0125(RowSet rs) throws Exception {
+ rs.setTimestamp("one", Timestamp.valueOf(LocalDateTime.now()));
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0126(RowSet rs) throws Exception {
+ rs.setTimestamp("one", Timestamp.valueOf(LocalDateTime.now()),
+ Calendar.getInstance());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0127(RowSet rs) throws Exception {
+ rs.setDouble("one", 2.0d);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0128(RowSet rs) throws Exception {
+ rs.setFloat("one", 2.0f);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0129(RowSet rs) throws Exception {
+ rs.setInt("one", 21);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0130(RowSet rs) throws Exception {
+ rs.setLong("one", 21l);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0131(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNCharacterStream("one", rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0132(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNCharacterStream("one", rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0133(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNCharacterStream(1, rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0134(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNCharacterStream(1, rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0135(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setClob("one", rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0136(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setClob("one", rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0137(RowSet rs) throws Exception {
+ rs.setNClob("one", new StubNClob());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0138(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNClob(1, rdr);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0139(RowSet rs) throws Exception {
+ Reader rdr = null;
+ rs.setNClob(1, rdr, query.length());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0140(RowSet rs) throws Exception {
+ rs.setNClob(1, new StubNClob());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0141(RowSet rs) throws Exception {
+ rs.setNString(1, query);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0142(RowSet rs) throws Exception {
+ rs.setNull("one", Types.INTEGER);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0143(RowSet rs) throws Exception {
+ rs.setNull("one", Types.INTEGER, "my.type");
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0144(RowSet rs) throws Exception {
+ rs.setObject("one", query, Types.VARCHAR);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0145(RowSet rs) throws Exception {
+ rs.setObject("one", query, Types.VARCHAR, 0);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0146(RowSet rs) throws Exception {
+ rs.setObject("one", query);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0147(RowSet rs) throws Exception {
+ RowId aRowid = null;
+ rs.setRowId("one", aRowid);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0148(RowSet rs) throws Exception {
+ rs.setSQLXML("one", new StubSQLXML());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0149(RowSet rs) throws Exception {
+ rs.setSQLXML(1, new StubSQLXML());
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0150(RowSet rs) throws Exception {
+ rs.setNString(1, query);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0151(RowSet rs) throws Exception {
+ rs.setNString("one", query);
+ }
+
+ /*
+ * This method is currently not implemented in BaseRowSet and will
+ * throw a SQLFeatureNotSupportedException
+ */
+ @Test(dataProvider = "rowSetType",
+ expectedExceptions = SQLFeatureNotSupportedException.class)
+ public void commonRowSetTest0152(RowSet rs) throws Exception {
+ short val = 21;
+ rs.setShort("one", val);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/cachedrowset/CachedRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.cachedrowset;
+
+import java.sql.SQLException;
+import javax.sql.rowset.CachedRowSet;
+
+public class CachedRowSetTests extends CommonCachedRowSetTests {
+
+ @Override
+ protected CachedRowSet newInstance() throws SQLException {
+ return rsf.createCachedRowSet();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/cachedrowset/CommonCachedRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,1612 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.cachedrowset;
+
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Date;
+import java.sql.JDBCType;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Collection;
+import javax.sql.RowSet;
+import javax.sql.rowset.CachedRowSet;
+import javax.sql.rowset.RowSetMetaDataImpl;
+import javax.sql.rowset.serial.SerialRef;
+import javax.sql.rowset.spi.SyncFactory;
+import javax.sql.rowset.spi.SyncProvider;
+import javax.sql.rowset.spi.SyncProviderException;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import test.rowset.CommonRowSetTests;
+import util.StubArray;
+import util.StubRef;
+import util.StubSyncProvider;
+import util.TestRowSetListener;
+
+public abstract class CommonCachedRowSetTests extends CommonRowSetTests {
+
+ /*
+ * DATATYPES Table column names
+ */
+ private final String[] DATATYPES_COLUMN_NAMES = {"AINTEGER", "ACHAR",
+ "AVARCHAR", "ALONG", "ABOOLEAN", "ASHORT", "ADOUBLE", "ABIGDECIMAL",
+ "AREAL", "ABYTE", "ADATE", "ATIME", "ATIMESTAMP", "ABYTES", "ARRAY",
+ "AREF", "AFLOAT"};
+
+ /*
+ * Initializes a RowSet containing the DATAYPES data
+ */
+ protected <T extends RowSet> T createDataTypesRowSet() throws SQLException {
+ T rs = (T) newInstance();
+ initDataTypesMetaData((CachedRowSet) rs);
+ createDataTypesRows(rs);
+ // Make sure you are not on the insertRow
+ rs.moveToCurrentRow();
+ return rs;
+ }
+
+ //DataProviders to use for common tests
+
+ /*
+ * DataProvider that uses a RowSet with the COFFEE_HOUSES Table
+ */
+ @DataProvider(name = "rowsetUsingCoffeeHouses")
+ protected Object[][] rowsetUsingCoffeeHouses() throws Exception {
+ RowSet rs = createCoffeeHousesRowSet();
+ return new Object[][]{
+ {rs}
+ };
+ }
+
+ /*
+ * DataProvider that uses a RowSet with the COFFEES Table
+ */
+ @DataProvider(name = "rowsetUsingCoffees")
+ protected Object[][] rowsetUsingCoffees() throws Exception {
+ RowSet rs = createCoffeesRowSet();
+ return new Object[][]{
+ {rs}
+ };
+ }
+
+ /*
+ * DataProvider that uses a RowSet with the DATAYPES Table and
+ * used to validate the various supported data types
+ */
+ @DataProvider(name = "rowsetUsingDataTypes")
+ protected Object[][] rowsetUsingDataTypes() throws Exception {
+
+ CachedRowSet rs = createDataTypesRowSet();
+ return new Object[][]{
+ {rs, JDBCType.INTEGER},
+ {rs, JDBCType.CHAR},
+ {rs, JDBCType.VARCHAR},
+ {rs, JDBCType.BIGINT},
+ {rs, JDBCType.BOOLEAN},
+ {rs, JDBCType.SMALLINT},
+ {rs, JDBCType.DOUBLE},
+ {rs, JDBCType.DECIMAL},
+ {rs, JDBCType.REAL},
+ {rs, JDBCType.TINYINT},
+ {rs, JDBCType.DATE},
+ {rs, JDBCType.TIME},
+ {rs, JDBCType.TIMESTAMP},
+ {rs, JDBCType.VARBINARY},
+ {rs, JDBCType.ARRAY},
+ {rs, JDBCType.REF},
+ {rs, JDBCType.FLOAT}
+ };
+ }
+
+ /*
+ * Initializes the DATAYPES table metadata
+ */
+ protected void initDataTypesMetaData(CachedRowSet crs) throws SQLException {
+ RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();
+ crs.setType(RowSet.TYPE_SCROLL_INSENSITIVE);
+
+ rsmd.setColumnCount(DATATYPES_COLUMN_NAMES.length);
+
+ for (int i = 1; i <= DATATYPES_COLUMN_NAMES.length; i++) {
+ rsmd.setColumnName(i, DATATYPES_COLUMN_NAMES[i - 1]);
+ rsmd.setColumnLabel(i, rsmd.getColumnName(i));
+ }
+
+ rsmd.setColumnType(1, Types.INTEGER);
+ rsmd.setColumnType(2, Types.CHAR);
+ rsmd.setColumnType(3, Types.VARCHAR);
+ rsmd.setColumnType(4, Types.BIGINT);
+ rsmd.setColumnType(5, Types.BOOLEAN);
+ rsmd.setColumnType(6, Types.SMALLINT);
+ rsmd.setColumnType(7, Types.DOUBLE);
+ rsmd.setColumnType(8, Types.DECIMAL);
+ rsmd.setColumnType(9, Types.REAL);
+ rsmd.setColumnType(10, Types.TINYINT);
+ rsmd.setColumnType(11, Types.DATE);
+ rsmd.setColumnType(12, Types.TIME);
+ rsmd.setColumnType(13, Types.TIMESTAMP);
+ rsmd.setColumnType(14, Types.VARBINARY);
+ rsmd.setColumnType(15, Types.ARRAY);
+ rsmd.setColumnType(16, Types.REF);
+ rsmd.setColumnType(17, Types.FLOAT);
+ crs.setMetaData(rsmd);
+
+ }
+
+ /*
+ * Add rows to DATAYPES table
+ */
+ protected void createDataTypesRows(RowSet crs) throws SQLException {
+
+ Integer aInteger = 100;
+ String aChar = "Oswald Cobblepot";
+ Long aLong = Long.MAX_VALUE;
+ Short aShort = Short.MAX_VALUE;
+ Double aDouble = Double.MAX_VALUE;
+ BigDecimal aBigDecimal = BigDecimal.ONE;
+ Boolean aBoolean = false;
+ Float aFloat = Float.MAX_VALUE;
+ Byte aByte = Byte.MAX_VALUE;
+ Date aDate = Date.valueOf(LocalDate.now());
+ Time aTime = Time.valueOf(LocalTime.now());
+ Timestamp aTimeStamp = Timestamp.valueOf(LocalDateTime.now());
+ Array aArray = new StubArray("INTEGER", new Object[1]);
+ Ref aRef = new SerialRef(new StubRef("INTEGER", query));
+ byte[] bytes = new byte[10];
+ crs.moveToInsertRow();
+ crs.updateInt(1, aInteger);
+ crs.updateString(2, aChar);
+ crs.updateString(3, aChar);
+ crs.updateLong(4, aLong);
+ crs.updateBoolean(5, aBoolean);
+ crs.updateShort(6, aShort);
+ crs.updateDouble(7, aDouble);
+ crs.updateBigDecimal(8, aBigDecimal);
+ crs.updateFloat(9, aFloat);
+ crs.updateByte(10, aByte);
+ crs.updateDate(11, aDate);
+ crs.updateTime(12, aTime);
+ crs.updateTimestamp(13, aTimeStamp);
+ crs.updateBytes(14, bytes);
+ crs.updateArray(15, aArray);
+ crs.updateRef(16, aRef);
+ crs.updateDouble(17, aDouble);
+ crs.insertRow();
+ crs.moveToCurrentRow();
+
+ }
+
+ /*
+ * Dermine if a Row exists in a ResultSet by its primary key
+ * If the parameter deleteRow is true, delete the row and validate
+ * the RowSet indicates it is deleted
+ */
+ protected boolean findRowByPrimaryKey(RowSet rs, int id, int idPos,
+ boolean deleteRow) throws Exception {
+ boolean foundRow = false;
+ rs.beforeFirst();
+ while (rs.next()) {
+ if (rs.getInt(idPos) == id) {
+ foundRow = true;
+ if (deleteRow) {
+ rs.deleteRow();
+ // validate row is marked as deleted
+ assertTrue(rs.rowDeleted());
+ }
+ break;
+ }
+ }
+ return foundRow;
+ }
+
+ /*
+ * Wrapper method to find if a row exists within a RowSet by its primary key
+ */
+ protected boolean findRowByPrimaryKey(RowSet rs, int id, int idPos) throws Exception {
+ return findRowByPrimaryKey(rs, id, idPos, false);
+ }
+
+ /*
+ * Wrapper method to find if a row exists within a RowSet by its primary key
+ * and delete it
+ */
+ protected boolean deleteRowByPrimaryKey(RowSet rs, int id, int idPos) throws Exception {
+ return findRowByPrimaryKey(rs, id, idPos, true);
+ }
+
+ /*
+ * Utility method that compares two ResultSetMetaDataImpls for containing
+ * the same values
+ */
+ private void compareMetaData(ResultSetMetaData rsmd,
+ ResultSetMetaData rsmd1) throws SQLException {
+
+ assertEquals(rsmd1.getColumnCount(), rsmd.getColumnCount());
+ int cols = rsmd.getColumnCount();
+ for (int i = 1; i <= cols; i++) {
+ assertTrue(rsmd1.getCatalogName(i).equals(rsmd.getCatalogName(i)));
+ assertTrue(rsmd1.getColumnClassName(i).equals(rsmd.getColumnClassName(i)));
+ assertTrue(rsmd1.getColumnDisplaySize(i) == rsmd.getColumnDisplaySize(i));
+ assertTrue(rsmd1.getColumnLabel(i).equals(rsmd.getColumnLabel(i)));
+ assertTrue(rsmd1.getColumnName(i).equals(rsmd.getColumnName(i)));
+ assertTrue(rsmd1.getColumnType(i) == rsmd.getColumnType(i));
+ assertTrue(rsmd1.getPrecision(i) == rsmd.getPrecision(i));
+ assertTrue(rsmd1.getScale(i) == rsmd.getScale(i));
+ assertTrue(rsmd1.getSchemaName(i).equals(rsmd.getSchemaName(i)));
+ assertTrue(rsmd1.getTableName(i).equals(rsmd.getTableName(i)));
+ assertTrue(rsmd1.isAutoIncrement(i) == rsmd.isAutoIncrement(i));
+ assertTrue(rsmd1.isCaseSensitive(i) == rsmd.isCaseSensitive(i));
+ assertTrue(rsmd1.isCurrency(i) == rsmd.isCurrency(i));
+ assertTrue(rsmd1.isDefinitelyWritable(i) == rsmd.isDefinitelyWritable(i));
+ assertTrue(rsmd1.isNullable(i) == rsmd.isNullable(i));
+ assertTrue(rsmd1.isReadOnly(i) == rsmd.isReadOnly(i));
+ assertTrue(rsmd1.isSearchable(i) == rsmd.isSearchable(i));
+ assertTrue(rsmd1.isSigned(i) == rsmd.isSigned(i));
+ assertTrue(rsmd1.isWritable(i) == rsmd.isWritable(i));
+
+ }
+ }
+
+ /*
+ * Utility method to compare two rowsets
+ */
+ private void compareRowSets(CachedRowSet crs, CachedRowSet crs1) throws Exception {
+
+ int rows = crs.size();
+ assertTrue(rows == crs1.size());
+
+ ResultSetMetaData rsmd = crs.getMetaData();
+
+ compareMetaData(rsmd, crs1.getMetaData());
+ int cols = rsmd.getColumnCount();
+
+ for (int row = 1; row <= rows; row++) {
+ crs.absolute((row));
+ crs1.absolute(row);
+ for (int col = 1; col <= cols; col++) {
+ compareColumnValue(JDBCType.valueOf(rsmd.getColumnType(col)),
+ crs, crs1, col);
+ }
+ }
+
+ }
+
+ /*
+ * Utility method to compare two columns
+ */
+ private void compareColumnValue(JDBCType type, ResultSet rs, ResultSet rs1,
+ int col) throws SQLException {
+
+ switch (type) {
+ case INTEGER:
+ assertTrue(rs.getInt(col) == rs1.getInt(col));
+ break;
+ case CHAR:
+ case VARCHAR:
+ assertTrue(rs.getString(col).equals(rs1.getString(col)));
+ break;
+ case BIGINT:
+ assertTrue(rs.getLong(col) == rs1.getLong(col));
+ break;
+ case BOOLEAN:
+ assertTrue(rs.getBoolean(col) == rs1.getBoolean(col));
+ break;
+ case SMALLINT:
+ assertTrue(rs.getShort(col) == rs1.getShort(col));
+ break;
+ case DOUBLE:
+ case FLOAT:
+ assertTrue(rs.getDouble(col) == rs1.getDouble(col));
+ break;
+ case DECIMAL:
+ assertTrue(rs.getBigDecimal(col).equals(rs1.getBigDecimal(col)));
+ break;
+ case REAL:
+ assertTrue(rs.getFloat(col) == rs1.getFloat(col));
+ break;
+ case TINYINT:
+ assertTrue(rs.getByte(col) == rs1.getByte(col));
+ break;
+ case DATE:
+ assertTrue(rs.getDate(col).equals(rs1.getDate(col)));
+ break;
+ case TIME:
+ assertTrue(rs.getTime(col).equals(rs1.getTime(col)));
+ break;
+ case TIMESTAMP:
+ assertTrue(rs.getTimestamp(col).equals(rs1.getTimestamp(col)));
+ break;
+ }
+ }
+
+ /*
+ * Validate SyncProviderException is thrown when acceptChanges is called
+ * but there is not a way to make a connection to the datasource
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SyncProviderException.class)
+ public void commonCachedRowSetTest0000(CachedRowSet rs) throws Exception {
+ rs.acceptChanges();
+ rs.close();
+ }
+
+ /*
+ * Validate SyncProviderException is thrown when acceptChanges is called
+ * when null is passed as the datasource
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SyncProviderException.class)
+ public void commonCachedRowSetTest0001(CachedRowSet rs) throws Exception {
+ rs.acceptChanges(null);
+ rs.close();
+ }
+
+ /*
+ * Validate that that RIOPtimsticProvider is the default SyncProvider
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0002(CachedRowSet rs) throws SQLException {
+ SyncProvider sp = rs.getSyncProvider();
+ assertTrue(sp instanceof com.sun.rowset.providers.RIOptimisticProvider);
+ rs.close();
+ }
+
+ /*
+ * Validate that you can specify a SyncProvider
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0003(CachedRowSet rs) throws SQLException {
+
+ // Register a provider and make sure it is avaiable
+ SyncFactory.registerProvider(stubProvider);
+ rs.setSyncProvider(stubProvider);
+ SyncProvider sp = rs.getSyncProvider();
+ assertTrue(sp instanceof StubSyncProvider);
+ SyncFactory.unregisterProvider(stubProvider);
+ rs.close();
+ }
+
+ /*
+ * Create a RowSetListener and validate that notifyRowSetChanged is called
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0004(CachedRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.release();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
+ rs.close();
+ }
+
+ /*
+ * Create a RowSetListener and validate that notifyRowSetChanged is called
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0005(CachedRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.restoreOriginal();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
+ rs.close();
+ }
+
+ /*
+ * Create a RowSetListener and validate that notifyRowChanged is called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0006(RowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.moveToInsertRow();
+ rs.updateInt(1, 10024);
+ rs.updateString(2, "Sacramento");
+ rs.updateInt(3, 1987);
+ rs.updateInt(4, 2341);
+ rs.updateInt(5, 4328);
+ rs.insertRow();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
+ rs.close();
+ }
+
+ /*
+ * Create a multiple RowSetListeners and validate that notifyRowChanged,
+ * notifiyMoved is called on all listners
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0007(RowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ TestRowSetListener rsl2 = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.addRowSetListener(rsl2);
+ rs.first();
+ rs.updateInt(1, 1961);
+ rs.updateString(2, "Pittsburgh");
+ rs.updateInt(3, 1987);
+ rs.updateInt(4, 2341);
+ rs.updateInt(5, 6689);
+ rs.updateRow();
+ assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED
+ | TestRowSetListener.ROW_CHANGED));
+ assertTrue(rsl2.isNotified(TestRowSetListener.CURSOR_MOVED
+ | TestRowSetListener.ROW_CHANGED));
+ rs.close();
+ }
+
+ /*
+ * Create a RowSetListener and validate that notifyRowChanged and
+ * notifyCursorMoved are called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0008(CachedRowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+
+ rs.first();
+ assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
+ rs.deleteRow();
+ assertTrue(
+ rsl.isNotified(TestRowSetListener.ROW_CHANGED | TestRowSetListener.CURSOR_MOVED));
+ rsl.resetFlag();
+ rs.setShowDeleted(true);
+ rs.undoDelete();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
+ rs.close();
+ }
+
+ /*
+ * Create a RowSetListener and validate that notifyCursorMoved is called
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0009(RowSet rs) throws Exception {
+ TestRowSetListener rsl = new TestRowSetListener();
+ rs.addRowSetListener(rsl);
+ rs.beforeFirst();
+ assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
+ rs.close();
+ }
+
+ /*
+ * Validate that getTableName() returns the proper values
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0010(CachedRowSet rs) throws Exception {
+ assertNull(rs.getTableName());
+ rs.setTableName(COFFEE_HOUSES_TABLE);
+ assertTrue(rs.getTableName().equals(COFFEE_HOUSES_TABLE));
+ rs.close();
+ }
+
+ /*
+ * Validate that getKeyColumns() returns the proper values
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0011(CachedRowSet rs) throws Exception {
+ int[] pkeys = {1, 3};
+ assertNull(rs.getKeyColumns());
+ rs.setKeyColumns(pkeys);
+ assertEquals(rs.getKeyColumns(), pkeys);
+ rs.close();
+ }
+
+ /*
+ * Validate that setMatchColumn throws a SQLException if the column
+ * index specified is out of range
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0012(CachedRowSet rs) throws Exception {
+ rs.setMatchColumn(-1);
+ rs.close();
+ }
+
+ /*
+ * Validate that setMatchColumn throws a SQLException if the column
+ * index specified is out of range
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0013(CachedRowSet rs) throws Exception {
+ int[] cols = {1, -1};
+ rs.setMatchColumn(cols);
+ rs.close();
+ }
+
+ /*
+ * Validate that setMatchColumn throws a SQLException if the column
+ * index specified is out of range
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0014(CachedRowSet rs) throws Exception {
+ rs.setMatchColumn((String) null);
+ rs.close();
+ }
+
+ /*
+ * Validate that setMatchColumn throws a SQLException if the column
+ * index specified is out of range
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0015(CachedRowSet rs) throws Exception {
+ String[] cols = {"ID", null};
+ rs.setMatchColumn(cols);
+ }
+
+ /*
+ * Validate that getMatchColumn returns the same value specified by
+ * setMatchColumn
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
+ public void commonCachedRowSetTest0016(CachedRowSet rs) throws Exception {
+ int[] expectedCols = {1};
+ String[] expectedColNames = {"ID"};
+ rs.setMatchColumn(1);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ String[] actualColNames = rs.getMatchColumnNames();
+ for (int i = 0; i < actualCols.length; i++) {
+ System.out.println(actualCols[i]);
+ }
+ assertEquals(actualCols, expectedCols);
+ assertEquals(actualColNames, expectedColNames);
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumn returns the same value specified by
+ * setMatchColumn
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
+ public void commonCachedRowSetTest0017(CachedRowSet rs) throws Exception {
+ int[] expectedCols = {1};
+ String[] expectedColNames = {"ID"};
+ rs.setMatchColumn(expectedColNames[0]);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ String[] actualColNames = rs.getMatchColumnNames();
+ assertEquals(actualCols, expectedCols);
+ assertEquals(actualColNames, expectedColNames);
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumn returns the same valid value specified by
+ * setMatchColumn
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
+ public void commonCachedRowSetTest0018(CachedRowSet rs) throws Exception {
+ int[] expectedCols = {1, 3};
+ String[] expectedColNames = {"COF_ID", "SUP_ID"};
+ rs.setMatchColumn(expectedCols);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ String[] actualColNames = rs.getMatchColumnNames();
+ assertEquals(actualCols, expectedCols);
+ assertEquals(actualColNames, expectedColNames);
+ assertEquals(actualCols, expectedCols);
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumn returns the same valid value specified by
+ * setMatchColumn
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
+ public void commonCachedRowSetTest0019(CachedRowSet rs) throws Exception {
+ int[] expectedCols = {1, 3};
+ String[] expectedColNames = {"COF_ID", "SUP_ID"};
+ rs.setMatchColumn(expectedColNames);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ String[] actualColNames = rs.getMatchColumnNames();
+ assertEquals(actualCols, expectedCols);
+ assertEquals(actualColNames, expectedColNames);
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumnIndexes throws a SQLException if
+ * unsetMatchColumn has been called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0020(CachedRowSet rs) throws Exception {
+ rs.setMatchColumn(1);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ assertTrue(actualCols != null);
+ rs.unsetMatchColumn(1);
+ actualCols = rs.getMatchColumnIndexes();
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumnNames throws a SQLException if
+ * unsetMatchColumn has been called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0021(CachedRowSet rs) throws Exception {
+ String matchColumn = "ID";
+ rs.setMatchColumn(matchColumn);
+ String[] actualColNames = rs.getMatchColumnNames();
+ assertTrue(actualColNames != null);
+ rs.unsetMatchColumn(matchColumn);
+ actualColNames = rs.getMatchColumnNames();
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumnIndexes throws a SQLException if
+ * unsetMatchColumn has been called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0022(CachedRowSet rs) throws Exception {
+ int[] expectedCols = {1, 3};
+ rs.setMatchColumn(expectedCols);
+ int[] actualCols = rs.getMatchColumnIndexes();
+ assertTrue(actualCols != null);
+ rs.unsetMatchColumn(expectedCols);
+ actualCols = rs.getMatchColumnIndexes();
+ rs.close();
+ }
+
+ /*
+ * Validate that getMatchColumnNames throws a SQLException if
+ * unsetMatchColumn has been called
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0023(CachedRowSet rs) throws Exception {
+ String[] expectedColNames = {"COF_ID", "SUP_ID"};
+ rs.setMatchColumn(expectedColNames);
+ String[] actualColNames = rs.getMatchColumnNames();
+ assertTrue(actualColNames != null);
+ rs.unsetMatchColumn(expectedColNames);
+ actualColNames = rs.getMatchColumnNames();
+ rs.close();
+ }
+
+ /*
+ * Validate size() returns the correct number of rows
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0024(CachedRowSet rs) throws Exception {
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ rs.close();
+ }
+
+ /*
+ * Validate that the correct rows are returned comparing the primary
+ * keys
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0025(RowSet rs) throws SQLException {
+ assertEquals(getPrimaryKeys(rs), COFFEE_HOUSES_PRIMARY_KEYS);
+ rs.close();
+ }
+
+ /*
+ * Delete a row within the RowSet using its primary key
+ * Validate the visibility of the row depending on the value of
+ * setShowdelete
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0026(CachedRowSet rs) throws Exception {
+ Object[] afterDelete = {
+ 10023, 33002, 10040, 32001, 10042, 10024, 10039, 10041,
+ 33005, 33010, 10037, 10034, 32004
+ };
+ int rowToDelete = 10035;
+ // All rows should be found
+ assertEquals(getPrimaryKeys(rs), COFFEE_HOUSES_PRIMARY_KEYS);
+ // Delete the row
+ assertTrue(deleteRowByPrimaryKey(rs, rowToDelete, 1));
+ // With setShowDeleted(false) which is the default,
+ // the deleted row should not be visible
+ assertFalse(findRowByPrimaryKey(rs, rowToDelete, 1));
+ assertEquals(getPrimaryKeys(rs), afterDelete);
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ // With setShowDeleted(true), the deleted row should be visible
+ rs.setShowDeleted(true);
+ assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
+ rs.close();
+ }
+
+ /*
+ * Validate that there is no page size by default
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0027(CachedRowSet rs) throws Exception {
+ assertTrue(rs.getPageSize() == 0);
+ rs.close();
+ }
+
+ /*
+ * Validate the value you set via setPageSize is returned by getPageSize
+ * then reset to having no limit
+ */
+ @Test(dataProvider = "rowSetType")
+ public void commonCachedRowSetTest0028(CachedRowSet rs) throws Exception {
+ int rows = 100;
+ rs.setPageSize(rows);
+ assertTrue(rows == rs.getPageSize());
+ rs.setPageSize(0);
+ assertTrue(rs.getPageSize() == 0);
+ rs.close();
+ }
+
+ /*
+ * Validate SQLException is thrown when an invalid value is specified
+ * for setPageSize
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0029(CachedRowSet rs) throws Exception {
+ rs.setPageSize(-1);
+ rs.close();
+ }
+
+ /*
+ * Validate SQLException is thrown when nextPage is called without a
+ * call to populate or execute
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0030(CachedRowSet rs) throws Exception {
+ rs.nextPage();
+ rs.close();
+ }
+
+ /*
+ * Validate SQLException is thrown when previousPage is called without a
+ * call to populate or execute
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0031(CachedRowSet rs) throws Exception {
+ rs.previousPage();
+ rs.close();
+ }
+
+
+ /*
+ * Validate SQLException is thrown when execute is called
+ * but there is not a way to make a connection to the datasource
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0032(CachedRowSet rs) throws Exception {
+ rs.execute(null);
+ rs.close();
+ }
+
+ /*
+ * Validate SQLException is thrown when execute is called
+ * but there is not a way to make a connection to the datasource
+ */
+ @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0033(CachedRowSet rs) throws Exception {
+ rs.execute();
+ rs.close();
+ }
+
+ /*
+ * Validate that toCollection(<column>) returns the proper values
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0034(CachedRowSet rs) throws Exception {
+ Object[] cities = {"Mendocino", "Seattle", "SF", "Portland", "SF",
+ "Sacramento", "Carmel", "LA", "Olympia", "Seattle", "SF",
+ "LA", "San Jose", "Eugene"};
+ rs.beforeFirst();
+ assertEquals(rs.toCollection(2).toArray(), cities);
+ assertEquals(rs.toCollection("CITY").toArray(), cities);
+ rs.close();
+ }
+
+ /*
+ * Validate that toCollection() returns the proper values
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0035(CachedRowSet rs) throws Exception {
+ Collection<?> col = rs.toCollection();
+ assertTrue(rs.size() == col.size());
+ assertTrue(rs.toCollection().containsAll(col)
+ && col.containsAll(rs.toCollection()));
+ try ( // Validate that False is returned when compared to a different RowSet;
+ CachedRowSet crs1 = createCoffeesRowSet()) {
+ assertFalse(crs1.toCollection().containsAll(col)
+ && col.containsAll(crs1.toCollection()));
+ }
+ rs.close();
+
+ }
+
+ /*
+ * Validate that createCopy() returns the proper values
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0036(CachedRowSet rs) throws Exception {
+ try (CachedRowSet crs1 = rs.createCopy()) {
+ compareRowSets(rs, crs1);
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that createCopySchema() returns the proper values
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0037(CachedRowSet rs) throws Exception {
+ try (CachedRowSet crs1 = rs.createCopySchema()) {
+ assertTrue(crs1.size() == 0);
+ compareMetaData(crs1.getMetaData(), rs.getMetaData());
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that createCopyNoConstraints() returns the proper values
+ * and getMatchColumnIndexes should throw a SQLException. This test
+ * specifies setMatchColumn(int)
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0038(CachedRowSet rs) throws Exception {
+ rs.setMatchColumn(1);
+ try (CachedRowSet crs1 = rs.createCopyNoConstraints()) {
+ assertTrue(crs1.size() == COFFEE_HOUSES_ROWS);
+ compareRowSets(rs, crs1);
+ boolean recievedSQE = false;
+ try {
+ int[] indexes = crs1.getMatchColumnIndexes();
+ } catch (SQLException e) {
+ recievedSQE = true;
+ }
+ assertTrue(recievedSQE);
+ recievedSQE = false;
+ try {
+ String[] colNames = crs1.getMatchColumnNames();
+ } catch (SQLException e) {
+ recievedSQE = true;
+ }
+ assertTrue(recievedSQE);
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that createCopyNoConstraints() returns the proper values
+ * and getMatchColumnIndexes should throw a SQLException. This test
+ * specifies setMatchColumn(String)
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0039(CachedRowSet rs) throws Exception {
+ rs.setMatchColumn("ID");
+ try (CachedRowSet crs1 = rs.createCopyNoConstraints()) {
+ assertTrue(crs1.size() == COFFEE_HOUSES_ROWS);
+ compareRowSets(rs, crs1);
+ boolean recievedSQE = false;
+ try {
+ int[] indexes = crs1.getMatchColumnIndexes();
+ } catch (SQLException e) {
+ recievedSQE = true;
+ }
+ assertTrue(recievedSQE);
+ recievedSQE = false;
+ try {
+ String[] colNames = crs1.getMatchColumnNames();
+ } catch (SQLException e) {
+ recievedSQE = true;
+ }
+ assertTrue(recievedSQE);
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that columnUpdated works with the various datatypes specifying
+ * the column index
+ */
+ @Test(dataProvider = "rowsetUsingDataTypes")
+ public void commonCachedRowSetTest0040(CachedRowSet rs, JDBCType type) throws Exception {
+ rs.beforeFirst();
+ assertTrue(rs.next());
+ switch (type) {
+ case INTEGER:
+ assertFalse(rs.columnUpdated(1));
+ rs.updateInt(1, Integer.MIN_VALUE);
+ assertTrue(rs.columnUpdated(1));
+ break;
+ case CHAR:
+ assertFalse(rs.columnUpdated(2));
+ rs.updateString(2, "foo");
+ assertTrue(rs.columnUpdated(2));
+ break;
+ case VARCHAR:
+ assertFalse(rs.columnUpdated(3));
+ rs.updateString(3, "foo");
+ assertTrue(rs.columnUpdated(3));
+ break;
+ case BIGINT:
+ assertFalse(rs.columnUpdated(4));
+ rs.updateLong(4, Long.MIN_VALUE);
+ assertTrue(rs.columnUpdated(4));
+ break;
+ case BOOLEAN:
+ assertFalse(rs.columnUpdated(5));
+ rs.updateBoolean(5, false);
+ assertTrue(rs.columnUpdated(5));
+ break;
+ case SMALLINT:
+ assertFalse(rs.columnUpdated(6));
+ rs.updateShort(6, Short.MIN_VALUE);
+ assertTrue(rs.columnUpdated(6));
+ break;
+ case DOUBLE:
+ assertFalse(rs.columnUpdated(7));
+ rs.updateDouble(7, Double.MIN_VALUE);
+ assertTrue(rs.columnUpdated(7));
+ break;
+ case DECIMAL:
+ assertFalse(rs.columnUpdated(8));
+ rs.updateBigDecimal(8, BigDecimal.TEN);
+ assertTrue(rs.columnUpdated(8));
+ break;
+ case REAL:
+ assertFalse(rs.columnUpdated(9));
+ rs.updateFloat(9, Float.MIN_VALUE);
+ assertTrue(rs.columnUpdated(9));
+ break;
+ case TINYINT:
+ assertFalse(rs.columnUpdated(10));
+ rs.updateByte(10, Byte.MIN_VALUE);
+ assertTrue(rs.columnUpdated(10));
+ break;
+ case DATE:
+ assertFalse(rs.columnUpdated(11));
+ rs.updateDate(11, Date.valueOf(LocalDate.now()));
+ assertTrue(rs.columnUpdated(11));
+ break;
+ case TIME:
+ assertFalse(rs.columnUpdated(12));
+ rs.updateTime(12, Time.valueOf(LocalTime.now()));
+ assertTrue(rs.columnUpdated(12));
+ break;
+ case TIMESTAMP:
+ assertFalse(rs.columnUpdated(13));
+ rs.updateTimestamp(13, Timestamp.valueOf(LocalDateTime.now()));
+ assertTrue(rs.columnUpdated(13));
+ break;
+ case VARBINARY:
+ assertFalse(rs.columnUpdated(14));
+ rs.updateBytes(14, new byte[1]);
+ assertTrue(rs.columnUpdated(14));
+ break;
+ case ARRAY:
+ assertFalse(rs.columnUpdated(15));
+ rs.updateArray(15, new StubArray("VARCHAR", new Object[10]));
+ assertTrue(rs.columnUpdated(15));
+ break;
+ case REF:
+ assertFalse(rs.columnUpdated(16));
+ rs.updateRef(16, new StubRef("INTEGER", query));
+ assertTrue(rs.columnUpdated(16));
+ break;
+ case FLOAT:
+ assertFalse(rs.columnUpdated(17));
+ rs.updateDouble(17, Double.MIN_NORMAL);
+ assertTrue(rs.columnUpdated(17));
+ }
+
+ }
+
+ /*
+ * Validate that columnUpdated works with the various datatypes specifying
+ * the column name
+ */
+ @Test(dataProvider = "rowsetUsingDataTypes")
+ public void commonCachedRowSetTest0041(CachedRowSet rs, JDBCType type) throws Exception {
+ rs.beforeFirst();
+ assertTrue(rs.next());
+ switch (type) {
+ case INTEGER:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[0]));
+ rs.updateInt(DATATYPES_COLUMN_NAMES[0], Integer.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[0]));
+ break;
+ case CHAR:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[1]));
+ rs.updateString(DATATYPES_COLUMN_NAMES[1], "foo");
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[1]));
+ break;
+ case VARCHAR:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[2]));
+ rs.updateString(DATATYPES_COLUMN_NAMES[2], "foo");
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[2]));
+ break;
+ case BIGINT:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[3]));
+ rs.updateLong(DATATYPES_COLUMN_NAMES[3], Long.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[3]));
+ break;
+ case BOOLEAN:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[4]));
+ rs.updateBoolean(DATATYPES_COLUMN_NAMES[4], false);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[4]));
+ break;
+ case SMALLINT:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[5]));
+ rs.updateShort(DATATYPES_COLUMN_NAMES[5], Short.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[5]));
+ break;
+ case DOUBLE:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[6]));
+ rs.updateDouble(DATATYPES_COLUMN_NAMES[6], Double.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[6]));
+ break;
+ case DECIMAL:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[7]));
+ rs.updateBigDecimal(DATATYPES_COLUMN_NAMES[7], BigDecimal.TEN);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[7]));
+ break;
+ case REAL:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[8]));
+ rs.updateFloat(DATATYPES_COLUMN_NAMES[8], Float.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[8]));
+ break;
+ case TINYINT:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[9]));
+ rs.updateByte(DATATYPES_COLUMN_NAMES[9], Byte.MIN_VALUE);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[9]));
+ break;
+ case DATE:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[10]));
+ rs.updateDate(DATATYPES_COLUMN_NAMES[10], Date.valueOf(LocalDate.now()));
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[10]));
+ break;
+ case TIME:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[11]));
+ rs.updateTime(DATATYPES_COLUMN_NAMES[11], Time.valueOf(LocalTime.now()));
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[11]));
+ break;
+ case TIMESTAMP:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[12]));
+ rs.updateTimestamp(DATATYPES_COLUMN_NAMES[12], Timestamp.valueOf(LocalDateTime.now()));
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[12]));
+ break;
+ case VARBINARY:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[13]));
+ rs.updateBytes(DATATYPES_COLUMN_NAMES[13], new byte[1]);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[13]));
+ break;
+ case ARRAY:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[14]));
+ rs.updateArray(DATATYPES_COLUMN_NAMES[14], new StubArray("VARCHAR", new Object[10]));
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[14]));
+ break;
+ case REF:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[15]));
+ rs.updateRef(DATATYPES_COLUMN_NAMES[15], new StubRef("INTEGER", query));
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[15]));
+ break;
+ case FLOAT:
+ assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[16]));
+ rs.updateDouble(DATATYPES_COLUMN_NAMES[16], Double.MIN_NORMAL);
+ assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[16]));
+ break;
+ }
+
+ }
+
+ /*
+ * Validate isBeforeFirst(), isFirst() and first() return the correct
+ * results
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0042(RowSet rs) throws Exception {
+ assertFalse(rs.isBeforeFirst());
+ assertFalse(rs.isFirst());
+ rs.beforeFirst();
+ assertTrue(rs.isBeforeFirst());
+ assertFalse(rs.isFirst());
+ rs.next();
+ assertFalse(rs.isBeforeFirst());
+ assertTrue(rs.isFirst());
+ rs.next();
+ assertFalse(rs.isBeforeFirst());
+ assertFalse(rs.isFirst());
+ rs.first();
+ assertFalse(rs.isBeforeFirst());
+ assertTrue(rs.isFirst());
+ rs.close();
+ }
+
+ /*
+ * Validate isAfterLast(), isLast() and last() return the correct
+ * results
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0043(RowSet rs) throws Exception {
+ assertFalse(rs.isAfterLast());
+ assertFalse(rs.isLast());
+ rs.afterLast();
+ assertTrue(rs.isAfterLast());
+ assertFalse(rs.isLast());
+ rs.previous();
+ assertFalse(rs.isAfterLast());
+ assertTrue(rs.isLast());
+ rs.previous();
+ assertFalse(rs.isAfterLast());
+ assertFalse(rs.isLast());
+ rs.last();
+ assertFalse(rs.isAfterLast());
+ assertTrue(rs.isLast());
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoDelete is called on the
+ * insertRow
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0044(CachedRowSet rs) throws Exception {
+ rs.insertRow();
+ rs.undoDelete();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoDelete is called when
+ * cursor is before the first row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0045(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.beforeFirst();
+ rs.undoDelete();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoDelete is called when
+ * cursor is after the last row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0046(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.afterLast();
+ rs.undoDelete();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoUpdate is called on the
+ * insertRow
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0047(CachedRowSet rs) throws Exception {
+ rs.insertRow();
+ rs.undoUpdate();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoUpdate is called when
+ * cursor is before the first row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0048(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.beforeFirst();
+ rs.undoUpdate();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoUpdate is called when
+ * cursor is after the last row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0049(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.afterLast();
+ rs.undoUpdate();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoInsert is called on the
+ * insertRow
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0050(CachedRowSet rs) throws Exception {
+ rs.insertRow();
+ rs.undoInsert();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoInsert is called when
+ * cursor is before the first row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0051(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.beforeFirst();
+ rs.undoInsert();
+ rs.close();
+ }
+
+ /*
+ * Validate a SQLException is thrown when undoInsert is called when
+ * cursor is after the last row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses",
+ expectedExceptions = SQLException.class)
+ public void commonCachedRowSetTest0052(CachedRowSet rs) throws Exception {
+ rs.setShowDeleted(true);
+ rs.afterLast();
+ rs.undoInsert();
+ rs.close();
+ }
+
+ /*
+ * Insert a row, then call undoInsert to roll back the insert and validate
+ * the row is not there
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0053(CachedRowSet rs) throws Exception {
+ int rowToInsert = 1961;
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ // Add new row
+ rs.moveToInsertRow();
+ rs.updateInt(1, rowToInsert);
+ rs.updateString(2, "GOTHAM");
+ rs.updateInt(3, 3450);
+ rs.updateInt(4, 2005);
+ rs.updateInt(5, 5455);
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ // check that the number of rows has increased
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
+ assertTrue(findRowByPrimaryKey(rs, rowToInsert, 1));
+ rs.undoInsert();
+ // Check to make sure the row is no longer there
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ assertFalse(findRowByPrimaryKey(rs, rowToInsert, 1));
+ rs.close();
+ }
+
+ /*
+ * Insert a row, delete the row and then call undoDelete to make sure it
+ * is comes back
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0054(CachedRowSet rs) throws Exception {
+ int rowToDelete = 1961;
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ // Add new row
+ rs.moveToInsertRow();
+ rs.updateInt(1, rowToDelete);
+ rs.updateString(2, "GOTHAM");
+ rs.updateInt(3, 3450);
+ rs.updateInt(4, 2005);
+ rs.updateInt(5, 5455);
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ // check that the number of rows has increased
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
+ assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
+ rs.absolute(COFFEE_HOUSES_ROWS + 1);
+ rs.deleteRow();
+ // Check to make sure the row is no longer there
+ //assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ assertFalse(findRowByPrimaryKey(rs, rowToDelete, 1));
+ rs.setShowDeleted(true);
+ rs.absolute(COFFEE_HOUSES_ROWS + 1);
+ rs.undoDelete();
+ // check that the row is back
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
+ assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
+ rs.close();
+ }
+
+ /*
+ * Insert a row, modify a field and then call undoUpdate to revert the
+ * insert
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0055(CachedRowSet rs) throws Exception {
+ int rowToInsert = 1961;
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ // Add new row
+ rs.moveToInsertRow();
+ rs.updateInt(1, rowToInsert);
+ rs.updateString(2, "GOTHAM");
+ rs.updateInt(3, 3450);
+ rs.updateInt(4, 2005);
+ rs.updateInt(5, 5455);
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ // check that the number of rows has increased
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
+ assertTrue(findRowByPrimaryKey(rs, rowToInsert, 1));
+ rs.absolute(COFFEE_HOUSES_ROWS + 1);
+ // Save off the original column values
+ String f2 = rs.getString(2);
+ int f3 = rs.getInt(3);
+ rs.updateString(2, "SMALLVILLE");
+ rs.updateInt(3, 500);
+ // Validate the columns have been updated
+ assertTrue(rs.columnUpdated(2));
+ assertTrue(rs.columnUpdated(3));
+ // Undo the update and validate it has taken place
+ rs.absolute(COFFEE_HOUSES_ROWS + 1);
+ rs.undoUpdate();
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ assertFalse(findRowByPrimaryKey(rs, rowToInsert, 1));
+ rs.close();
+ }
+
+ /*
+ * Validate getOriginal returns a ResultSet which is a copy of the original
+ * RowSet
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void commonCachedRowSetTest0056(CachedRowSet rs) throws Exception {
+ String coffee = "Hazelnut";
+ int sales = 100;
+ int id = 200;
+ Object[] updatedPkeys = {1, id, 3, 4, 5};
+ // Change the coffee name and sales total for row 2 and save the
+ // previous values
+ rs.absolute(2);
+ int origId = rs.getInt(1);
+ String origCoffee = rs.getString(2);
+ int origSales = rs.getInt(5);
+ rs.updateInt(1, id);
+ rs.updateString(2, coffee);
+ rs.updateInt(5, sales);
+ // MetaData should match
+ try ( // Get the original original RowSet and validate that the changes
+ // are only made to the current, not the original
+ ResultSet rs1 = rs.getOriginal()) {
+ // MetaData should match
+ compareMetaData(rs.getMetaData(), rs1.getMetaData());
+ assertTrue(rs1.isBeforeFirst());
+ assertTrue(rs1.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
+ assertTrue(rs1.getType() == ResultSet.TYPE_SCROLL_INSENSITIVE);
+ rs1.absolute(2);
+ // Check original rowset is not changed
+ assertTrue(rs1.getInt(1) == origId);
+ assertTrue(rs1.getString(2).equals(origCoffee));
+ assertTrue(rs1.getInt(5) == origSales);
+ assertEquals(getPrimaryKeys(rs1), COFFEES_PRIMARY_KEYS);
+ // Check current rowset
+ assertTrue(rs.getInt(1) == id);
+ assertTrue(rs.getString(2).equals(coffee));
+ assertTrue(rs.getInt(5) == sales);
+ assertEquals(getPrimaryKeys(rs), updatedPkeys);
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate getOriginalRow returns a ResultSet which is a copy of the
+ * original row that was modified
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void commonCachedRowSetTest0057(CachedRowSet rs) throws Exception {
+ String coffee = "Hazelnut";
+ int sales = 100;
+ int id = 200;
+ Object[] updatedPkeys = {1, id, 3, 4, 5};
+ // Change the coffee name and sales total for row 2 and save the
+ // previous values
+ rs.absolute(2);
+ int origId = rs.getInt(1);
+ String origCoffee = rs.getString(2);
+ int origSales = rs.getInt(5);
+ rs.updateInt(1, id);
+ rs.updateString(2, coffee);
+ rs.updateInt(5, sales);
+ // MetaData should match
+ try ( // Get the original original row and validate that the changes
+ // are only made to the current, not the original
+ ResultSet rs1 = rs.getOriginalRow()) {
+ // MetaData should match
+ compareMetaData(rs.getMetaData(), rs1.getMetaData());
+ assertTrue(rs1.isBeforeFirst());
+ assertTrue(rs1.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
+ assertTrue(rs1.getType() == ResultSet.TYPE_SCROLL_INSENSITIVE);
+ rs1.next();
+ assertTrue(rs1.isFirst() && rs1.isLast());
+ assertTrue(rs1.getRow() == 1);
+ // Check original row is not changed
+ assertTrue(rs1.getInt(1) == origId);
+ assertTrue(rs1.getString(2).equals(origCoffee));
+ assertTrue(rs1.getInt(5) == origSales);
+ // Check current row
+ assertTrue(rs.getInt(1) == id);
+ assertTrue(rs.getString(2).equals(coffee));
+ assertTrue(rs.getInt(5) == sales);
+ assertEquals(getPrimaryKeys(rs), updatedPkeys);
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that restoreOrginal will restore the RowSet to its
+ * state prior to the insert of a row
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0058(CachedRowSet rs) throws Exception {
+ int rowToInsert = 1961;
+ assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
+ try ( // Add new row
+ CachedRowSet crs1 = rsf.createCachedRowSet()) {
+ rs.beforeFirst();
+ crs1.populate(rs);
+ TestRowSetListener rsl = new TestRowSetListener();
+ crs1.addRowSetListener(rsl);
+ crs1.moveToInsertRow();
+ crs1.updateInt(1, rowToInsert);
+ crs1.updateString(2, "GOTHAM");
+ crs1.updateInt(3, 3450);
+ crs1.updateInt(4, 2005);
+ crs1.updateInt(5, 5455);
+ crs1.insertRow();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
+ crs1.moveToCurrentRow();
+ assertTrue(findRowByPrimaryKey(crs1, rowToInsert, 1));
+ // Restore back to our original state and the
+ // previously inserted row should not be there
+ rsl.resetFlag();
+ crs1.restoreOriginal();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
+ assertTrue(crs1.isBeforeFirst());
+ crs1.last();
+ assertFalse(crs1.rowInserted());
+ assertFalse(findRowByPrimaryKey(crs1, rowToInsert, 1));
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that restoreOrginal will restore the RowSet to its
+ * state prior to deleting a row
+ */
+ @Test(dataProvider = "rowsetUsingCoffees", enabled = true)
+ public void commonCachedRowSetTest0059(CachedRowSet rs) throws Exception {
+ int rowToDelete = 2;
+ try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
+ rs.beforeFirst();
+ crs1.populate(rs);
+ TestRowSetListener rsl = new TestRowSetListener();
+ crs1.addRowSetListener(rsl);
+ // Delete a row, the PK is also the absolute position as a List
+ // backs the RowSet
+ crs1.absolute(rowToDelete);
+ crs1.deleteRow();
+ assertTrue(crs1.rowDeleted());
+ assertFalse(findRowByPrimaryKey(crs1, rowToDelete, 1));
+ // Restore back to our original state and the
+ // previously deleted row should be there
+ rsl.resetFlag();
+ crs1.restoreOriginal();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
+ assertTrue(crs1.isBeforeFirst());
+ crs1.absolute(rowToDelete);
+ assertFalse(crs1.rowDeleted());
+ assertTrue(findRowByPrimaryKey(crs1, rowToDelete, 1));
+ }
+ rs.close();
+ }
+
+ /*
+ * Validate that restoreOrginal will restore the RowSet to its
+ * state prior to updating a row
+ */
+ @Test(dataProvider = "rowsetUsingCoffees", enabled = true)
+ public void commonCachedRowSetTest0060(CachedRowSet rs) throws Exception {
+ int rowToUpdate = 2;
+ String coffee = "Hazelnut";
+ try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
+ rs.beforeFirst();
+ crs1.populate(rs);
+ TestRowSetListener rsl = new TestRowSetListener();
+ crs1.addRowSetListener(rsl);
+ // Delete a row, the PK is also the absolute position as a List
+ // backs the RowSet
+ crs1.absolute(rowToUpdate);
+ String origCoffee = crs1.getString(2);
+ crs1.updateString(2, coffee);
+ assertTrue(crs1.columnUpdated(2));
+ crs1.updateRow();
+ assertTrue(crs1.rowUpdated());
+ assertFalse(origCoffee.equals(crs1.getString(2)));
+ // Restore back to our original state and the
+ // previous value for the column within the row should be there
+ rsl.resetFlag();
+ crs1.restoreOriginal();
+ assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
+ assertTrue(crs1.isBeforeFirst());
+ // absolute() is failing for some reason so need to look at this later
+ crs1.next();
+ crs1.next();
+ assertFalse(crs1.columnUpdated(2));
+ assertFalse(crs1.rowUpdated());
+ assertTrue(origCoffee.equals(crs1.getString(2)));
+ }
+ rs.close();
+ }
+
+ /*
+ * Initialize a RowSet via the populate method. Validate it matches
+ * the original ResultSet
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0061(CachedRowSet rs) throws Exception {
+ try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
+ rs.beforeFirst();
+ crs1.populate(rs);
+ compareRowSets(rs, crs1);
+ }
+ rs.close();
+ }
+
+ /*
+ * Initialize a RowSet via the populate method specifying a starting row.
+ * Validate it matches the original ResultSet starting for the specofied
+ * offset
+ */
+ @Test(dataProvider = "rowsetUsingCoffeeHouses")
+ public void commonCachedRowSetTest0062(CachedRowSet rs) throws Exception {
+ Object[] expectedRows = {
+ 32001, 10042, 10024, 10039, 10041, 33005, 33010, 10035, 10037,
+ 10034, 32004
+ };
+ int startingRow = 4;
+ try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
+ rs.beforeFirst();
+ crs1.populate(rs, startingRow);
+ assertEquals(crs1.size(), COFFEE_HOUSES_ROWS - startingRow + 1);
+ assertEquals(getPrimaryKeys(crs1), expectedRows);
+ }
+ rs.close();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/filteredrowset/CityFilter.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.filteredrowset;
+
+import java.sql.SQLException;
+import javax.sql.RowSet;
+import javax.sql.rowset.Predicate;
+
+/*
+ * Simple implementation of Predicate which is used to filter rows based
+ * on a City.
+ */
+public class CityFilter implements Predicate {
+
+ private final String[] cities;
+ private String colName = null;
+ private int colNumber = -1;
+
+ public CityFilter(String[] cities, String colName) {
+ this.cities = cities;
+ this.colName = colName;
+ }
+
+ public CityFilter(String[] cities, int colNumber) {
+ this.cities = cities;
+ this.colNumber = colNumber;
+ }
+
+ public boolean evaluate(Object value, String colName) {
+
+ if (colName.equalsIgnoreCase(this.colName)) {
+ for (String city : cities) {
+ if (city.equalsIgnoreCase((String) value)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean evaluate(Object value, int colNumber) {
+
+ if (colNumber == this.colNumber) {
+ for (String city : this.cities) {
+ if (city.equalsIgnoreCase((String) value)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean evaluate(RowSet rs) {
+
+ boolean result = false;
+
+ if (rs == null) {
+ return false;
+ }
+
+ try {
+ for (String city : cities) {
+
+ String val = "";
+ if (colNumber > 0) {
+ val = (String) rs.getObject(colNumber);
+ } else if (colName != null) {
+ val = (String) rs.getObject(colName);
+ }
+
+ if (val.equalsIgnoreCase(city)) {
+ return true;
+ }
+ }
+ } catch (SQLException e) {
+ result = false;
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/filteredrowset/FilteredRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.filteredrowset;
+
+import java.sql.SQLException;
+import javax.sql.RowSet;
+import javax.sql.rowset.FilteredRowSet;
+import javax.sql.rowset.Predicate;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import test.rowset.webrowset.CommonWebRowSetTests;
+
+public class FilteredRowSetTests extends CommonWebRowSetTests {
+
+ private FilteredRowSet frs;
+
+ @BeforeMethod
+ public void setUpMethod() throws Exception {
+ frs = createCoffeeHousesRowSet();
+ }
+
+ @AfterMethod
+ public void tearDownMethod() throws Exception {
+ frs.close();
+ }
+
+ protected FilteredRowSet newInstance() throws SQLException {
+ return rsf.createFilteredRowSet();
+ }
+
+ /*
+ * Validate getFilter returns null if setFilter has not been called
+ */
+ @Test
+ public void FilteredRowSetTest0000() throws SQLException {
+ assertNull(frs.getFilter());
+ }
+
+ /*
+ * Call setFilter to set a Predicate and validate that getFilter
+ * returns the correct Predicate
+ */
+ @Test
+ public void FilteredRowSetTest0001() throws SQLException {
+ Predicate p = new PrimaryKeyFilter(0, 100030, 1);
+ frs.setFilter(p);
+ assertTrue(frs.getFilter().equals(p));
+ frs.setFilter(null);
+ assertNull(frs.getFilter());
+ }
+
+ /*
+ * Validate that the correct rows are returned when a Predicate using
+ * a column index is used
+ */
+ @Test
+ public void FilteredRowSetTest0002() throws SQLException {
+ Object[] expectedKeys = {
+ 10023, 10040, 10042, 10024, 10039, 10041, 10035, 10037, 10034
+ };
+ frs.setFilter(new PrimaryKeyFilter(10000, 10999, 1));
+ assertEquals(getPrimaryKeys(frs), expectedKeys);
+ }
+
+ /*
+ * Validate that the correct rows are returned when a Predicate using
+ * a column Label is used
+ */
+ @Test
+ public void FilteredRowSetTest0003() throws SQLException {
+ Object[] expectedKeys = {
+ 10023, 10040, 10042, 10024, 10039, 10041, 10035, 10037, 10034
+ };
+ frs.setFilter(new PrimaryKeyFilter(10000, 10999, "STORE_ID"));
+ assertEquals(getPrimaryKeys(frs), expectedKeys);
+
+ }
+
+ /*
+ * Validate that the correct rows are returned when a Predicate using
+ * a column index is used
+ */
+ @Test
+ public void FilteredRowSetTest0004() throws SQLException {
+ Object[] expectedKeys = {
+ 10040, 10042, 10041, 10035, 10037
+ };
+ String[] cityArray = {"SF", "LA"};
+ frs.setFilter(new CityFilter(cityArray, 2));
+ assertEquals(getPrimaryKeys(frs), expectedKeys);
+ }
+
+ /*
+ * Validate that the correct rows are returned when a Predicate using
+ * a column Label is used
+ */
+ @Test
+ public void FilteredRowSetTest0005() throws SQLException {
+ Object[] expectedKeys = {
+ 10040, 10042, 10041, 10035, 10037
+ };
+ String[] cityArray = {"SF", "LA"};
+ frs.setFilter(new CityFilter(cityArray, "CITY"));
+ assertEquals(getPrimaryKeys(frs), expectedKeys);
+ }
+
+
+ // Tests that are common but need to be disabled due to an implementation bug
+
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0043(RowSet rs) throws Exception {
+ // Need to fix bug in FilteredRowSets
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/filteredrowset/PrimaryKeyFilter.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.filteredrowset;
+
+import javax.sql.RowSet;
+import javax.sql.rowset.Predicate;
+
+/*
+ * Simple implementation of Predicate which is used to filter rows based
+ * on the Primary Key.
+ */
+public class PrimaryKeyFilter implements Predicate {
+
+ private final int lo;
+ private final int hi;
+ private String colName = null;
+ private int colNumber = -1;
+
+ public PrimaryKeyFilter(int lo, int hi, int colNumber) {
+ this.lo = lo;
+ this.hi = hi;
+ this.colNumber = colNumber;
+ }
+
+ public PrimaryKeyFilter(int lo, int hi, String colName) {
+ this.lo = lo;
+ this.hi = hi;
+ this.colName = colName;
+ }
+
+ public boolean evaluate(Object value, String columnName) {
+
+ boolean result = false;
+ if (columnName.equalsIgnoreCase(this.colName)) {
+ int columnValue = ((Integer) value);
+ result = (columnValue >= this.lo) && (columnValue <= this.hi);
+ }
+ return result;
+ }
+
+ public boolean evaluate(Object value, int columnNumber) {
+
+ boolean result = false;
+ if (this.colNumber == columnNumber) {
+ int columnValue = (Integer) value;
+ result = (columnValue >= this.lo) && (columnValue <= this.hi);
+ }
+ return result;
+ }
+
+ public boolean evaluate(RowSet rs) {
+
+ boolean result = false;
+ try {
+ int columnValue = -1;
+
+ if (this.colNumber > 0) {
+ columnValue = rs.getInt(this.colNumber);
+ } else if (this.colName != null) {
+ columnValue = rs.getInt(this.colName);
+ }
+ if ((columnValue >= this.lo) && (columnValue <= this.hi)) {
+ result = true;
+ }
+
+ } catch (Exception e) {
+ System.out.println("Error:" + e.getMessage());
+ result = false;
+ }
+ return result;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/joinrowset/JoinRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.joinrowset;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+import javax.sql.RowSet;
+import javax.sql.rowset.CachedRowSet;
+import javax.sql.rowset.JoinRowSet;
+import javax.sql.rowset.RowSetMetaDataImpl;
+import javax.sql.rowset.WebRowSet;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import test.rowset.webrowset.CommonWebRowSetTests;
+
+public class JoinRowSetTests extends CommonWebRowSetTests {
+
+ private final String SUPPLIERS_TABLE = "SUPPLIERS";
+ // Expected COF_IDs to be found
+ private final Object[] EXPECTED = {4, 1};
+ // SUPPLIERS Primary Key to use to validate the joins
+ private final int SUP_ID = 101;
+ // Join Column between the SUPPLIERS and COFFEES table
+ private final String JOIN_COLNAME = "SUP_ID";
+ // Column index in COFFEES table which contains SUP_ID
+ private final int COFFEES_JOIN_COLUMN_INDEX = 3;
+ // Column index in SUPPLIERS table which contains SUP_ID
+ private final int SUPPLIERS_JOIN_COLUMN_INDEX = 1;
+
+ @Override
+ protected JoinRowSet newInstance() throws SQLException {
+ return rsf.createJoinRowSet();
+ }
+
+ /*
+ * Initializes the SUPPLIERS metadata
+ */
+ private void initSuppliersMetaData(CachedRowSet crs) throws SQLException {
+ RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();
+
+ /*
+ * CREATE TABLE SUPPLIERS (
+ * SUP_ID INTEGER NOT NULL,
+ * SUP_NAME VARCHAR(32) NOT NULL,
+ * STREET VARCHAR(32) NOT NULL,
+ * CITY VARCHAR(32) NOT NULL,
+ * STATE CHAR(2) NOT NULL,
+ * ZIP CHAR(5) NOT NULL,
+ * PRIMARY KEY (SUP_ID))
+ */
+ rsmd.setColumnCount(6);
+ rsmd.setColumnName(1, "SUP_ID");
+ rsmd.setColumnName(2, "SUP_NAME");
+ rsmd.setColumnName(3, "STREET");
+ rsmd.setColumnName(4, "CITY");
+ rsmd.setColumnName(5, "STATE");
+ rsmd.setColumnName(6, "ZIP");
+
+ rsmd.setColumnType(1, Types.INTEGER);
+ rsmd.setColumnType(2, Types.VARCHAR);
+ rsmd.setColumnType(3, Types.VARCHAR);
+ rsmd.setColumnType(4, Types.VARCHAR);
+ rsmd.setColumnType(5, Types.CHAR);
+ rsmd.setColumnType(6, Types.CHAR);
+ crs.setMetaData(rsmd);
+ crs.setTableName(SUPPLIERS_TABLE);
+ }
+
+ /*
+ * Add rows to SUPPLIERS table
+ */
+ protected void createSuppiersRows(RowSet rs) throws SQLException {
+
+ // insert into SUPPLIERS values(49, 'Superior Coffee', '1 Party Place',
+ // 'Mendocino', 'CA', '95460')
+ rs.moveToInsertRow();
+ rs.updateInt(1, 49);
+ rs.updateString(2, "Superior Coffee");
+ rs.updateString(3, "1 Party Place");
+ rs.updateString(4, "Mendocino");
+ rs.updateString(5, "CA");
+ rs.updateString(6, "95460");
+ rs.insertRow();
+
+ // insert into SUPPLIERS values(101, 'Acme, Inc.', '99 Market Street',
+ // 'Groundsville', 'CA', '95199')
+ rs.moveToInsertRow();
+ rs.updateInt(1, 101);
+ rs.updateString(2, "Acme, Inc.");
+ rs.updateString(3, "99 Market Street");
+ rs.updateString(4, "Groundsville");
+ rs.updateString(5, "CA");
+ rs.updateString(6, "95199");
+ rs.insertRow();
+ // insert into SUPPLIERS values(150, 'The High Ground',
+ // '100 Coffee Lane', 'Meadows', 'CA', '93966')
+ rs.moveToInsertRow();
+ rs.updateInt(1, 150);
+ rs.updateString(2, "The High Ground");
+ rs.updateString(3, "100 Coffee Lane");
+ rs.updateString(4, "Meadows");
+ rs.updateString(5, "CA");
+ rs.updateString(6, "93966");
+ rs.insertRow();
+ // insert into SUPPLIERS values(456," 'Restaurant Supplies, Inc.',
+ // '200 Magnolia Street', 'Meadows', 'CA', '93966')
+ rs.moveToInsertRow();
+ rs.updateInt(1, 456);
+ rs.updateString(2, "Restaurant Supplies, Inc.");
+ rs.updateString(3, "200 Magnolia Stree");
+ rs.updateString(4, "Meadows");
+ rs.updateString(5, "CA");
+ rs.updateString(6, "93966");
+ rs.insertRow();
+ // insert into SUPPLIERS values(927, 'Professional Kitchen',
+ // '300 Daisy Avenue', 'Groundsville'," 'CA', '95199')
+ rs.moveToInsertRow();
+ rs.updateInt(1, 927);
+ rs.updateString(2, "Professional Kitchen");
+ rs.updateString(3, "300 Daisy Avenue");
+ rs.updateString(4, "Groundsville");
+ rs.updateString(5, "CA");
+ rs.updateString(6, "95199");
+ rs.insertRow();
+ }
+
+ /*
+ * DataProvider used to set parameters for basic types that are supported
+ */
+ @DataProvider(name = "createCachedRowSetsToUse")
+ private Object[][] createCachedRowSetsToUse() throws SQLException {
+ CachedRowSet crs = rsf.createCachedRowSet();
+ initCoffeesMetaData(crs);
+ createCoffeesRows(crs);
+ // Make sure you are not on the insertRow
+ crs.moveToCurrentRow();
+ CachedRowSet crs1 = rsf.createCachedRowSet();
+ initSuppliersMetaData(crs1);
+ createSuppiersRows(crs1);
+ // Make sure you are not on the insertRow
+ crs1.moveToCurrentRow();
+ return new Object[][]{
+ {crs, crs1}
+ };
+ }
+
+ /*
+ * Validate that the correct coffees are returned for SUP_ID
+ */
+ private void validateResults(final JoinRowSet jrs) throws SQLException {
+ List<Integer> results = new ArrayList<>();
+ jrs.beforeFirst();
+ while (jrs.next()) {
+ if (jrs.getInt(JOIN_COLNAME) == SUP_ID) {
+ results.add(jrs.getInt("COF_ID"));
+ }
+ }
+ assertEquals(results.toArray(), EXPECTED);
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column name to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0000(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ jrs.addRowSet(crs, JOIN_COLNAME);
+ jrs.addRowSet(crs1, JOIN_COLNAME);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column index to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0001(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ jrs.addRowSet(crs, COFFEES_JOIN_COLUMN_INDEX);
+ jrs.addRowSet(crs1, SUPPLIERS_JOIN_COLUMN_INDEX);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column name to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0002(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ RowSet[] rowsets = {crs, crs1};
+ String[] joinCols = {JOIN_COLNAME, JOIN_COLNAME};
+ jrs.addRowSet(rowsets, joinCols);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column index to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0003(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ RowSet[] rowsets = {crs, crs1};
+ int[] joinCols = {COFFEES_JOIN_COLUMN_INDEX,
+ SUPPLIERS_JOIN_COLUMN_INDEX};
+ jrs.addRowSet(rowsets, joinCols);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column name to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0005(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ crs.setMatchColumn(JOIN_COLNAME);
+ crs1.setMatchColumn(JOIN_COLNAME);
+ jrs.addRowSet(crs);
+ jrs.addRowSet(crs1);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ /*
+ * Join two CachedRowSets specifying a column index to join against
+ */
+ @Test(dataProvider = "createCachedRowSetsToUse")
+ public void joinRowSetTests0006(CachedRowSet crs, CachedRowSet crs1)
+ throws Exception {
+
+ try (JoinRowSet jrs = newInstance()) {
+ crs.setMatchColumn(COFFEES_JOIN_COLUMN_INDEX);
+ crs1.setMatchColumn(SUPPLIERS_JOIN_COLUMN_INDEX);
+
+ jrs.addRowSet(crs);
+ jrs.addRowSet(crs1);
+ validateResults(jrs);
+ crs.close();
+ crs1.close();
+ }
+ }
+
+ // Disabled tests due to bugs in JoinRowSet
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0004(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0005(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0008(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0026(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0027(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0053(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0054(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType", enabled = false)
+ public void commonCachedRowSetTest0055(CachedRowSet rs) throws Exception {
+ }
+
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0009(WebRowSet wrs1) throws Exception {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/webrowset/CommonWebRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.webrowset;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStreamWriter;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.util.Arrays;
+import javax.sql.rowset.WebRowSet;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertEqualsNoOrder;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import test.rowset.cachedrowset.CommonCachedRowSetTests;
+
+public abstract class CommonWebRowSetTests extends CommonCachedRowSetTests {
+
+ protected final String XMLFILEPATH = System.getProperty("test.src", ".")
+ + File.separatorChar + "xml" + File.separatorChar;
+ protected final String COFFEE_ROWS_XML = XMLFILEPATH + "COFFEE_ROWS.xml";
+ protected final String DELETED_COFFEE_ROWS_XML
+ = XMLFILEPATH + "DELETED_COFFEE_ROWS.xml";
+ protected final String MODFIED_DELETED_COFFEE_ROWS_XML
+ = XMLFILEPATH + "MODFIED_DELETED_COFFEE_ROWS.xml";
+ protected final String UPDATED_COFFEE_ROWS_XML
+ = XMLFILEPATH + "UPDATED_COFFEE_ROWS.xml";
+ protected final String INSERTED_COFFEE_ROWS_XML
+ = XMLFILEPATH + "INSERTED_COFFEE_ROWS.xml";
+ protected final String UPDATED_INSERTED_COFFEE_ROWS_XML
+ = XMLFILEPATH + "UPDATED_INSERTED_COFFEE_ROWS.xml";
+
+
+ /*
+ * Utility method to write a WebRowSet XML file via an OutputStream
+ */
+ protected ByteArrayOutputStream writeWebRowSetWithOutputStream(WebRowSet rs) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ rs.writeXml(oos);
+ }
+ return baos;
+ }
+
+ /*
+ * Utility method to write a WebRowSet XML file via an OutputStream
+ * and populating the WebRowSet via a ResultSet
+ */
+ protected ByteArrayOutputStream writeWebRowSetWithOutputStream(ResultSet rs) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ WebRowSet wrs = rsf.createWebRowSet();
+ wrs.writeXml(rs, oos);
+ }
+ return baos;
+ }
+
+
+ /*
+ * Utility method to popoulate a WebRowSet via a InputStream
+ */
+ protected WebRowSet readWebRowSetWithOInputStream(ByteArrayOutputStream baos) throws Exception {
+ WebRowSet wrs1 = rsf.createWebRowSet();
+ try (ObjectInputStream ois
+ = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+ wrs1.readXml(ois);
+ }
+ return wrs1;
+ }
+
+ /*
+ * Utility method to write a WebRowSet XML file via an Writer
+ */
+ protected ByteArrayOutputStream writeWebRowSetWithOutputStreamWithWriter(WebRowSet rs) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(baos);
+ rs.writeXml(osw);
+ return baos;
+ }
+
+ /*
+ * Utility method to write a WebRowSet XML file via an Writer and populating
+ * the WebRowSet via a ResultSet
+ */
+ protected ByteArrayOutputStream writeWebRowSetWithOutputStreamWithWriter(ResultSet rs) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(baos);
+ WebRowSet wrs = rsf.createWebRowSet();
+ wrs.writeXml(rs, osw);
+ return baos;
+ }
+
+ /*
+ * Utility method to popoulate a WebRowSet via a Readar
+ */
+ protected WebRowSet readWebRowSetWithOInputStreamWithReader(ByteArrayOutputStream baos) throws Exception {
+ WebRowSet wrs1 = rsf.createWebRowSet();
+ InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
+ wrs1.readXml(isr);
+ return wrs1;
+ }
+
+ /*
+ * Validate the expected Rows are contained within the RowSet
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void WebRowSetTest0000(WebRowSet wrs) throws Exception {
+ assertEquals(getPrimaryKeys(wrs), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs.size(), COFFEES_ROWS);
+ wrs.close();
+ }
+
+ /*
+ * Validate the expected Rows are contained within the RowSet
+ * populated by readXML(Reader)
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0001(WebRowSet wrs1) throws Exception {
+
+ try (FileReader fr = new FileReader(COFFEE_ROWS_XML)) {
+ wrs1.readXml(fr);
+ }
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ wrs1.close();
+
+ }
+
+ /*
+ * Validate the expected Rows are contained within the RowSet
+ * populated by readXML(InputStream)
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0002(WebRowSet wrs1) throws Exception {
+ try (FileInputStream fis = new FileInputStream(COFFEE_ROWS_XML)) {
+ wrs1.readXml(fis);
+ }
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ wrs1.close();
+ }
+
+ /*
+ * Write a WebRowSet via writeXML(OutputStream), read it
+ * back via readXML(InputStream) and validate the primary keys
+ * are the same
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void WebRowSetTest0003(WebRowSet wrs) throws Exception {
+ ByteArrayOutputStream baos = writeWebRowSetWithOutputStream(wrs);
+ try (WebRowSet wrs1 = readWebRowSetWithOInputStream(baos)) {
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ }
+ }
+
+ /*
+ * Write a ResultSet via writeXML(OutputStream), read it
+ * back via readXML(InputStream) and validate the primary keys
+ * are the same
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void WebRowSetTest0004(WebRowSet wrs) throws Exception {
+ ResultSet rs = wrs;
+ rs.beforeFirst();
+ ByteArrayOutputStream baos = writeWebRowSetWithOutputStream(rs);
+ try (WebRowSet wrs1 = readWebRowSetWithOInputStream(baos)) {
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ }
+ }
+
+ /*
+ * Write a WebRowSet via writeXML(Writer), read it
+ * back via readXML(Reader) and validate the primary keys
+ * are the same
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void WebRowSetTest0005(WebRowSet wrs) throws Exception {
+ ByteArrayOutputStream baos = writeWebRowSetWithOutputStreamWithWriter(wrs);
+ try (WebRowSet wrs1 = readWebRowSetWithOInputStreamWithReader(baos)) {
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ }
+ }
+
+ /*
+ * Write a WebRowSet via writeXML(Writer), read it
+ * back via readXML(Reader) and validate the primary keys
+ * are the same
+ */
+ @Test(dataProvider = "rowsetUsingCoffees")
+ public void WebRowSetTest0006(WebRowSet wrs) throws Exception {
+ ResultSet rs = wrs;
+ rs.beforeFirst();
+ ByteArrayOutputStream baos = writeWebRowSetWithOutputStreamWithWriter(rs);
+ try (WebRowSet wrs1 = readWebRowSetWithOInputStreamWithReader(baos)) {
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ assertEquals(wrs1.size(), COFFEES_ROWS);
+ }
+ }
+
+ /*
+ * Validate the expected Rows are contained within the RowSet
+ * after deleting the specified rows
+ */
+ @Test(dataProvider = "rowsetUsingCoffees", enabled = false)
+ public void WebRowSetTest0007(WebRowSet wrs) throws Exception {
+ assertEquals(getPrimaryKeys(wrs), COFFEES_PRIMARY_KEYS);
+ int[] rowsToDelete = {2, 4};
+ assertEquals(getPrimaryKeys(wrs), COFFEES_PRIMARY_KEYS);
+ for (int row : rowsToDelete) {
+ assertTrue(deleteRowByPrimaryKey(wrs, row, 1));
+ }
+
+ FileInputStream fis = new FileInputStream(MODFIED_DELETED_COFFEE_ROWS_XML);
+ try (WebRowSet wrs1 = rsf.createWebRowSet()) {
+ wrs1.readXml(fis);
+ // With setShowDeleted(false) which is the default,
+ // the deleted row should not be visible
+ for (int row : rowsToDelete) {
+ assertTrue(findRowByPrimaryKey(wrs1, row, 1));
+ }
+ assertTrue(wrs.size() == COFFEES_ROWS);
+ // With setShowDeleted(true), the deleted row should be visible
+ for (int row : rowsToDelete) {
+ assertTrue(findRowByPrimaryKey(wrs, row, 1));
+ }
+ }
+ }
+
+ /*
+ * Validate the expected Rows are contained within the RowSet
+ * that was populated by reading an xml file with all rows
+ * marked as a currentRow
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0008(WebRowSet wrs1) throws Exception {
+ FileInputStream fis = new FileInputStream(COFFEE_ROWS_XML);
+ wrs1.readXml(fis);
+ assertTrue(wrs1.size() == COFFEES_ROWS);
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ // Validate that the rows are not marked as deleted, inserted or updated
+ wrs1.beforeFirst();
+ while (wrs1.next()) {
+ assertFalse(wrs1.rowDeleted());
+ assertFalse(wrs1.rowInserted());
+ assertFalse(wrs1.rowUpdated());
+ }
+ wrs1.close();
+ }
+
+ /*
+ * Read an XML file to populate a WebRowSet and validate that the rows
+ * that are marked as deleted are marked as such in the WebRowSet
+ * Also validate that they are or are not visible based on the
+ * setShowDeleted value
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0009(WebRowSet wrs1) throws Exception {
+ int[] rowsToDelete = {2, 4};
+ Object[] expectedRows = {1, 3, 5};
+ FileInputStream fis = new FileInputStream(DELETED_COFFEE_ROWS_XML);
+ wrs1.readXml(fis);
+ assertTrue(wrs1.size() == COFFEES_ROWS);
+ assertEquals(getPrimaryKeys(wrs1), expectedRows);
+ // With setShowDeleted(false) which is the default,
+ // the deleted row should not be visible
+ for (int row : rowsToDelete) {
+ assertFalse(findRowByPrimaryKey(wrs1, row, 1));
+ }
+ // With setShowDeleted(true), the deleted row should be visible
+ wrs1.setShowDeleted(true);
+ for (int row : rowsToDelete) {
+ assertTrue(findRowByPrimaryKey(wrs1, row, 1));
+ }
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ wrs1.close();
+
+ }
+
+ /*
+ * Validate that the correct row in the WebRowSet that had been created
+ * from an xml file is marked as updated and contains the correct values
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0010(WebRowSet wrs1) throws Exception {
+ FileInputStream fis = new FileInputStream(UPDATED_COFFEE_ROWS_XML);
+ wrs1.readXml(fis);
+ assertTrue(wrs1.size() == COFFEES_ROWS);
+ assertEquals(getPrimaryKeys(wrs1), COFFEES_PRIMARY_KEYS);
+ wrs1.beforeFirst();
+ while (wrs1.next()) {
+ if (wrs1.getInt(1) == 3) {
+ assertTrue(wrs1.rowUpdated());
+ assertTrue(wrs1.getInt(5) == 21 && wrs1.getInt(6) == 69);
+ assertFalse(wrs1.rowDeleted());
+ assertFalse(wrs1.rowInserted());
+ } else {
+ assertFalse(wrs1.rowUpdated());
+ assertFalse(wrs1.rowDeleted());
+ assertFalse(wrs1.rowInserted());
+ }
+ }
+ wrs1.close();
+ }
+
+ /*
+ * Validate the correct row is marked as inserted in a WebRowSet
+ * that is read from an xml file
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0011(WebRowSet wrs1) throws Exception {
+ int expectedSize = COFFEES_ROWS + 2;
+ int addedRowPK = 15;
+ int addedRowPK2 = 20;
+ Object[] expected = Arrays.copyOf(COFFEES_PRIMARY_KEYS, expectedSize);
+ expected[expectedSize - 2] = addedRowPK;
+ expected[expectedSize - 1] = addedRowPK2;
+ FileInputStream fis = new FileInputStream(INSERTED_COFFEE_ROWS_XML);
+ wrs1.readXml(fis);
+ assertTrue(wrs1.size() == expectedSize);
+ assertEqualsNoOrder(getPrimaryKeys(wrs1), expected);
+ wrs1.beforeFirst();
+ while (wrs1.next()) {
+ if (wrs1.getInt(1) == 15 || wrs1.getInt(1) == 20) {
+ assertTrue(wrs1.rowInserted());
+ assertFalse(wrs1.rowDeleted());
+ assertFalse(wrs1.rowUpdated());
+ } else {
+ assertFalse(wrs1.rowInserted());
+ assertFalse(wrs1.rowDeleted());
+ assertFalse(wrs1.rowUpdated());
+ }
+ }
+ wrs1.close();
+ }
+
+ /*
+ * Read an xml file which contains a row that was inserted and updated
+ */
+ @Test(dataProvider = "rowSetType")
+ public void WebRowSetTest0012(WebRowSet wrs1) throws Exception {
+ int expectedSize = COFFEES_ROWS + 1;
+ int addedRowPK = 100;
+ Object[] expected = Arrays.copyOf(COFFEES_PRIMARY_KEYS, expectedSize);
+ expected[expectedSize - 1] = addedRowPK;
+ FileInputStream fis = new FileInputStream(UPDATED_INSERTED_COFFEE_ROWS_XML);
+ wrs1.readXml(fis);
+ assertTrue(wrs1.size() == expectedSize);
+ assertEquals(getPrimaryKeys(wrs1), expected);
+ wrs1.beforeFirst();
+ while (wrs1.next()) {
+ if (wrs1.getInt(1) == addedRowPK) {
+ // Row that was inserted and updated
+ assertTrue(wrs1.rowUpdated());
+ assertTrue(
+ wrs1.getBigDecimal(4).equals(BigDecimal.valueOf(12.99))
+ && wrs1.getInt(6) == 125);
+ assertFalse(wrs1.rowDeleted());
+ assertTrue(wrs1.rowInserted());
+ } else {
+ // Remaining rows should only be inserted
+ assertFalse(wrs1.rowUpdated());
+ assertFalse(wrs1.rowDeleted());
+ assertTrue(wrs1.rowInserted());
+ }
+ }
+ wrs1.close();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/webrowset/WebRowSetTests.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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 test.rowset.webrowset;
+
+import java.sql.SQLException;
+import javax.sql.rowset.WebRowSet;
+
+public class WebRowSetTests extends CommonWebRowSetTests {
+
+ @Override
+ protected WebRowSet newInstance() throws SQLException {
+ return rsf.createWebRowSet();
+ }
+
+}
--- a/jdk/test/javax/sql/testng/util/StubSyncProvider.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/javax/sql/testng/util/StubSyncProvider.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -51,12 +51,12 @@
@Override
public RowSetReader getRowSetReader() {
- throw new UnsupportedOperationException("Not supported yet.");
+ return null;
}
@Override
public RowSetWriter getRowSetWriter() {
- throw new UnsupportedOperationException("Not supported yet.");
+ return null;
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command><null/></command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url><null/></url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <currentRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/DELETED_COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command>SELECT * FROM COFFEES</command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url>jdbc:derby://localhost:1527/testDB;create=true</url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <currentRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <deleteRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </deleteRow>
+ <currentRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <deleteRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </deleteRow>
+ <currentRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/INSERTED_COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,207 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command><null/></command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url><null/></url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <currentRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <insertRow>
+ <columnValue>15</columnValue>
+ <columnValue>Hazelnut</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>20</columnValue>
+ <columnValue>French Vanilla</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <currentRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/MODFIED_DELETED_COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command><null/></command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url><null/></url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <insertRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <modifyRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </modifyRow>
+ <insertRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <modifyRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </modifyRow>
+ <insertRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/UPDATED_COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,193 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command>SELECT * FROM COFFEES</command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url>jdbc:derby://localhost:1527/testDB;create=true</url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <currentRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <updateRow>21</updateRow>
+ <columnValue>0</columnValue>
+ <updateRow>69</updateRow>
+ </currentRow>
+ <currentRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ <currentRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </currentRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/xml/UPDATED_INSERTED_COFFEE_ROWS.xml Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,201 @@
+<?xml version="1.0"?>
+<webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
+ <properties>
+ <command><null/></command>
+ <concurrency>1008</concurrency>
+ <datasource><null/></datasource>
+ <escape-processing>true</escape-processing>
+ <fetch-direction>1000</fetch-direction>
+ <fetch-size>0</fetch-size>
+ <isolation-level>2</isolation-level>
+ <key-columns>
+ </key-columns>
+ <map>
+ </map>
+ <max-field-size>0</max-field-size>
+ <max-rows>0</max-rows>
+ <query-timeout>0</query-timeout>
+ <read-only>true</read-only>
+ <rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type>
+ <show-deleted>false</show-deleted>
+ <table-name>COFFEES</table-name>
+ <url><null/></url>
+ <sync-provider>
+ <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
+ <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
+ <sync-provider-version>1.0</sync-provider-version>
+ <sync-provider-grade>2</sync-provider-grade>
+ <data-source-lock>1</data-source-lock>
+ </sync-provider>
+ </properties>
+ <metadata>
+ <column-count>6</column-count>
+ <column-definition>
+ <column-index>1</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>COF_NAME</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>2</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SUP_ID</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>12</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>3</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>PRICE</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>4</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>SALES</column-name>
+ <schema-name></schema-name>
+ <column-precision>10</column-precision>
+ <column-scale>2</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>2</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>5</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name>TOTAL</column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ <column-definition>
+ <column-index>6</column-index>
+ <auto-increment>false</auto-increment>
+ <case-sensitive>false</case-sensitive>
+ <currency>false</currency>
+ <nullable>0</nullable>
+ <signed>false</signed>
+ <searchable>false</searchable>
+ <column-display-size>0</column-display-size>
+ <column-label><null/></column-label>
+ <column-name><null/></column-name>
+ <schema-name></schema-name>
+ <column-precision>0</column-precision>
+ <column-scale>0</column-scale>
+ <table-name></table-name>
+ <catalog-name></catalog-name>
+ <column-type>4</column-type>
+ <column-type-name><null/></column-type-name>
+ </column-definition>
+ </metadata>
+ <data>
+ <insertRow>
+ <columnValue>1</columnValue>
+ <columnValue>Colombian</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>7.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>2</columnValue>
+ <columnValue>French_Roast</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>3</columnValue>
+ <columnValue>Espresso</columnValue>
+ <columnValue>150</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>4</columnValue>
+ <columnValue>Colombian_Decaf</columnValue>
+ <columnValue>101</columnValue>
+ <columnValue>8.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>5</columnValue>
+ <columnValue>French_Roast_Decaf</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <columnValue>0</columnValue>
+ <columnValue>0</columnValue>
+ </insertRow>
+ <insertRow>
+ <columnValue>100</columnValue>
+ <columnValue>Mocha</columnValue>
+ <columnValue>49</columnValue>
+ <columnValue>9.99</columnValue>
+ <updateRow>12.99</updateRow>
+ <columnValue>20</columnValue>
+ <columnValue>35</columnValue>
+ <updateRow>125</updateRow>
+ </insertRow>
+ </data>
+</webRowSet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JButton/4796987/bug4796987.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, 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 4796987
+ * @summary XP Only: JButton.setBorderPainted() does not work with XP L&F
+ * @author Alexander Scherbatiy
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug4796987
+ */
+
+import java.awt.*;
+import javax.swing.*;
+import sun.awt.OSInfo;
+import sun.awt.SunToolkit;
+import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
+
+public class bug4796987 {
+
+ private static JButton button1;
+ private static JButton button2;
+
+ public static void main(String[] args) throws Exception {
+ if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS
+ && OSInfo.getWindowsVersion() == OSInfo.WINDOWS_XP) {
+ UIManager.setLookAndFeel(new WindowsLookAndFeel());
+ testButtonBorder();
+ }
+ }
+
+ private static void testButtonBorder() throws Exception {
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ public void run() {
+ createAndShowGUI();
+ }
+ });
+
+ toolkit.realSync();
+ Thread.sleep(500);
+
+ Point p1 = Util.getCenterPoint(button1);
+ Point p2 = Util.getCenterPoint(button2);
+
+ Color color = robot.getPixelColor(p1.x, p2.x);
+ for (int dx = p1.x; dx < p2.x - p1.x; dx++) {
+ robot.mouseMove(p1.x + dx, p1.y);
+ if (!color.equals(robot.getPixelColor(p1.x + dx, p1.y))) {
+ throw new RuntimeException("Button has border and background!");
+ }
+ }
+ }
+
+ private static JButton getButton() {
+ JButton button = new JButton();
+ button.setBorderPainted(false);
+ button.setFocusable(false);
+ return button;
+ }
+
+ private static void createAndShowGUI() {
+ JFrame frame = new JFrame("Test");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(200, 200);
+
+ JButton button = new JButton();
+ button.setBorder(null);
+
+ JPanel panel = new JPanel(new BorderLayout(50, 50));
+ panel.add(getButton(), BorderLayout.CENTER);
+ panel.add(button1 = getButton(), BorderLayout.WEST);
+ panel.add(button2 = getButton(), BorderLayout.EAST);
+ frame.getContentPane().add(panel);
+ frame.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/8062561/bug8062561.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 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.awt.Robot;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JFileChooser;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileSystemView;
+import sun.awt.OSInfo;
+
+/**
+ * @test
+ * @bug 8062561
+ * @summary File system view returns null default directory
+ * @run main/othervm bug8062561 GENERATE_POLICY
+ * @run main/othervm/policy=security.policy bug8062561 CHECK_DEFAULT_DIR run
+ */
+public class bug8062561 {
+
+ private static final String POLICY_FILE = "security2.policy";
+ private static volatile boolean fileChooserIsShown = false;
+
+ public static void main(String[] args) throws Exception {
+
+ String test = args[0];
+
+ switch (test) {
+ case "GENERATE_POLICY":
+ generatePolicyFile();
+ break;
+ case "CHECK_DEFAULT_DIR":
+ checkDefaultDirectory();
+ break;
+ case "CHECK_FILE_CHOOSER":
+ checkFileChooser();
+ break;
+ default:
+ throw new RuntimeException("Wrong argument!");
+ }
+ }
+
+ private static void checkDefaultDirectory() {
+ if (System.getSecurityManager() == null) {
+ throw new RuntimeException("Security manager is not set!");
+ }
+
+ File defaultDirectory = FileSystemView.getFileSystemView().
+ getDefaultDirectory();
+ if (defaultDirectory != null) {
+ throw new RuntimeException("File system default directory is null!");
+ }
+ }
+ private static volatile JFileChooser fileChooser;
+
+ private static void checkFileChooser() throws Exception {
+ if (System.getSecurityManager() == null) {
+ throw new RuntimeException("Security manager is not set!");
+ }
+
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ public void run() {
+ fileChooser = new JFileChooser();
+ fileChooser.showOpenDialog(null);
+ fileChooserIsShown = true;
+ System.out.println("Start file chooser: " + fileChooserIsShown);
+ }
+ });
+
+ long time = System.currentTimeMillis();
+ while (fileChooser == null) {
+ if (System.currentTimeMillis() - time >= 10000) {
+ throw new RuntimeException("FileChoser is not shown!");
+ }
+ Thread.sleep(500);
+ }
+
+ Thread.sleep(500);
+ robot.keyPress(KeyEvent.VK_ESCAPE);
+ robot.keyRelease(KeyEvent.VK_ESCAPE);
+ System.exit(0);
+ }
+
+ private static void generatePolicyFile() throws Exception {
+ if (System.getSecurityManager() != null) {
+ throw new RuntimeException("Security manager should be null!");
+ }
+
+ if (!OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS)) {
+ return;
+ }
+
+ File defaultDirectory = FileSystemView.getFileSystemView().
+ getDefaultDirectory();
+
+ if (defaultDirectory == null) {
+ throw new RuntimeException("Default directory is null!");
+ }
+
+ File policyFile = new File(POLICY_FILE);
+ if (!policyFile.exists()) {
+ policyFile.createNewFile();
+ }
+
+ try (PrintWriter writer = new PrintWriter(policyFile, "UTF-8")) {
+ writer.println("grant {");
+ String documents = defaultDirectory.getCanonicalPath();
+ documents = documents.replace('\\', '/');
+ // Documents permission
+ writer.print(" permission java.io.FilePermission");
+ writer.print(" \"" + documents + "\",");
+ writer.println(" \"read\";");
+ // Desktop permission
+ writer.print(" permission java.io.FilePermission");
+ writer.print(" \"" + documents.replace("Documents", "Desktop") + "\",");
+ writer.println(" \"read\";");
+ // robot permission // "java.awt.AWTPermission" "createRobot"
+ writer.print(" permission java.awt.AWTPermission");
+ writer.println(" \"createRobot\";");
+ writer.println("};");
+ }
+
+ performTest();
+ }
+
+ private static void performTest() throws Exception {
+ String javaPath = System.getProperty("java.home", "");
+ String command = javaPath + File.separator + "bin" + File.separator + "java"
+ + " -Djava.security.manager -Djava.security.policy=" + POLICY_FILE
+ + " bug8062561 CHECK_FILE_CHOOSER";
+ System.out.println(command);
+ boolean processExit = false;
+
+ Process process = Runtime.getRuntime().exec(command);
+
+ try {
+ processExit = process.waitFor(20, TimeUnit.SECONDS);
+ } catch (IllegalThreadStateException e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("[RESULT] : "
+ + "The sub process has cleanly exited : PASS");
+
+ InputStream errorStream = process.getErrorStream();
+ System.out.println("========= Child process stderr ========");
+ boolean exception = dumpStream(errorStream);
+ if (exception) {
+ throw new RuntimeException("[RESULT] :"
+ + " Exception in child process : FAIL");
+ }
+ System.out.println("=======================================");
+
+ InputStream processInputStream = process.getInputStream();
+ System.out.println("========= Child process output ========");
+ dumpStream(processInputStream);
+ System.out.println("=======================================");
+
+ if (!processExit) {
+ process.destroy();
+ throw new RuntimeException("[RESULT] : "
+ + "The sub process has not exited : FAIL");
+ }
+ }
+
+ public static boolean dumpStream(InputStream in) throws IOException {
+ String tempString;
+ int count = in.available();
+ boolean exception = false;
+ while (count > 0) {
+ byte[] b = new byte[count];
+ in.read(b);
+ tempString = new String(b);
+ if (!exception) {
+ exception = tempString.indexOf("Exception") != -1;
+ }
+ System.out.println(tempString);
+ count = in.available();
+ }
+
+ return exception;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/8062561/security.policy Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,5 @@
+grant {
+
+ permission java.util.PropertyPermission "user.home", "read";
+ permission java.util.PropertyPermission "user.dir", "read";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/8062561/security2.policy Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,1 @@
+// Autogenerated file
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JToolTip/6219960/bug6219960.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 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.awt.Component;
+import java.awt.Container;
+import java.awt.GridLayout;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.AWTException;
+import java.awt.IllegalComponentStateException;
+import java.awt.event.InputEvent;
+import javax.swing.JButton;
+import javax.swing.JDesktopPane;
+import javax.swing.JFrame;
+import javax.swing.JInternalFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.ToolTipManager;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ * @test
+ * @bug 6219960
+ * @summary null reference in ToolTipManager
+ * @run main bug6219960
+ */
+public class bug6219960 {
+
+ private static final String QUESTION = "Question";
+
+ static volatile JFrame frame;
+ static JTable table;
+
+ public static void main(String[] args) throws Exception {
+ Robot robot = new Robot();
+ SwingUtilities.invokeAndWait(bug6219960::createAndShowGUI);
+ robot.waitForIdle();
+ showModal("The tooltip should be showing. Press ok with mouse. And don't move it.");
+ robot.waitForIdle();
+ showModal("Now press ok and move the mouse inside the table (don't leave it).");
+ robot.waitForIdle();
+ }
+
+ private static void createAndShowGUI() {
+ ToolTipManager.sharedInstance().setDismissDelay(10 * 60 * 1000);
+ frame = new JFrame();
+ frame.setLocation(20, 20);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ JDesktopPane desk = new JDesktopPane();
+ JInternalFrame iframe = new JInternalFrame();
+ iframe.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
+ desk.add(iframe);
+ JButton save = new JButton();
+ save.setToolTipText("Wait for dialog to show.");
+ save.setText("Wait for the tooltip to show.");
+ JPanel panel = new JPanel(new GridLayout(1, 2));
+ panel.add(save);
+ table = createTable();
+ panel.add(new JScrollPane(table));
+ iframe.setContentPane(panel);
+ frame.getContentPane().add(desk);
+ frame.setSize(800, 600);
+ iframe.setSize(640, 480);
+ iframe.validate();
+ iframe.setVisible(true);
+ frame.validate();
+ frame.setVisible(true);
+ try {
+ iframe.setSelected(true);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+
+ try {
+ Robot robot = new Robot();
+ Rectangle bounds = frame.getBounds();
+ int centerX = (int) (bounds.getX() + bounds.getWidth() / 6);
+ int centerY = (int) (bounds.getY() + bounds.getHeight() / 6);
+ robot.mouseMove(centerX, centerY);
+ } catch (AWTException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void showModal(final String msg) throws Exception {
+
+ new Thread(() -> {
+
+ int timeout = 3000;
+ long endTime = System.currentTimeMillis() + timeout;
+
+ while (System.currentTimeMillis() <= endTime) {
+ if (pressOK(frame)) {
+ return;
+ }
+ }
+ throw new RuntimeException("Internal frame has not been found!");
+ }).start();
+
+ Thread.sleep(900);
+
+ SwingUtilities.invokeAndWait(() -> {
+ JOptionPane.showInternalMessageDialog(table, msg,
+ QUESTION,
+ JOptionPane.PLAIN_MESSAGE);
+ });
+ }
+
+ private static JTable createTable() {
+ DefaultTableModel model = new DefaultTableModel();
+ JTable table = new JTable(model);
+ table.setFillsViewportHeight(true);
+ return table;
+ }
+
+ private static boolean pressOK(Component comp) {
+
+ JInternalFrame internalFrame
+ = findModalInternalFrame(comp, QUESTION);
+
+ if (internalFrame == null) {
+ return false;
+ }
+
+ JButton button = (JButton) findButton(internalFrame);
+
+ if (button == null) {
+ return false;
+ }
+
+ try {
+ Robot robot = new Robot();
+ Point location = button.getLocationOnScreen();
+ Rectangle bounds = button.getBounds();
+ int centerX = (int) (location.getX() + bounds.getWidth() / 2);
+ int centerY = (int) (location.getY() + bounds.getHeight() / 2);
+ robot.mouseMove(centerX, centerY);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ } catch (IllegalComponentStateException ignore) {
+ return false;
+ } catch (AWTException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+
+ private static JInternalFrame findModalInternalFrame(Component comp, String title) {
+
+ if (comp instanceof JInternalFrame) {
+ JInternalFrame internalFrame = (JInternalFrame) comp;
+ if (internalFrame.getTitle().equals(title)) {
+ return (JInternalFrame) comp;
+ }
+ }
+
+ if (comp instanceof Container) {
+ Container cont = (Container) comp;
+ for (int i = 0; i < cont.getComponentCount(); i++) {
+ JInternalFrame result = findModalInternalFrame(cont.getComponent(i), title);
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static JButton findButton(Component comp) {
+
+ if (comp instanceof JButton) {
+ return (JButton) comp;
+ }
+
+ if (comp instanceof Container) {
+ Container cont = (Container) comp;
+ for (int i = 0; i < cont.getComponentCount(); i++) {
+ JButton result = findButton(cont.getComponent(i));
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/UIDefaults/7180976/Pending.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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 javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+/**
+ * @test
+ * @bug 7180976
+ * @author Sergey Bylokhov
+ */
+public final class Pending implements Runnable {
+
+ private static volatile boolean passed;
+
+ public static void main(final String[] args) throws Exception {
+ SwingUtilities.invokeLater(new Pending());
+ Thread.sleep(10000);
+ if (!passed) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ @Override
+ public void run() {
+ UIManager.put("foobar", "Pending");
+ UIManager.get("foobar");
+ passed = true;
+ }
+}
\ No newline at end of file
--- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, 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,6 +45,7 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -67,7 +68,7 @@
*
* @test
* @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
- * 7157656 8002390 7012868 7012856 8015728 8038500 8040059
+ * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211
* @summary Test Zip filesystem provider
* @run main ZipFSTester
* @run main/othervm/java.security.policy=test.policy ZipFSTester
@@ -89,6 +90,7 @@
test2(fs); // more tests
}
testTime(jarFile);
+ test8069211();
}
static void test0(FileSystem fs)
@@ -416,6 +418,29 @@
Files.delete(fsPath);
}
+ static void test8069211() throws Exception {
+ // create a new filesystem, copy this file into it
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "true");
+ Path fsPath = getTempPath();
+ try (FileSystem fs = newZipFileSystem(fsPath, env);) {
+ OutputStream out = Files.newOutputStream(fs.getPath("/foo"));
+ out.write("hello".getBytes());
+ out.close();
+ out.close();
+ }
+ try (FileSystem fs = newZipFileSystem(fsPath, new HashMap<String, Object>())) {
+ if (!Arrays.equals(Files.readAllBytes(fs.getPath("/foo")),
+ "hello".getBytes())) {
+ throw new RuntimeException("entry close() failed");
+ }
+ } catch (Exception x) {
+ throw new RuntimeException("entry close() failed", x);
+ } finally {
+ Files.delete(fsPath);
+ }
+ }
+
private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
throws Exception
{
--- a/jdk/test/sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -48,14 +48,7 @@
static final File tmpFolder = new File(testClassesDir);
static {
- String javaHome = System.getProperty("java.home");
- if (javaHome.endsWith("jre")) {
- int index = javaHome.lastIndexOf(slash);
- if (index != -1)
- javaHome = javaHome.substring(0, index);
- }
-
- jar = javaHome + slash + "bin" + slash + "jar";
+ jar = System.getProperty("java.home") + slash + "bin" + slash + "jar";
}
public static void main(String[] args) throws Exception {
--- a/jdk/test/sun/misc/JarIndex/metaInfFilenames/Basic.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/Basic.java Wed Jul 05 20:15:59 2017 +0200
@@ -78,7 +78,6 @@
* URLClassLoader. Each request to the HTTP server is recorded to ensure
* only the correct amount of requests are being made.
*
- * Note: Needs jdk/lib/tools.jar in the classpath to compile and run.
*/
public class Basic {
@@ -160,14 +159,7 @@
static String jar;
static {
- String javaHome = System.getProperty("java.home");
- if (javaHome.endsWith("jre")) {
- int index = javaHome.lastIndexOf(slash);
- if (index != -1)
- javaHome = javaHome.substring(0, index);
- }
-
- jar = javaHome + slash+ "bin" + slash + "jar";
+ jar = System.getProperty("java.home") + slash+ "bin" + slash + "jar";
}
/* create the index */
--- a/jdk/test/sun/security/ec/TestEC.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ec/TestEC.java Wed Jul 05 20:15:59 2017 +0200
@@ -59,6 +59,10 @@
public class TestEC {
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
// MD5 is used in this test case, don't disable MD5 algorithm.
Security.setProperty(
"jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
--- a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, 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
@@ -43,6 +43,10 @@
private static String[] cmdArgs;
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
cmdArgs = args;
main(new ClientJSSEServerJSSE());
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014, 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 8047769
+ * @summary SecureRandom should be more frugal with file descriptors
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.Reference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Arrays;
+
+public class FileInputStreamPoolTest {
+
+ static final byte[] bytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
+
+ static void testCaching(File file) throws IOException {
+ InputStream in1 = TestProxy.FileInputStreamPool_getInputStream(file);
+ InputStream in2 = TestProxy.FileInputStreamPool_getInputStream(file);
+ assertTrue(in1 == in2,
+ "1st InputStream: " + in1 +
+ " is not same as 2nd: " + in2);
+
+ byte[] readBytes = new byte[bytes.length];
+ int nread = in1.read(readBytes);
+ assertTrue(bytes.length == nread,
+ "short read: " + nread +
+ " bytes of expected: " + bytes.length);
+ assertTrue(Arrays.equals(readBytes, bytes),
+ "readBytes: " + Arrays.toString(readBytes) +
+ " not equal to expected: " + Arrays.toString(bytes));
+ }
+
+ static void assertTrue(boolean test, String message) {
+ if (!test) {
+ throw new AssertionError(message);
+ }
+ }
+
+ static void processReferences() {
+ // make JVM process References
+ System.gc();
+ // help ReferenceHandler thread enqueue References
+ while (TestProxy.Reference_tryHandlePending(false)) {}
+ // help run Finalizers
+ System.runFinalization();
+ }
+
+ public static void main(String[] args) throws Exception {
+ // 1st create temporary file
+ File file = File.createTempFile("test", ".dat");
+ try (AutoCloseable acf = () -> {
+ // On Windows, failure to delete file is probably a consequence
+ // of the file still being opened - so the test should fail.
+ assertTrue(file.delete(),
+ "Can't delete: " + file + " (is it still open?)");
+ }) {
+ try (FileOutputStream out = new FileOutputStream(file)) {
+ out.write(bytes);
+ }
+
+ // test caching 1t time
+ testCaching(file);
+
+ processReferences();
+
+ // test caching 2nd time - this should only succeed if the stream
+ // is re-opened as a consequence of cleared WeakReference
+ testCaching(file);
+
+ processReferences();
+ }
+ }
+
+ /**
+ * A proxy for (package)private static methods:
+ * sun.security.provider.FileInputStreamPool.getInputStream
+ * java.lang.ref.Reference.tryHandlePending
+ */
+ static class TestProxy {
+ private static final Method getInputStreamMethod;
+ private static final Method tryHandlePendingMethod;
+
+ static {
+ try {
+ Class<?> fileInputStreamPoolClass =
+ Class.forName("sun.security.provider.FileInputStreamPool");
+ getInputStreamMethod =
+ fileInputStreamPoolClass.getDeclaredMethod(
+ "getInputStream", File.class);
+ getInputStreamMethod.setAccessible(true);
+
+ tryHandlePendingMethod = Reference.class.getDeclaredMethod(
+ "tryHandlePending", boolean.class);
+ tryHandlePendingMethod.setAccessible(true);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ static InputStream FileInputStreamPool_getInputStream(File file)
+ throws IOException {
+ try {
+ return (InputStream) getInputStreamMethod.invoke(null, file);
+ } catch (InvocationTargetException e) {
+ Throwable te = e.getTargetException();
+ if (te instanceof IOException) {
+ throw (IOException) te;
+ } else if (te instanceof RuntimeException) {
+ throw (RuntimeException) te;
+ } else if (te instanceof Error) {
+ throw (Error) te;
+ } else {
+ throw new UndeclaredThrowableException(te);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static boolean Reference_tryHandlePending(boolean waitForNotify) {
+ try {
+ return (boolean) tryHandlePendingMethod
+ .invoke(null, waitForNotify);
+ } catch (InvocationTargetException e) {
+ Throwable te = e.getTargetException();
+ if (te instanceof RuntimeException) {
+ throw (RuntimeException) te;
+ } else if (te instanceof Error) {
+ throw (Error) te;
+ } else {
+ throw new UndeclaredThrowableException(te);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/ClientHandshaker/LengthCheckTest.java Wed Jul 05 20:15:59 2017 +0200
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2015, 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 8044860
+ * @summary Vectors and fixed length fields should be verified
+ * for allowed sizes.
+ * @run main/othervm LengthCheckTest
+ */
+
+/**
+ * A SSLEngine usage example which simplifies the presentation
+ * by removing the I/O and multi-threading concerns.
+ *
+ * The test creates two SSLEngines, simulating a client and server.
+ * The "transport" layer consists two byte buffers: think of them
+ * as directly connected pipes.
+ *
+ * Note, this is a *very* simple example: real code will be much more
+ * involved. For example, different threading and I/O models could be
+ * used, transport mechanisms could close unexpectedly, and so on.
+ *
+ * When this application runs, notice that several messages
+ * (wrap/unwrap) pass before any application data is consumed or
+ * produced. (For more information, please see the SSL/TLS
+ * specifications.) There may several steps for a successful handshake,
+ * so it's typical to see the following series of operations:
+ *
+ * client server message
+ * ====== ====== =======
+ * wrap() ... ClientHello
+ * ... unwrap() ClientHello
+ * ... wrap() ServerHello/Certificate
+ * unwrap() ... ServerHello/Certificate
+ * wrap() ... ClientKeyExchange
+ * wrap() ... ChangeCipherSpec
+ * wrap() ... Finished
+ * ... unwrap() ClientKeyExchange
+ * ... unwrap() ChangeCipherSpec
+ * ... unwrap() Finished
+ * ... wrap() ChangeCipherSpec
+ * ... wrap() Finished
+ * unwrap() ... ChangeCipherSpec
+ * unwrap() ... Finished
+ */
+
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.security.*;
+import java.nio.*;
+import java.util.List;
+import java.util.ArrayList;
+import sun.security.ssl.ProtocolVersion;
+
+public class LengthCheckTest {
+
+ /*
+ * Enables logging of the SSLEngine operations.
+ */
+ private static final boolean logging = true;
+
+ /*
+ * Enables the JSSE system debugging system property:
+ *
+ * -Djavax.net.debug=all
+ *
+ * This gives a lot of low-level information about operations underway,
+ * including specific handshake messages, and might be best examined
+ * after gaining some familiarity with this application.
+ */
+ private static final boolean debug = false;
+ private static final boolean dumpBufs = true;
+
+ private final SSLContext sslc;
+
+ private SSLEngine clientEngine; // client Engine
+ private ByteBuffer clientOut; // write side of clientEngine
+ private ByteBuffer clientIn; // read side of clientEngine
+
+ private SSLEngine serverEngine; // server Engine
+ private ByteBuffer serverOut; // write side of serverEngine
+ private ByteBuffer serverIn; // read side of serverEngine
+
+ private HandshakeTest handshakeTest;
+
+ /*
+ * For data transport, this example uses local ByteBuffers. This
+ * isn't really useful, but the purpose of this example is to show
+ * SSLEngine concepts, not how to do network transport.
+ */
+ private ByteBuffer cTOs; // "reliable" transport client->server
+ private ByteBuffer sTOc; // "reliable" transport server->client
+
+ /*
+ * The following is to set up the keystores.
+ */
+ private static final String pathToStores = "../../../../javax/net/ssl/etc";
+ private static final String keyStoreFile = "keystore";
+ private static final String trustStoreFile = "truststore";
+ private static final String passwd = "passphrase";
+
+ private static final String keyFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ private static final String trustFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ // Define a few basic TLS record and message types we might need
+ private static final int TLS_RECTYPE_CCS = 0x14;
+ private static final int TLS_RECTYPE_ALERT = 0x15;
+ private static final int TLS_RECTYPE_HANDSHAKE = 0x16;
+ private static final int TLS_RECTYPE_APPDATA = 0x17;
+
+ private static final int TLS_HS_HELLO_REQUEST = 0x00;
+ private static final int TLS_HS_CLIENT_HELLO = 0x01;
+ private static final int TLS_HS_SERVER_HELLO = 0x02;
+ private static final int TLS_HS_CERTIFICATE = 0x0B;
+ private static final int TLS_HS_SERVER_KEY_EXCHG = 0x0C;
+ private static final int TLS_HS_CERT_REQUEST = 0x0D;
+ private static final int TLS_HS_SERVER_HELLO_DONE = 0x0E;
+ private static final int TLS_HS_CERT_VERIFY = 0x0F;
+ private static final int TLS_HS_CLIENT_KEY_EXCHG = 0x10;
+ private static final int TLS_HS_FINISHED = 0x14;
+
+ // We're not going to define all the alert types in TLS, just
+ // the ones we think we'll need to reference by name.
+ private static final int TLS_ALERT_LVL_WARNING = 0x01;
+ private static final int TLS_ALERT_LVL_FATAL = 0x02;
+
+ private static final int TLS_ALERT_UNEXPECTED_MSG = 0x0A;
+ private static final int TLS_ALERT_HANDSHAKE_FAILURE = 0x28;
+ private static final int TLS_ALERT_INTERNAL_ERROR = 0x50;
+
+ public interface HandshakeTest {
+ void execTest() throws Exception;
+ }
+
+ public final HandshakeTest servSendLongID = new HandshakeTest() {
+ @Override
+ public void execTest() throws Exception {
+ boolean gotException = false;
+ SSLEngineResult clientResult; // results from client's last op
+ SSLEngineResult serverResult; // results from server's last op
+
+ log("\n==== Test: Client receives 64-byte session ID ====");
+
+ // Send Client Hello
+ clientResult = clientEngine.wrap(clientOut, cTOs);
+ log("client wrap: ", clientResult);
+ runDelegatedTasks(clientResult, clientEngine);
+ cTOs.flip();
+ dumpByteBuffer("CLIENT-TO-SERVER", cTOs);
+
+ // Server consumes Client Hello
+ serverResult = serverEngine.unwrap(cTOs, serverIn);
+ log("server unwrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ cTOs.compact();
+
+ // Server generates ServerHello/Cert/Done record
+ serverResult = serverEngine.wrap(serverOut, sTOc);
+ log("server wrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ sTOc.flip();
+
+ // Intercept the ServerHello messages and instead send
+ // one that has a 64-byte session ID.
+ if (isTlsMessage(sTOc, TLS_RECTYPE_HANDSHAKE,
+ TLS_HS_SERVER_HELLO)) {
+ ArrayList<ByteBuffer> recList = splitRecord(sTOc);
+
+ // Use the original ServerHello as a template to craft one
+ // with a longer-than-allowed session ID.
+ ByteBuffer servHelloBuf =
+ createEvilServerHello(recList.get(0), 64);
+
+ recList.set(0, servHelloBuf);
+
+ // Now send each ByteBuffer (each being a complete
+ // TLS record) into the client-side unwrap.
+ for (ByteBuffer bBuf : recList) {
+ dumpByteBuffer("SERVER-TO-CLIENT", bBuf);
+ try {
+ clientResult = clientEngine.unwrap(bBuf, clientIn);
+ } catch (SSLProtocolException e) {
+ log("Received expected SSLProtocolException: " + e);
+ gotException = true;
+ }
+ log("client unwrap: ", clientResult);
+ runDelegatedTasks(clientResult, clientEngine);
+ }
+ } else {
+ dumpByteBuffer("SERVER-TO-CLIENT", sTOc);
+ log("client unwrap: ", clientResult);
+ runDelegatedTasks(clientResult, clientEngine);
+ }
+ sTOc.compact();
+
+ // The Client should now send a TLS Alert
+ clientResult = clientEngine.wrap(clientOut, cTOs);
+ log("client wrap: ", clientResult);
+ runDelegatedTasks(clientResult, clientEngine);
+ cTOs.flip();
+ dumpByteBuffer("CLIENT-TO-SERVER", cTOs);
+
+ // At this point we can verify that both an exception
+ // was thrown and the proper action (a TLS alert) was
+ // sent back to the server.
+ if (gotException == false ||
+ !isTlsMessage(cTOs, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR)) {
+ throw new SSLException(
+ "Client failed to throw Alert:fatal:internal_error");
+ }
+ }
+ };
+
+ public final HandshakeTest clientSendLongID = new HandshakeTest() {
+ @Override
+ public void execTest() throws Exception {
+ boolean gotException = false;
+ SSLEngineResult clientResult; // results from client's last op
+ SSLEngineResult serverResult; // results from server's last op
+
+ log("\n==== Test: Server receives 64-byte session ID ====");
+
+ // Send Client Hello
+ ByteBuffer evilClientHello = createEvilClientHello(64);
+ dumpByteBuffer("CLIENT-TO-SERVER", evilClientHello);
+
+ try {
+ // Server consumes Client Hello
+ serverResult = serverEngine.unwrap(evilClientHello, serverIn);
+ log("server unwrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ evilClientHello.compact();
+
+ // Under normal circumstances this should be a ServerHello
+ // But should throw an exception instead due to the invalid
+ // session ID.
+ serverResult = serverEngine.wrap(serverOut, sTOc);
+ log("server wrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ sTOc.flip();
+ dumpByteBuffer("SERVER-TO-CLIENT", sTOc);
+ } catch (SSLProtocolException ssle) {
+ log("Received expected SSLProtocolException: " + ssle);
+ gotException = true;
+ }
+
+ // We expect to see the server generate an alert here
+ serverResult = serverEngine.wrap(serverOut, sTOc);
+ log("server wrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ sTOc.flip();
+ dumpByteBuffer("SERVER-TO-CLIENT", sTOc);
+
+ // At this point we can verify that both an exception
+ // was thrown and the proper action (a TLS alert) was
+ // sent back to the client.
+ if (gotException == false ||
+ !isTlsMessage(sTOc, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR)) {
+ throw new SSLException(
+ "Server failed to throw Alert:fatal:internal_error");
+ }
+ }
+ };
+
+
+ /*
+ * Main entry point for this test.
+ */
+ public static void main(String args[]) throws Exception {
+ List<LengthCheckTest> ccsTests = new ArrayList<>();
+
+ if (debug) {
+ System.setProperty("javax.net.debug", "ssl");
+ }
+
+ ccsTests.add(new LengthCheckTest("ServSendLongID"));
+ ccsTests.add(new LengthCheckTest("ClientSendLongID"));
+
+ for (LengthCheckTest test : ccsTests) {
+ test.runTest();
+ }
+
+ System.out.println("Test Passed.");
+ }
+
+ /*
+ * Create an initialized SSLContext to use for these tests.
+ */
+ public LengthCheckTest(String testName) throws Exception {
+
+ KeyStore ks = KeyStore.getInstance("JKS");
+ KeyStore ts = KeyStore.getInstance("JKS");
+
+ char[] passphrase = "passphrase".toCharArray();
+
+ ks.load(new FileInputStream(keyFilename), passphrase);
+ ts.load(new FileInputStream(trustFilename), passphrase);
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ts);
+
+ SSLContext sslCtx = SSLContext.getInstance("TLS");
+
+ sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+ sslc = sslCtx;
+
+ switch (testName) {
+ case "ServSendLongID":
+ handshakeTest = servSendLongID;
+ break;
+ case "ClientSendLongID":
+ handshakeTest = clientSendLongID;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown test name: " +
+ testName);
+ }
+ }
+
+ /*
+ * Run the test.
+ *
+ * Sit in a tight loop, both engines calling wrap/unwrap regardless
+ * of whether data is available or not. We do this until both engines
+ * report back they are closed.
+ *
+ * The main loop handles all of the I/O phases of the SSLEngine's
+ * lifetime:
+ *
+ * initial handshaking
+ * application data transfer
+ * engine closing
+ *
+ * One could easily separate these phases into separate
+ * sections of code.
+ */
+ private void runTest() throws Exception {
+ boolean dataDone = false;
+
+ createSSLEngines();
+ createBuffers();
+
+ handshakeTest.execTest();
+ }
+
+ /*
+ * Using the SSLContext created during object creation,
+ * create/configure the SSLEngines we'll use for this test.
+ */
+ private void createSSLEngines() throws Exception {
+ /*
+ * Configure the serverEngine to act as a server in the SSL/TLS
+ * handshake. Also, require SSL client authentication.
+ */
+ serverEngine = sslc.createSSLEngine();
+ serverEngine.setUseClientMode(false);
+ serverEngine.setNeedClientAuth(false);
+
+ /*
+ * Similar to above, but using client mode instead.
+ */
+ clientEngine = sslc.createSSLEngine("client", 80);
+ clientEngine.setUseClientMode(true);
+
+ // In order to make a test that will be backwards compatible
+ // going back to JDK 5, force the handshake to be TLS 1.0 and
+ // use one of the older cipher suites.
+ clientEngine.setEnabledProtocols(new String[]{"TLSv1"});
+ clientEngine.setEnabledCipherSuites(
+ new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA"});
+ }
+
+ /*
+ * Create and size the buffers appropriately.
+ */
+ private void createBuffers() {
+
+ /*
+ * We'll assume the buffer sizes are the same
+ * between client and server.
+ */
+ SSLSession session = clientEngine.getSession();
+ int appBufferMax = session.getApplicationBufferSize();
+ int netBufferMax = session.getPacketBufferSize();
+
+ /*
+ * We'll make the input buffers a bit bigger than the max needed
+ * size, so that unwrap()s following a successful data transfer
+ * won't generate BUFFER_OVERFLOWS.
+ *
+ * We'll use a mix of direct and indirect ByteBuffers for
+ * tutorial purposes only. In reality, only use direct
+ * ByteBuffers when they give a clear performance enhancement.
+ */
+ clientIn = ByteBuffer.allocate(appBufferMax + 50);
+ serverIn = ByteBuffer.allocate(appBufferMax + 50);
+
+ cTOs = ByteBuffer.allocateDirect(netBufferMax);
+ sTOc = ByteBuffer.allocateDirect(netBufferMax);
+
+ clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
+ serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());
+ }
+
+ /*
+ * If the result indicates that we have outstanding tasks to do,
+ * go ahead and run them in this thread.
+ */
+ private static void runDelegatedTasks(SSLEngineResult result,
+ SSLEngine engine) throws Exception {
+
+ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable runnable;
+ while ((runnable = engine.getDelegatedTask()) != null) {
+ log("\trunning delegated task...");
+ runnable.run();
+ }
+ HandshakeStatus hsStatus = engine.getHandshakeStatus();
+ if (hsStatus == HandshakeStatus.NEED_TASK) {
+ throw new Exception(
+ "handshake shouldn't need additional tasks");
+ }
+ log("\tnew HandshakeStatus: " + hsStatus);
+ }
+ }
+
+ private static boolean isEngineClosed(SSLEngine engine) {
+ return (engine.isOutboundDone() && engine.isInboundDone());
+ }
+
+ /*
+ * Simple check to make sure everything came across as expected.
+ */
+ private static void checkTransfer(ByteBuffer a, ByteBuffer b)
+ throws Exception {
+ a.flip();
+ b.flip();
+
+ if (!a.equals(b)) {
+ throw new Exception("Data didn't transfer cleanly");
+ } else {
+ log("\tData transferred cleanly");
+ }
+
+ a.position(a.limit());
+ b.position(b.limit());
+ a.limit(a.capacity());
+ b.limit(b.capacity());
+ }
+
+ /*
+ * Logging code
+ */
+ private static boolean resultOnce = true;
+
+ private static void log(String str, SSLEngineResult result) {
+ if (!logging) {
+ return;
+ }
+ if (resultOnce) {
+ resultOnce = false;
+ System.out.println("The format of the SSLEngineResult is: \n" +
+ "\t\"getStatus() / getHandshakeStatus()\" +\n" +
+ "\t\"bytesConsumed() / bytesProduced()\"\n");
+ }
+ HandshakeStatus hsStatus = result.getHandshakeStatus();
+ log(str +
+ result.getStatus() + "/" + hsStatus + ", " +
+ result.bytesConsumed() + "/" + result.bytesProduced() +
+ " bytes");
+ if (hsStatus == HandshakeStatus.FINISHED) {
+ log("\t...ready for application data");
+ }
+ }
+
+ private static void log(String str) {
+ if (logging) {
+ System.out.println(str);
+ }
+ }
+
+ /**
+ * Split a record consisting of multiple TLS handshake messages
+ * into individual TLS records, each one in a ByteBuffer of its own.
+ *
+ * @param tlsRecord A ByteBuffer containing the tls record data.
+ * The position of the buffer should be at the first byte
+ * in the TLS record data.
+ *
+ * @return An ArrayList consisting of one or more ByteBuffers. Each
+ * ByteBuffer will contain a single TLS record with one message.
+ * That message will be taken from the input record. The order
+ * of the messages in the ArrayList will be the same as they
+ * were in the input record.
+ */
+ private ArrayList<ByteBuffer> splitRecord(ByteBuffer tlsRecord) {
+ SSLSession session = clientEngine.getSession();
+ int netBufferMax = session.getPacketBufferSize();
+ ArrayList<ByteBuffer> recordList = new ArrayList<>();
+
+ if (tlsRecord.hasRemaining()) {
+ int type = Byte.toUnsignedInt(tlsRecord.get());
+ byte ver_major = tlsRecord.get();
+ byte ver_minor = tlsRecord.get();
+ int recLen = Short.toUnsignedInt(tlsRecord.getShort());
+ byte[] newMsgData = null;
+ while (tlsRecord.hasRemaining()) {
+ ByteBuffer newRecord = ByteBuffer.allocateDirect(netBufferMax);
+ switch (type) {
+ case TLS_RECTYPE_CCS:
+ case TLS_RECTYPE_ALERT:
+ case TLS_RECTYPE_APPDATA:
+ // None of our tests have multiple non-handshake
+ // messages coalesced into a single record.
+ break;
+ case TLS_RECTYPE_HANDSHAKE:
+ newMsgData = getHandshakeMessage(tlsRecord);
+ break;
+ }
+
+ // Put a new TLS record on the destination ByteBuffer
+ newRecord.put((byte)type);
+ newRecord.put(ver_major);
+ newRecord.put(ver_minor);
+ newRecord.putShort((short)newMsgData.length);
+
+ // Now add the message content itself and attach to the
+ // returned ArrayList
+ newRecord.put(newMsgData);
+ newRecord.flip();
+ recordList.add(newRecord);
+ }
+ }
+
+ return recordList;
+ }
+
+ private static ByteBuffer createEvilClientHello(int sessIdLen) {
+ ByteBuffer newRecord = ByteBuffer.allocateDirect(4096);
+
+ // Lengths will initially be place holders until we determine the
+ // finished length of the ByteBuffer. Then we'll go back and scribble
+ // in the correct lengths.
+
+ newRecord.put((byte)TLS_RECTYPE_HANDSHAKE); // Record type
+ newRecord.putShort((short)0x0301); // Protocol (TLS 1.0)
+ newRecord.putShort((short)0); // Length place holder
+
+ newRecord.putInt(TLS_HS_CLIENT_HELLO << 24); // HS type and length
+ newRecord.putShort((short)0x0301);
+ newRecord.putInt((int)(System.currentTimeMillis() / 1000));
+ SecureRandom sr = new SecureRandom();
+ byte[] randBuf = new byte[28];
+ sr.nextBytes(randBuf);
+ newRecord.put(randBuf); // Client Random
+ newRecord.put((byte)sessIdLen); // Session ID length
+ if (sessIdLen > 0) {
+ byte[] sessId = new byte[sessIdLen];
+ sr.nextBytes(sessId);
+ newRecord.put(sessId); // Session ID
+ }
+ newRecord.putShort((short)2); // 2 bytes of ciphers
+ newRecord.putShort((short)0x002F); // TLS_RSA_AES_CBC_SHA
+ newRecord.putShort((short)0x0100); // only null compression
+ newRecord.putShort((short)5); // 5 bytes of extensions
+ newRecord.putShort((short)0xFF01); // Renegotiation info
+ newRecord.putShort((short)1);
+ newRecord.put((byte)0); // No reneg info exts
+
+ // Go back and fill in the correct length values for the record
+ // and handshake message headers.
+ int recordLength = newRecord.position();
+ newRecord.putShort(3, (short)(recordLength - 5));
+ int newTypeAndLen = (newRecord.getInt(5) & 0xFF000000) |
+ ((recordLength - 9) & 0x00FFFFFF);
+ newRecord.putInt(5, newTypeAndLen);
+
+ newRecord.flip();
+ return newRecord;
+ }
+
+ private static ByteBuffer createEvilServerHello(ByteBuffer origHello,
+ int newSessIdLen) {
+ if (newSessIdLen < 0 || newSessIdLen > Byte.MAX_VALUE) {
+ throw new RuntimeException("Length must be 0 <= X <= 127");
+ }
+
+ ByteBuffer newRecord = ByteBuffer.allocateDirect(4096);
+ // Copy the bytes from the old hello to the new up to the session ID
+ // field. We will go back later and fill in a new length field in
+ // the record header. This includes the record header (5 bytes), the
+ // Handshake message header (4 bytes), protocol version (2 bytes),
+ // and the random (32 bytes).
+ ByteBuffer scratchBuffer = origHello.slice();
+ scratchBuffer.limit(43);
+ newRecord.put(scratchBuffer);
+
+ // Advance the position in the originial hello buffer past the
+ // session ID.
+ origHello.position(43);
+ int origIDLen = Byte.toUnsignedInt(origHello.get());
+ if (origIDLen > 0) {
+ // Skip over the session ID
+ origHello.position(origHello.position() + origIDLen);
+ }
+
+ // Now add our own sessionID to the new record
+ SecureRandom sr = new SecureRandom();
+ byte[] sessId = new byte[newSessIdLen];
+ sr.nextBytes(sessId);
+ newRecord.put((byte)newSessIdLen);
+ newRecord.put(sessId);
+
+ // Create another slice in the original buffer, based on the position
+ // past the session ID. Copy the remaining bytes into the new
+ // hello buffer. Then go back and fix up the length
+ newRecord.put(origHello.slice());
+
+ // Go back and fill in the correct length values for the record
+ // and handshake message headers.
+ int recordLength = newRecord.position();
+ newRecord.putShort(3, (short)(recordLength - 5));
+ int newTypeAndLen = (newRecord.getInt(5) & 0xFF000000) |
+ ((recordLength - 9) & 0x00FFFFFF);
+ newRecord.putInt(5, newTypeAndLen);
+
+ newRecord.flip();
+ return newRecord;
+ }
+
+ /**
+ * Look at an incoming TLS record and see if it is the desired
+ * record type, and where appropriate the correct subtype.
+ *
+ * @param srcRecord The input TLS record to be evaluated. This
+ * method will only look at the leading message if multiple
+ * TLS handshake messages are coalesced into a single record.
+ * @param reqRecType The requested TLS record type
+ * @param recParams Zero or more integer sub type fields. For CCS
+ * and ApplicationData, no params are used. For handshake records,
+ * one value corresponding to the HandshakeType is required.
+ * For Alerts, two values corresponding to AlertLevel and
+ * AlertDescription are necessary.
+ *
+ * @return true if the proper handshake message is the first one
+ * in the input record, false otherwise.
+ */
+ private boolean isTlsMessage(ByteBuffer srcRecord, int reqRecType,
+ int... recParams) {
+ boolean foundMsg = false;
+
+ if (srcRecord.hasRemaining()) {
+ srcRecord.mark();
+
+ // Grab the fields from the TLS Record
+ int recordType = Byte.toUnsignedInt(srcRecord.get());
+ byte ver_major = srcRecord.get();
+ byte ver_minor = srcRecord.get();
+ int recLen = Short.toUnsignedInt(srcRecord.getShort());
+
+ if (recordType == reqRecType) {
+ // For any zero-length recParams, making sure the requested
+ // type is sufficient.
+ if (recParams.length == 0) {
+ foundMsg = true;
+ } else {
+ switch (recordType) {
+ case TLS_RECTYPE_CCS:
+ case TLS_RECTYPE_APPDATA:
+ // We really shouldn't find ourselves here, but
+ // if someone asked for these types and had more
+ // recParams we can ignore them.
+ foundMsg = true;
+ break;
+ case TLS_RECTYPE_ALERT:
+ // Needs two params, AlertLevel and AlertDescription
+ if (recParams.length != 2) {
+ throw new RuntimeException(
+ "Test for Alert requires level and desc.");
+ } else {
+ int level = Byte.toUnsignedInt(srcRecord.get());
+ int desc = Byte.toUnsignedInt(srcRecord.get());
+ if (level == recParams[0] &&
+ desc == recParams[1]) {
+ foundMsg = true;
+ }
+ }
+ break;
+ case TLS_RECTYPE_HANDSHAKE:
+ // Needs one parameter, HandshakeType
+ if (recParams.length != 1) {
+ throw new RuntimeException(
+ "Test for Handshake requires only HS type");
+ } else {
+ // Go into the first handhshake message in the
+ // record and grab the handshake message header.
+ // All we need to do is parse out the leading
+ // byte.
+ int msgHdr = srcRecord.getInt();
+ int msgType = (msgHdr >> 24) & 0x000000FF;
+ if (msgType == recParams[0]) {
+ foundMsg = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ srcRecord.reset();
+ }
+
+ return foundMsg;
+ }
+
+ private byte[] getHandshakeMessage(ByteBuffer srcRecord) {
+ // At the start of this routine, the position should be lined up
+ // at the first byte of a handshake message. Mark this location
+ // so we can return to it after reading the type and length.
+ srcRecord.mark();
+ int msgHdr = srcRecord.getInt();
+ int type = (msgHdr >> 24) & 0x000000FF;
+ int length = msgHdr & 0x00FFFFFF;
+
+ // Create a byte array that has enough space for the handshake
+ // message header and body.
+ byte[] data = new byte[length + 4];
+ srcRecord.reset();
+ srcRecord.get(data, 0, length + 4);
+
+ return (data);
+ }
+
+ /**
+ * Hex-dumps a ByteBuffer to stdout.
+ */
+ private static void dumpByteBuffer(String header, ByteBuffer bBuf) {
+ if (dumpBufs == false) {
+ return;
+ }
+
+ int bufLen = bBuf.remaining();
+ if (bufLen > 0) {
+ bBuf.mark();
+
+ // We expect the position of the buffer to be at the
+ // beginning of a TLS record. Get the type, version and length.
+ int type = Byte.toUnsignedInt(bBuf.get());
+ int ver_major = Byte.toUnsignedInt(bBuf.get());
+ int ver_minor = Byte.toUnsignedInt(bBuf.get());
+ int recLen = Short.toUnsignedInt(bBuf.getShort());
+ ProtocolVersion pv = ProtocolVersion.valueOf(ver_major, ver_minor);
+
+ log("===== " + header + " (" + tlsRecType(type) + " / " +
+ pv + " / " + bufLen + " bytes) =====");
+ bBuf.reset();
+ for (int i = 0; i < bufLen; i++) {
+ if (i != 0 && i % 16 == 0) {
+ System.out.print("\n");
+ }
+ System.out.format("%02X ", bBuf.get(i));
+ }
+ log("\n===============================================");
+ bBuf.reset();
+ }
+ }
+
+ private static String tlsRecType(int type) {
+ switch (type) {
+ case 20:
+ return "Change Cipher Spec";
+ case 21:
+ return "Alert";
+ case 22:
+ return "Handshake";
+ case 23:
+ return "Application Data";
+ default:
+ return ("Unknown (" + type + ")");
+ }
+ }
+}
--- a/jdk/test/sun/security/ssl/ProtocolVersion/HttpsProtocols.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ssl/ProtocolVersion/HttpsProtocols.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, 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
@@ -32,6 +32,7 @@
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
+import java.security.Security;
public class HttpsProtocols implements HostnameVerifier {
@@ -177,6 +178,10 @@
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
String keyFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + keyStoreFile;
--- a/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedDefaultProtocols.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedDefaultProtocols.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -35,6 +35,7 @@
import javax.net.*;
import javax.net.ssl.*;
import java.util.Arrays;
+import java.security.Security;
public class CustomizedDefaultProtocols {
static enum ContextVersion {
@@ -93,6 +94,10 @@
}
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
boolean failed = false;
for (ContextVersion cv : ContextVersion.values()) {
System.out.println("Checking SSLContext of " + cv.contextVersion);
--- a/jdk/test/sun/security/ssl/SSLContextImpl/DefaultEnabledProtocols.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/DefaultEnabledProtocols.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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,6 +34,7 @@
import javax.net.*;
import javax.net.ssl.*;
import java.util.Arrays;
+import java.security.Security;
public class DefaultEnabledProtocols {
static enum ContextVersion {
@@ -92,6 +93,10 @@
}
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
boolean failed = false;
for (ContextVersion cv : ContextVersion.values()) {
System.out.println("Checking SSLContext of " + cv.contextVersion);
--- a/jdk/test/sun/security/ssl/SSLContextImpl/NoOldVersionContext.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/NoOldVersionContext.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -35,6 +35,7 @@
import javax.net.*;
import javax.net.ssl.*;
import java.util.Arrays;
+import java.security.Security;
public class NoOldVersionContext {
static enum ContextVersion {
@@ -93,6 +94,10 @@
}
public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
boolean failed = false;
for (ContextVersion cv : ContextVersion.values()) {
System.out.println("Checking SSLContext of " + cv.contextVersion);
--- a/jdk/test/sun/security/ssl/SSLEngineImpl/DelegatedTaskWrongException.java Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/DelegatedTaskWrongException.java Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -115,6 +115,9 @@
}
public static void main(String args[]) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
DelegatedTaskWrongException test;
--- a/jdk/test/sun/security/tools/policytool/i18n.sh Sat Jan 24 23:23:06 2015 -0800
+++ b/jdk/test/sun/security/tools/policytool/i18n.sh Wed Jul 05 20:15:59 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2015, 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
@@ -83,8 +83,9 @@
exit 1
fi
+# The keystore type is set to JKS, to match the type expected by i18n.html
${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkeypair -alias hello -dname CN=Hello \
- -storepass changeit -keypass changeit -keystore ks
+ -storepass changeit -keypass changeit -keystore ks -storetype jks
echo changeit > good
echo badpass > bad
${TESTJAVA}${FS}bin${FS}policytool ${TESTTOOLVMOPTS}
--- a/modules.xml Sat Jan 24 23:23:06 2015 -0800
+++ b/modules.xml Wed Jul 05 20:15:59 2017 +0200
@@ -737,7 +737,7 @@
</export>
<export>
<name>sun.awt</name>
- <to>oracle.accessbridge</to>
+ <to>jdk.accessbridge</to>
</export>
</module>
<module>